merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-10-26 10:57:35 +01:00
commit 758c43af6b
593 changed files with 13908 additions and 5690 deletions

View File

@ -0,0 +1,73 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<div id="mw_b">
<div id="mw_f">
<div id="mw_g" style="display: none;"/>
</div>
</div>
<div id="mw_c" style="display: none;">
<div id="mw_d">
<div id="mw_e"></div>
</div>
</div>
<input id="mw_a"/>
<script>
function dumpAccessibleNode(aNode, level) {
var msg = "";
try {
msg += "name=\"" + aNode.name + "\" ";
} catch (e) {
msg += " noName ";
}
dump(msg + '\n');
}
function dumpAccessibleTree(aNode, level) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
level = level || 0;
dumpAccessibleNode(aNode, level);
try {
var child = aNode.firstChild;
while (child) {
dumpAccessibleTree(child, level + 1);
child = child.nextSibling;
}
} catch (e) {
dump("Error visiting child nodes: " + e + '\n');
}
}
function A(o) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var acc = Components.classes['@mozilla.org/accessibleRetrieval;1']
.getService(Components.interfaces.nsIAccessibleRetrieval);
return acc.getAccessibleFor(o);
}
function beginAccessible() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
dumpAccessibleTree(A(document),0);
}
setTimeout(beginAccessible, 100);
setTimeout(doe, 200);
function doe() {
document.getElementById('mw_a').appendChild(document.getElementById('mw_b'));
document.getElementById('mw_c').appendChild(document.getElementById('mw_d'));
document.getElementById('mw_e').appendChild(document.getElementById('mw_f'));
document.getElementById('mw_g').appendChild(document.getElementById('mw_b'));
}
</script>
</body>
</html>

View File

@ -1,2 +1,3 @@
# Disabled because it causes assertions/crashes in later crashtests, see bug 918246
# Disabled because they cause assertions/crashes in later crashtests, see bug 918246
skip load 448064.xhtml
skip load 471493.xul

View File

@ -485,7 +485,7 @@ exports["test:setInterval async Errors passed to .onError"] = WorkerTest(
onError: function(err) {
count++;
assert.equal(err.message, "ubik",
"error (corectly) propagated " + count + " time(s)");
"error (correctly) propagated " + count + " time(s)");
if (count >= 3) done();
}
});

View File

@ -477,7 +477,7 @@ exports["test:setInterval async Errors passed to .onError"] = WorkerTest(
onError: function(err) {
count++;
assert.equal(err.message, "ubik",
"error (corectly) propagated " + count + " time(s)");
"error (correctly) propagated " + count + " time(s)");
if (count >= 3) done();
}
});

View File

@ -485,7 +485,7 @@ exports["test:setInterval async Errors passed to .onError"] = WorkerTest(
onError: function(err) {
count++;
assert.equal(err.message, "ubik",
"error (corectly) propagated " + count + " time(s)");
"error (correctly) propagated " + count + " time(s)");
if (count >= 3) done();
}
});

View File

@ -431,7 +431,7 @@ UpdatePrompt.prototype = {
sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
let detail = {};
for each (let property in this._copyProperties) {
for (let property of this._copyProperties) {
detail[property] = aUpdate[property];
}

View File

@ -1645,6 +1645,8 @@ pref("dom.serviceWorkers.interception.enabled", true);
// Enable Push API.
pref("dom.push.enabled", true);
pref("dom.serviceWorkers.openWindow.enabled", true);
#endif
// These are the thumbnail width/height set in about:newtab.

View File

@ -319,26 +319,6 @@
orient="horizontal"
hidden="true"/>
<menupopup id="processHangOptions"
onpopupshowing="ProcessHangMonitor.refreshMenu(window);">
<menuitem id="processHangTerminateScript"
oncommand="ProcessHangMonitor.terminateScript(window)"
accesskey="&processHang.terminateScript.accessKey;"
label="&processHang.terminateScript.label;"/>
<menuitem id="processHangDebugScript"
oncommand="ProcessHangMonitor.debugScript(window)"
accesskey="&processHang.debugScript.accessKey;"
label="&processHang.debugScript.label;"/>
<menuitem id="processHangTerminatePlugin"
oncommand="ProcessHangMonitor.terminatePlugin(window)"
accesskey="&processHang.terminatePlugin.accessKey;"
label="&processHang.terminatePlugin.label;"/>
<menuitem id="processHangTerminateProcess"
oncommand="ProcessHangMonitor.terminateProcess(window)"
accesskey="&processHang.terminateProcess.accessKey;"
label="&processHang.terminateProcess.label;"/>
</menupopup>
<menupopup id="toolbar-context-menu"
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"

View File

@ -1,4 +1,8 @@
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/browser/config/mozconfigs/linux32/common-opt"

View File

@ -2,6 +2,11 @@
# safeguard below
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/browser/config/mozconfigs/linux32/common-opt"
ac_add_options --enable-official-branding

View File

@ -1,4 +1,8 @@
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"

View File

@ -2,6 +2,11 @@
# safeguard below
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
ac_add_options --enable-official-branding

View File

@ -1,5 +1,10 @@
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/common-opt"
ac_add_options --enable-official-branding

View File

@ -2,6 +2,11 @@
# safeguard below
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/browser/config/mozconfigs/macosx-universal/common-opt"
ac_add_options --enable-official-branding

View File

@ -73,6 +73,10 @@ for platform in all_platforms:
'ac_add_options --enable-official-branding',
'mk_add_options MOZ_MAKE_FLAGS="-j4"',
'export BUILDING_RELEASE=1',
'if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then',
'MOZ_AUTOMATION_UPLOAD_SYMBOLS=1',
'MOZ_AUTOMATION_UPDATE_PACKAGING=1',
'fi',
'MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}',
]
whitelist['release']['win32'] += ['mk_add_options MOZ_PGO=1']

View File

@ -1,5 +1,10 @@
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/build/mozconfig.win-common"
. "$topsrcdir/browser/config/mozconfigs/win32/common-opt"

View File

@ -2,6 +2,11 @@
# safeguard below
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/build/mozconfig.win-common"
. "$topsrcdir/browser/config/mozconfigs/win32/common-opt"

View File

@ -1,5 +1,10 @@
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/build/mozconfig.win-common"
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"

View File

@ -2,6 +2,11 @@
# safeguard below
MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
if [ -n "$ENABLE_RELEASE_PROMOTION" ]; then
MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
MOZ_AUTOMATION_UPDATE_PACKAGING=1
fi
. "$topsrcdir/build/mozconfig.win-common"
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"

View File

@ -925,15 +925,6 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY panicButton.thankyou.msg2 "Safe browsing!">
<!ENTITY panicButton.thankyou.buttonlabel "Thanks!">
<!ENTITY processHang.terminateScript.label "Stop Script">
<!ENTITY processHang.terminateScript.accessKey "S">
<!ENTITY processHang.debugScript.label "Debug Script">
<!ENTITY processHang.debugScript.accessKey "D">
<!ENTITY processHang.terminatePlugin.label "Kill Plugin">
<!ENTITY processHang.terminatePlugin.accessKey "P">
<!ENTITY processHang.terminateProcess.label "Kill Web Process">
<!ENTITY processHang.terminateProcess.accessKey "K">
<!ENTITY emeLearnMoreContextMenu.label "Learn more about DRM…">
<!ENTITY emeLearnMoreContextMenu.accesskey "D">
<!ENTITY emeNotificationsNotNow.label "Not now">

View File

@ -472,9 +472,13 @@ dataReportingNotification.button.label = Choose What I Share
dataReportingNotification.button.accessKey = C
# Process hang reporter
processHang.message = A web page is causing %1$S to run slowly. What would you like to do?
processHang.button.label = Options
processHang.button.accessKey = O
processHang.label = A web page is slowing down your browser. What would you like to do?
processHang.button_stop.label = Stop It
processHang.button_stop.accessKey = S
processHang.button_wait.label = Wait
processHang.button_wait.accessKey = W
processHang.button_debug.label = Debug Script
processHang.button_debug.accessKey = D
# Webapps notification popup
webapps.install = Install

View File

@ -19,13 +19,31 @@ Cu.import("resource://gre/modules/Services.jsm");
* the platform interface.
*/
/**
* If a hang hasn't been reported for more than 10 seconds, assume the
* content process has gotten unstuck (and hide the hang notification).
*/
const HANG_EXPIRATION_TIME = 10000;
var ProcessHangMonitor = {
/**
* If a hang hasn't been reported for more than 10 seconds, assume the
* content process has gotten unstuck (and hide the hang notification).
*/
get HANG_EXPIRATION_TIME() {
try {
return Services.prefs.getIntPref("browser.hangNotification.expiration");
} catch (ex) {
return 10000;
}
},
/**
* This timeout is the wait period applied after a user selects "Wait" in
* an existing notification.
*/
get WAIT_EXPIRATION_TIME() {
try {
return Services.prefs.getIntPref("browser.hangNotification.waitPeriod");
} catch (ex) {
return 10000;
}
},
/**
* Collection of hang reports that haven't expired or been dismissed
* by the user. The keys are nsIHangReports and values keys are
@ -34,6 +52,12 @@ var ProcessHangMonitor = {
*/
_activeReports: new Map(),
/**
* Collection of hang reports that have been suppressed for a
* short period of time.
*/
_pausedReports: new Map(),
/**
* Initialize hang reporting. Called once in the parent process.
*/
@ -70,46 +94,78 @@ var ProcessHangMonitor = {
},
/**
* Kill the plugin process causing the hang being reported for the
* selected browser in |win|.
* Terminate the plugin process associated with a hang being reported
* for the selected browser in |win|. Will attempt to generate a combined
* crash report for all processes.
*/
terminatePlugin: function(win) {
this.handleUserInput(win, report => report.terminatePlugin());
},
/**
* Kill the content process causing the hang being reported for the selected
* browser in |win|.
* Dismiss the browser notification and invoke an appropriate action based on
* the hang type.
*/
terminateProcess: function(win) {
this.handleUserInput(win, report => report.terminateProcess());
},
/**
* Update the "Options" pop-up menu for the hang notification
* associated with the selected browser in |win|. The menu should
* display only options that are relevant to the given report.
*/
refreshMenu: function(win) {
let report = this.findReport(win.gBrowser.selectedBrowser);
stopIt: function (win) {
let report = this.findActiveReport(win.gBrowser.selectedBrowser);
if (!report) {
return;
}
function setVisible(id, visible) {
let item = win.document.getElementById(id);
item.hidden = !visible;
switch (report.hangType) {
case report.SLOW_SCRIPT:
this.terminateScript(win);
break;
case report.PLUGIN_HANG:
this.terminatePlugin(win);
break;
}
},
if (report.hangType == report.SLOW_SCRIPT) {
setVisible("processHangTerminateScript", true);
setVisible("processHangDebugScript", true);
setVisible("processHangTerminatePlugin", false);
} else if (report.hangType == report.PLUGIN_HANG) {
setVisible("processHangTerminateScript", false);
setVisible("processHangDebugScript", false);
setVisible("processHangTerminatePlugin", true);
/**
* Dismiss the notification, clear the report from the active list and set up
* a new timer to track a wait period during which we won't notify.
*/
waitLonger: function(win) {
let report = this.findActiveReport(win.gBrowser.selectedBrowser);
if (!report) {
return;
}
// Remove the report from the active list and cancel its timer.
this.removeActiveReport(report);
// NOTE, we didn't call userCanceled on nsIHangReport here. This insures
// we don't repeatedly generate and cache crash report data for this hang
// in the process hang reporter. It already has one report for the browser
// process we want it hold onto.
// Create a new wait timer with notify callback
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(() => {
for (let [stashedReport, otherTimer] of this._pausedReports) {
if (otherTimer === timer) {
this.removePausedReport(stashedReport);
// Create a new notification display timeout timer
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(this, this.HANG_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
// Store the timer in the active reports map. If we receive a new
// observer notification for this hang, we'll redisplay the browser
// notification in reportHang below. If we do not receive a new
// observer, timer will take care of cleaning up resources associated
// with this hang. The observer for active hangs fires about once
// a second.
this._activeReports.set(report, timer);
break;
}
}
}, this.WAIT_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
this._pausedReports.set(report, timer);
// remove the browser notification associated with this hang
this.updateWindows();
},
/**
@ -118,11 +174,11 @@ var ProcessHangMonitor = {
* about it.
*/
handleUserInput: function(win, func) {
let report = this.findReport(win.gBrowser.selectedBrowser);
let report = this.findActiveReport(win.gBrowser.selectedBrowser);
if (!report) {
return;
}
this.removeReport(report);
this.removeActiveReport(report);
return func(report);
},
@ -153,9 +209,9 @@ var ProcessHangMonitor = {
},
/**
* Find any active hang reports for the given <browser> element.
* Find a active hang report for the given <browser> element.
*/
findReport: function(browser) {
findActiveReport: function(browser) {
let frameLoader = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
for (let [report, timer] of this._activeReports) {
if (report.isReportForBrowser(frameLoader)) {
@ -165,6 +221,44 @@ var ProcessHangMonitor = {
return null;
},
/**
* Find a paused hang report for the given <browser> element.
*/
findPausedReport: function(browser) {
let frameLoader = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
for (let [report, timer] of this._pausedReports) {
if (report.isReportForBrowser(frameLoader)) {
return report;
}
}
return null;
},
/**
* Remove an active hang report from the active list and cancel the timer
* associated with it.
*/
removeActiveReport: function(report) {
let timer = this._activeReports.get(report);
if (timer) {
timer.cancel();
}
this._activeReports.delete(report);
this.updateWindows();
},
/**
* Remove a paused hang report from the paused list and cancel the timer
* associated with it.
*/
removePausedReport: function(report) {
let timer = this._pausedReports.get(report);
if (timer) {
timer.cancel();
}
this._pausedReports.delete(report);
},
/**
* Iterate over all XUL windows and ensure that the proper hang
* reports are shown for each one. Also install event handlers in
@ -191,7 +285,7 @@ var ProcessHangMonitor = {
* If there is a hang report for the current tab in |win|, display it.
*/
updateWindow: function(win) {
let report = this.findReport(win.gBrowser.selectedBrowser);
let report = this.findActiveReport(win.gBrowser.selectedBrowser);
if (report) {
this.showNotification(win, report);
@ -212,19 +306,36 @@ var ProcessHangMonitor = {
let bundle = win.gNavigatorBundle;
let brandBundle = win.document.getElementById("bundle_brand");
let appName = brandBundle.getString("brandShortName");
let message = bundle.getFormattedString(
"processHang.message",
[appName]);
let buttons = [{
label: bundle.getString("processHang.button.label"),
accessKey: bundle.getString("processHang.button.accessKey"),
popup: "processHangOptions",
callback: null,
}];
label: bundle.getString("processHang.button_stop.label"),
accessKey: bundle.getString("processHang.button_stop.accessKey"),
callback: function() {
ProcessHangMonitor.stopIt(win);
}
},
{
label: bundle.getString("processHang.button_wait.label"),
accessKey: bundle.getString("processHang.button_wait.accessKey"),
callback: function() {
ProcessHangMonitor.waitLonger(win);
}
}];
nb.appendNotification(message, "process-hang",
#ifdef MOZ_DEV_EDITION
if (report.hangType == report.SLOW_SCRIPT) {
buttons.push({
label: bundle.getString("processHang.button_debug.label"),
accessKey: bundle.getString("processHang.button_debug.accessKey"),
callback: function() {
ProcessHangMonitor.debugScript(win);
}
});
}
#endif
nb.appendNotification(bundle.getString("processHang.label"),
"process-hang",
"chrome://browser/content/aboutRobots-icon.png",
nb.PRIORITY_WARNING_HIGH, buttons);
},
@ -270,11 +381,19 @@ var ProcessHangMonitor = {
* before, show a notification for it in all open XUL windows.
*/
reportHang: function(report) {
// If this hang was already reported, then reset the timer for it.
// If this hang was already reported reset the timer for it.
if (this._activeReports.has(report)) {
let timer = this._activeReports.get(report);
timer.cancel();
timer.initWithCallback(this, HANG_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
timer.initWithCallback(this, this.HANG_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
// if this report is in active but doesn't have a notification associated
// with it, display a notification.
this.updateWindows();
return;
}
// If this hang was already reported and paused by the user ignore it.
if (this._pausedReports.has(report)) {
return;
}
@ -291,28 +410,19 @@ var ProcessHangMonitor = {
// Otherwise create a new timer and display the report.
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(this, HANG_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
timer.initWithCallback(this, this.HANG_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
this._activeReports.set(report, timer);
this.updateWindows();
},
/**
* Dismiss a hang report because the user closed the notification
* for it or the report expired.
*/
removeReport: function(report) {
this._activeReports.delete(report);
this.updateWindows();
},
/**
* Callback for when HANG_EXPIRATION_TIME has elapsed.
*/
notify: function(timer) {
for (let [otherReport, otherTimer] of this._activeReports) {
if (otherTimer === timer) {
this.removeReport(otherReport);
this.removeActiveReport(otherReport);
otherReport.userCanceled();
break;
}

View File

@ -33,7 +33,6 @@ EXTRA_JS_MODULES += [
'offlineAppCache.jsm',
'PanelFrame.jsm',
'PluginContent.jsm',
'ProcessHangMonitor.jsm',
'ReaderParent.jsm',
'RecentWindow.jsm',
'RemotePrompt.jsm',
@ -46,6 +45,10 @@ EXTRA_JS_MODULES += [
'webrtcUI.jsm',
]
EXTRA_PP_JS_MODULES += [
'ProcessHangMonitor.jsm'
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXTRA_JS_MODULES += [
'Windows8WindowFrameColor.jsm',

View File

@ -3,6 +3,8 @@ support-files =
head.js
[browser_BrowserUITelemetry_buckets.js]
[browser_ProcessHangNotifications.js]
skip-if = !e10s
[browser_ContentSearch.js]
skip-if = e10s
support-files =

View File

@ -0,0 +1,185 @@
Cu.import("resource://gre/modules/UpdateUtils.jsm");
function getNotificationBox(aWindow) {
return aWindow.document.getElementById("high-priority-global-notificationbox");
}
function promiseNotificationShown(aWindow, aName) {
return new Promise((resolve) => {
let notification = getNotificationBox(aWindow);
notification.addEventListener("AlertActive", function active() {
notification.removeEventListener("AlertActive", active, true);
is(notification.allNotifications.length, 1, "Notification Displayed.");
resolve(notification);
});
});
}
function promiseReportCallMade(aValue) {
return new Promise((resolve) => {
let old = gTestHangReport.testCallback;
gTestHangReport.testCallback = function (val) {
gTestHangReport.testCallback = old;
is(aValue, val, "was the correct method call made on the hang report object?");
resolve();
};
});
}
function pushPrefs(...aPrefs) {
return new Promise((resolve) => {
SpecialPowers.pushPrefEnv({"set": aPrefs}, resolve);
resolve();
});
}
function popPrefs() {
return new Promise((resolve) => {
SpecialPowers.popPrefEnv(resolve);
resolve();
});
}
let gTestHangReport = {
SLOW_SCRIPT: 1,
PLUGIN_HANG: 2,
TEST_CALLBACK_CANCELED: 1,
TEST_CALLBACK_TERMSCRIPT: 2,
TEST_CALLBACK_TERMPLUGIN: 3,
_hangType: 1,
_tcb: function (aCallbackType) {},
get hangType() {
return this._hangType;
},
set hangType(aValue) {
this._hangType = aValue;
},
set testCallback(aValue) {
this._tcb = aValue;
},
QueryInterface: function (aIID) {
if (aIID.equals(Components.interfaces.nsIHangReport) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
userCanceled: function () {
this._tcb(this.TEST_CALLBACK_CANCELED);
},
terminateScript: function () {
this._tcb(this.TEST_CALLBACK_TERMSCRIPT);
},
terminatePlugin: function () {
this._tcb(this.TEST_CALLBACK_TERMPLUGIN);
},
isReportForBrowser: function(aFrameLoader) {
return true;
}
};
// on dev edition we add a button for js debugging of hung scripts.
let buttonCount = (UpdateUtils.UpdateChannel == "aurora" ? 3 : 2);
/**
* Test if hang reports receive a terminate script callback when the user selects
* stop in response to a script hang.
*/
add_task(function* terminateScriptTest() {
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
let notification = yield promise;
let buttons = notification.currentNotification.getElementsByTagName("button");
is(buttons.length, buttonCount, "proper number of buttons");
// Click the "Stop It" button, we should get a terminate script callback
gTestHangReport.hangType = gTestHangReport.SLOW_SCRIPT;
promise = promiseReportCallMade(gTestHangReport.TEST_CALLBACK_TERMSCRIPT);
buttons[0].click();
yield promise;
});
/**
* Test if hang reports receive user canceled callbacks after a user selects wait
* and the browser frees up from a script hang on its own.
*/
add_task(function* waitForScriptTest() {
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
let notification = yield promise;
let buttons = notification.currentNotification.getElementsByTagName("button");
is(buttons.length, buttonCount, "proper number of buttons");
yield pushPrefs(["browser.hangNotification.waitPeriod", 1000],
["browser.hangNotification.expiration", 2000]);
function nocbcheck() {
ok(false, "received a callback?");
}
let oldcb = gTestHangReport.testCallback;
gTestHangReport.testCallback = nocbcheck;
// Click the "Wait" button this time, we shouldn't get a callback at all.
buttons[1].click();
gTestHangReport.testCallback = oldcb;
// send another hang pulse, we should not get a notification here
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
is(notification.currentNotification, null, "no notification should be visible");
// After selecting Wait, we should get a userCanceled callback after
// HANG_EXPIRATION_TIME.
yield promiseReportCallMade(gTestHangReport.TEST_CALLBACK_CANCELED);
yield popPrefs();
});
/**
* Test if hang reports receive user canceled callbacks after the content
* process stops sending hang notifications.
*/
add_task(function* hangGoesAwayTest() {
yield pushPrefs(["browser.hangNotification.expiration", 1000]);
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
yield promise;
yield promiseReportCallMade(gTestHangReport.TEST_CALLBACK_CANCELED);
yield popPrefs();
});
/**
* Tests if hang reports receive a terminate plugin callback when the user selects
* stop in response to a plugin hang.
*/
add_task(function* terminatePluginTest() {
let promise = promiseNotificationShown(window, "process-hang");
Services.obs.notifyObservers(gTestHangReport, "process-hang-report", null);
let notification = yield promise;
let buttons = notification.currentNotification.getElementsByTagName("button");
is(buttons.length, buttonCount, "proper number of buttons");
// Click the "Stop It" button, we should get a terminate script callback
gTestHangReport.hangType = gTestHangReport.PLUGIN_HANG;
promise = promiseReportCallMade(gTestHangReport.TEST_CALLBACK_TERMPLUGIN);
buttons[0].click();
yield promise;
});

View File

@ -18,14 +18,14 @@ from mozbuild.preprocessor import preprocess
# processing of the jar file in the appropriate directory.
def _do_preprocessing(output_svg, input_svg_file, additional_defines):
additional_defines.update(buildconfig.defines)
preprocess(output=output_svg,
includes=[input_svg_file],
marker='%',
defines=additional_defines)
return preprocess(output=output_svg,
includes=[input_svg_file],
marker='%',
defines=additional_defines)
def tab_side_start(output_svg, input_svg_file):
_do_preprocessing(output_svg, input_svg_file, {'TAB_SIDE': 'start'})
return _do_preprocessing(output_svg, input_svg_file, {'TAB_SIDE': 'start'})
def tab_side_end(output_svg, input_svg_file):
_do_preprocessing(output_svg, input_svg_file, {'TAB_SIDE': 'end'})
return _do_preprocessing(output_svg, input_svg_file, {'TAB_SIDE': 'end'})

View File

@ -85,11 +85,16 @@ def verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair, platform,
# compare to whitelist
message = ""
if line[0] == '-':
# handle lines that move around in diff
if '+' + line[1:] in diff_list:
continue
if platform in mozconfigWhitelist.get('release', {}):
if clean_line in \
mozconfigWhitelist['release'][platform]:
continue
elif line[0] == '+':
if '-' + line[1:] in diff_list:
continue
if platform in mozconfigWhitelist.get('nightly', {}):
if clean_line in \
mozconfigWhitelist['nightly'][platform]:

View File

@ -267,6 +267,10 @@ ifdef MOZ_FOLD_LIBS_FLAGS
DEFAULT_GMAKE_FLAGS += XCFLAGS='$(MOZ_FOLD_LIBS_FLAGS)'
endif
ifeq (1,$(ALLOW_COMPILER_WARNINGS))
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
endif
NSS_SRCDIR = $(topsrcdir)
NSS_DIRS =

View File

@ -682,3 +682,4 @@ VFY_VerifyData
VFY_VerifyDataWithAlgorithmID
VFY_VerifyDigestDirect
_SGN_VerifyPKCS1DigestInfo
__PK11_SetCertificateNickname

View File

@ -67,21 +67,21 @@ function htmlSearch() {
if (label) {
is(target.querySelector(".results-panel-item-label").getAttribute("value"),
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
"The correct label (" + label + ") is currently selected.");
} else {
ok(!target.querySelector(".results-panel-item-label"),
"Shouldn't create empty label nodes.");
}
if (value) {
ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
"The corect value (" + value + ") is attached.");
"The correct value (" + value + ") is attached.");
} else {
ok(!target.querySelector(".results-panel-item-label-below"),
"Shouldn't create empty label nodes.");
}
if (description) {
is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
"The corect description (" + description + ") is currently shown.");
"The correct description (" + description + ") is currently shown.");
} else {
ok(!target.querySelector(".results-panel-item-label-before"),
"Shouldn't create empty label nodes.");
@ -138,21 +138,21 @@ function firstJsSearch() {
if (label) {
is(target.querySelector(".results-panel-item-label").getAttribute("value"),
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
"The correct label (" + label + ") is currently selected.");
} else {
ok(!target.querySelector(".results-panel-item-label"),
"Shouldn't create empty label nodes.");
}
if (value) {
ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
"The corect value (" + value + ") is attached.");
"The correct value (" + value + ") is attached.");
} else {
ok(!target.querySelector(".results-panel-item-label-below"),
"Shouldn't create empty label nodes.");
}
if (description) {
is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
"The corect description (" + description + ") is currently shown.");
"The correct description (" + description + ") is currently shown.");
} else {
ok(!target.querySelector(".results-panel-item-label-before"),
"Shouldn't create empty label nodes.");
@ -209,21 +209,21 @@ function secondJsSearch() {
if (label) {
is(target.querySelector(".results-panel-item-label").getAttribute("value"),
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
"The correct label (" + label + ") is currently selected.");
} else {
ok(!target.querySelector(".results-panel-item-label"),
"Shouldn't create empty label nodes.");
}
if (value) {
ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
"The corect value (" + value + ") is attached.");
"The correct value (" + value + ") is attached.");
} else {
ok(!target.querySelector(".results-panel-item-label-below"),
"Shouldn't create empty label nodes.");
}
if (description) {
is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
"The corect description (" + description + ") is currently shown.");
"The correct description (" + description + ") is currently shown.");
} else {
ok(!target.querySelector(".results-panel-item-label-before"),
"Shouldn't create empty label nodes.");
@ -280,21 +280,21 @@ function thirdJsSearch() {
if (label) {
is(target.querySelector(".results-panel-item-label").getAttribute("value"),
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
"The correct label (" + label + ") is currently selected.");
} else {
ok(!target.querySelector(".results-panel-item-label"),
"Shouldn't create empty label nodes.");
}
if (value) {
ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
"The corect value (" + value + ") is attached.");
"The correct value (" + value + ") is attached.");
} else {
ok(!target.querySelector(".results-panel-item-label-below"),
"Shouldn't create empty label nodes.");
}
if (description) {
is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
"The corect description (" + description + ") is currently shown.");
"The correct description (" + description + ") is currently shown.");
} else {
ok(!target.querySelector(".results-panel-item-label-before"),
"Shouldn't create empty label nodes.");
@ -348,21 +348,21 @@ function filterSearch() {
if (label) {
is(target.querySelector(".results-panel-item-label").getAttribute("value"),
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
"The correct label (" + label + ") is currently selected.");
} else {
ok(!target.querySelector(".results-panel-item-label"),
"Shouldn't create empty label nodes.");
}
if (value) {
ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
"The corect value (" + value + ") is attached.");
"The correct value (" + value + ") is attached.");
} else {
ok(!target.querySelector(".results-panel-item-label-below"),
"Shouldn't create empty label nodes.");
}
if (description) {
is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
"The corect description (" + description + ") is currently shown.");
"The correct description (" + description + ") is currently shown.");
} else {
ok(!target.querySelector(".results-panel-item-label-before"),
"Shouldn't create empty label nodes.");

View File

@ -15,7 +15,7 @@ function test() {
"The format() function shouldn't work if no params are passed.");
is(typeof l10.get("initWebGL.error"), "string",
"No valid string was returned from a corect name in the bundle.");
"No valid string was returned from a correct name in the bundle.");
is(typeof l10.format("linkProgram.error", ["error"]), "string",
"No valid formatted string was returned from a name in the bundle.");
}

View File

@ -0,0 +1,55 @@
/* -*- 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 "WindowOrientationObserver.h"
#include "nsGlobalWindow.h"
#include "mozilla/Hal.h"
/**
* This class is used by nsGlobalWindow to implement window.orientation
* and window.onorientationchange. This class is defined in its own file
* because Hal.h pulls in windows.h and can't be included from
* nsGlobalWindow.cpp
*/
WindowOrientationObserver::WindowOrientationObserver(
nsGlobalWindow* aGlobalWindow)
: mWindow(aGlobalWindow)
{
MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
hal::RegisterScreenConfigurationObserver(this);
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
mAngle = config.angle();
}
WindowOrientationObserver::~WindowOrientationObserver()
{
hal::UnregisterScreenConfigurationObserver(this);
}
void
WindowOrientationObserver::Notify(
const mozilla::hal::ScreenConfiguration& aConfiguration)
{
uint16_t currentAngle = aConfiguration.angle();
if (mAngle != currentAngle && mWindow->IsCurrentInnerWindow()) {
mAngle = currentAngle;
mWindow->GetOuterWindow()->DispatchCustomEvent(NS_LITERAL_STRING("orientationchange"));
}
}
/* static */ int16_t
WindowOrientationObserver::OrientationAngle()
{
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
int16_t angle = static_cast<int16_t>(config.angle());
// config.angle() returns 0, 90, 180 or 270.
// window.orientation returns -90, 0, 90 or 180.
return angle <= 180 ? angle : angle - 360;
}

View File

@ -0,0 +1,35 @@
/* -*- 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_WindowOrientationObserver_h
#define mozilla_dom_WindowOrientationObserver_h
#include "mozilla/HalScreenConfiguration.h"
class nsGlobalWindow;
namespace mozilla {
namespace dom {
class WindowOrientationObserver final :
public mozilla::hal::ScreenConfigurationObserver
{
public:
explicit WindowOrientationObserver(nsGlobalWindow* aGlobalWindow);
~WindowOrientationObserver();
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
static int16_t OrientationAngle();
private:
// Weak pointer, instance is owned by mWindow.
nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
uint16_t mAngle;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_WindowOrientationObserver_h

View File

@ -0,0 +1,36 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<script>
<![CDATA[
function boom()
{
var d = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
d.setAttributeNS(null, "contenteditable", "true");
var s = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
d.appendChild(s);
document.documentElement.appendChild(d);
var textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
var t1 = document.createTextNode("A");
textarea.appendChild(t1);
var t2 = document.createTextNode("B");
textarea.appendChild(t2);
document.documentElement.appendChild(textarea);
document.documentElement.offsetHeight;
d.removeChild(s);
textarea.removeChild(t2);
document.documentElement.appendChild(document.createTextNode(" C "));
document.documentElement.appendChild(t2);
}
window.addEventListener("load", boom, false);
]]>
</script>
<!-- no body -->
</html>

View File

@ -149,6 +149,7 @@ load 709954.html
load 713417-2.html
load 713417.html
load 715056.html
load 729431-1.xhtml
load 741163-1.html
load 745495.html
load 752226-1.html

View File

@ -209,6 +209,7 @@ EXPORTS.mozilla.dom += [
'URL.h',
'URLSearchParams.h',
'WebSocket.h',
'WindowOrientationObserver.h',
]
UNIFIED_SOURCES += [
@ -355,6 +356,7 @@ UNIFIED_SOURCES += [
'URLSearchParams.cpp',
'WebSocket.cpp',
'WindowNamedPropertiesHandler.cpp',
'WindowOrientationObserver.cpp',
]
if CONFIG['MOZ_WEBRTC']:

View File

@ -847,6 +847,7 @@ GK_ATOM(onobsolete, "onobsolete")
GK_ATOM(ononline, "ononline")
GK_ATOM(onoffline, "onoffline")
GK_ATOM(onopen, "onopen")
GK_ATOM(onorientationchange, "onorientationchange")
GK_ATOM(onotastatuschange, "onotastatuschange")
GK_ATOM(onoverflow, "onoverflow")
GK_ATOM(onoverflowchanged, "onoverflowchanged")

View File

@ -20,6 +20,9 @@
#include "mozilla/dom/DOMStorage.h"
#include "mozilla/dom/StorageEvent.h"
#include "mozilla/dom/StorageEventBinding.h"
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
#include "mozilla/dom/WindowOrientationObserver.h"
#endif
#include "nsDOMOfflineResourceList.h"
#include "nsError.h"
#include "nsIIdleService.h"
@ -1527,6 +1530,10 @@ nsGlobalWindow::CleanUp()
mSpeechSynthesis = nullptr;
#endif
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
mOrientationChangeObserver = nullptr;
#endif
ClearControllers();
mOpener = nullptr; // Forces Release
@ -1641,6 +1648,10 @@ nsGlobalWindow::FreeInnerObjects()
mScreen = nullptr;
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
mOrientationChangeObserver = nullptr;
#endif
if (mDoc) {
// Remember the document's principal and URI.
mDocumentPrincipal = mDoc->NodePrincipal();
@ -13654,6 +13665,27 @@ nsGlobalWindow::DisableDeviceSensor(uint32_t aType)
}
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
void
nsGlobalWindow::EnableOrientationChangeListener()
{
MOZ_ASSERT(IsInnerWindow());
if (!mOrientationChangeObserver) {
mOrientationChangeObserver =
new WindowOrientationObserver(this);
}
}
void
nsGlobalWindow::DisableOrientationChangeListener()
{
MOZ_ASSERT(IsInnerWindow());
mOrientationChangeObserver = nullptr;
}
#endif
void
nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
{
@ -14501,6 +14533,15 @@ nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
int16_t
nsGlobalWindow::Orientation() const
{
return WindowOrientationObserver::OrientationAngle();
}
#endif
NS_IMETHODIMP
nsGlobalWindow::GetConsole(JSContext* aCx,
JS::MutableHandle<JS::Value> aConsole)

View File

@ -118,6 +118,9 @@ class RequestOrUSVString;
class Selection;
class SpeechSynthesis;
class WakeLock;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
class WindowOrientationObserver;
#endif
namespace cache {
class CacheStorage;
} // namespace cache
@ -656,6 +659,11 @@ public:
virtual void EnableDeviceSensor(uint32_t aType) override;
virtual void DisableDeviceSensor(uint32_t aType) override;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
virtual void EnableOrientationChangeListener() override;
virtual void DisableOrientationChangeListener() override;
#endif
virtual void EnableTimeChangeNotifications() override;
virtual void DisableTimeChangeNotifications() override;
@ -907,6 +915,10 @@ public:
mozilla::dom::Navigator* GetNavigator(mozilla::ErrorResult& aError);
nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
int16_t Orientation() const;
#endif
mozilla::dom::Console* GetConsole(mozilla::ErrorResult& aRv);
void GetSidebar(mozilla::dom::OwningExternalOrWindowProxy& aResult,
@ -1822,6 +1834,10 @@ protected:
nsTArray<uint32_t> mEnabledSensors;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
nsAutoPtr<mozilla::dom::WindowOrientationObserver> mOrientationChangeObserver;
#endif
#ifdef MOZ_WEBSPEECH
// mSpeechSynthesis is only used on inner windows.
RefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;

View File

@ -635,6 +635,11 @@ public:
*/
virtual void DisableDeviceSensor(uint32_t aType) = 0;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
virtual void EnableOrientationChangeListener() = 0;
virtual void DisableOrientationChangeListener() = 0;
#endif
virtual void EnableTimeChangeNotifications() = 0;
virtual void DisableTimeChangeNotifications() = 0;

View File

@ -359,6 +359,8 @@ skip-if = buildapp == 'mulet'
[test_window_extensible.html]
[test_window_indexing.html]
[test_window_named_frame_enumeration.html]
[test_window_orientation.html]
skip-if = toolkit != 'gonk'
[test_writable-replaceable.html]
[test_navigatorPrefOverride.html]
[test_EventSource_redirects.html]

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test for window.orientation</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="orientationcommon.js"></script>
<div id="log"></div>
<script>
async_test(function(t) {
var originalOrientation = screen.orientation.type;
var alternateOrientation = originalOrientation == "portrait-primary" ?
"landscape-primary" : "portrait-primary";
var originalWindowOrientation = window.orientation;
window.onorientationchange = function() {
t.step(function() { assert_not_equals(window.orientation, originalWindowOrientation); });
var p2 = specialPowersUnlock();
p2.then(function() {
t.done();
}).catch(t.step_func(function(err) {
assert_unreached("Error unlocking orientation: " + err);
t.done();
}));
}
var p1 = specialPowersLock(alternateOrientation);
p1.catch(t.step_func(function(err) {
assert_unreached("Error locking orientation: " + err);
t.done();
}));
}, "Test window.orientation and orientationchange.");
</script>

View File

@ -22,6 +22,7 @@ function runTests(testFile, order) {
SpecialPowers.pushPrefEnv({
"set": [["dom.caches.enabled", true],
["dom.caches.testing.enabled", true],
["dom.requestcache.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]

View File

@ -80,7 +80,8 @@ ClipboardEvent::Constructor(const GlobalObject& aGlobal,
// support other types of events, make sure that read/write privileges are
// checked properly within DataTransfer.
clipboardData = new DataTransfer(ToSupports(e), eCopy, false, -1);
clipboardData->SetData(aParam.mDataType, aParam.mData);
clipboardData->SetData(aParam.mDataType, aParam.mData, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
}
}

View File

@ -280,6 +280,12 @@ DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
FileList*
DataTransfer::GetFiles(ErrorResult& aRv)
{
return GetFilesInternal(aRv, nsContentUtils::SubjectPrincipal());
}
FileList*
DataTransfer::GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal)
{
if (mEventMessage != eDrop &&
mEventMessage != eLegacyDragDrop &&
@ -294,7 +300,7 @@ DataTransfer::GetFiles(ErrorResult& aRv)
for (uint32_t i = 0; i < count; i++) {
nsCOMPtr<nsIVariant> variant;
aRv = MozGetDataAt(NS_ConvertUTF8toUTF16(kFileMime), i, getter_AddRefs(variant));
aRv = GetDataAtInternal(NS_ConvertUTF8toUTF16(kFileMime), i, aSubjectPrincipal, getter_AddRefs(variant));
if (aRv.Failed()) {
return nullptr;
}
@ -346,7 +352,7 @@ NS_IMETHODIMP
DataTransfer::GetFiles(nsIDOMFileList** aFileList)
{
ErrorResult rv;
NS_IF_ADDREF(*aFileList = GetFiles(rv));
NS_IF_ADDREF(*aFileList = GetFilesInternal(rv, nsContentUtils::GetSystemPrincipal()));
return rv.StealNSResult();
}
@ -391,7 +397,7 @@ DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
aData.Truncate();
nsCOMPtr<nsIVariant> data;
nsresult rv = MozGetDataAt(aFormat, 0, getter_AddRefs(data));
nsresult rv = GetDataAtInternal(aFormat, 0, nsContentUtils::SubjectPrincipal(), getter_AddRefs(data));
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_DOM_INDEX_SIZE_ERR) {
aRv.Throw(rv);
@ -450,15 +456,7 @@ DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
RefPtr<nsVariantCC> variant = new nsVariantCC();
variant->SetAsAString(aData);
aRv = MozSetDataAt(aFormat, variant, 0);
}
NS_IMETHODIMP
DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData)
{
ErrorResult rv;
SetData(aFormat, aData, rv);
return rv.StealNSResult();
aRv = SetDataAtInternal(aFormat, variant, 0, nsContentUtils::SubjectPrincipal());
}
void
@ -577,9 +575,16 @@ DataTransfer::MozTypesAt(uint32_t aIndex, nsISupports** aTypes)
return rv.StealNSResult();
}
NS_IMETHODIMP
DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
nsIVariant** aData)
nsresult
DataTransfer::GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex,
nsIVariant** aData)
{
return GetDataAtInternal(aFormat, aIndex, nsContentUtils::GetSystemPrincipal(), aData);
}
nsresult
DataTransfer::GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal, nsIVariant** aData)
{
*aData = nullptr;
@ -609,22 +614,18 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
// source of the drag is in a child frame of the caller. In that case,
// we only allow access to data of the same principal. During other events,
// only allow access to the data with the same principal.
nsIPrincipal* principal = nullptr;
if (mIsCrossDomainSubFrameDrop ||
bool checkFormatItemPrincipal = mIsCrossDomainSubFrameDrop ||
(mEventMessage != eDrop && mEventMessage != eLegacyDragDrop &&
mEventMessage != ePaste &&
!nsContentUtils::IsCallerChrome())) {
principal = nsContentUtils::SubjectPrincipal();
}
mEventMessage != ePaste);
uint32_t count = item.Length();
for (uint32_t i = 0; i < count; i++) {
TransferItem& formatitem = item[i];
if (formatitem.mFormat.Equals(format)) {
bool subsumes;
if (formatitem.mPrincipal && principal &&
(NS_FAILED(principal->Subsumes(formatitem.mPrincipal, &subsumes)) || !subsumes))
if (formatitem.mPrincipal && checkFormatItemPrincipal &&
!aSubjectPrincipal->Subsumes(formatitem.mPrincipal)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!formatitem.mData) {
FillInExternalData(formatitem, aIndex);
@ -643,12 +644,7 @@ DataTransfer::MozGetDataAt(const nsAString& aFormat, uint32_t aIndex,
MOZ_ASSERT(sp, "This cannot fail on the main thread.");
nsIPrincipal* dataPrincipal = sp->GetPrincipal();
NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
if (!principal) {
principal = nsContentUtils::SubjectPrincipal();
}
bool equals = false;
NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
NS_ERROR_DOM_SECURITY_ERR);
NS_ENSURE_TRUE(aSubjectPrincipal->Subsumes(dataPrincipal), NS_ERROR_DOM_SECURITY_ERR);
}
}
*aData = formatitem.mData;
@ -667,7 +663,7 @@ DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
mozilla::ErrorResult& aRv)
{
nsCOMPtr<nsIVariant> data;
aRv = MozGetDataAt(aFormat, aIndex, getter_AddRefs(data));
aRv = GetDataAtInternal(aFormat, aIndex, nsContentUtils::SubjectPrincipal(), getter_AddRefs(data));
if (aRv.Failed()) {
return;
}
@ -684,9 +680,9 @@ DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
}
}
NS_IMETHODIMP
DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
uint32_t aIndex)
nsresult
DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
uint32_t aIndex, nsIPrincipal* aSubjectPrincipal)
{
if (aFormat.IsEmpty()) {
return NS_OK;
@ -713,12 +709,11 @@ DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData,
// XXX perhaps this should also limit any non-string type as well
if ((aFormat.EqualsLiteral("application/x-moz-file-promise") ||
aFormat.EqualsLiteral("application/x-moz-file")) &&
!nsContentUtils::IsCallerChrome()) {
!nsContentUtils::IsSystemPrincipal(aSubjectPrincipal)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
return SetDataWithPrincipal(aFormat, aData, aIndex,
nsContentUtils::SubjectPrincipal());
return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal);
}
void
@ -730,7 +725,7 @@ DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
aRv = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData,
getter_AddRefs(data));
if (!aRv.Failed()) {
aRv = MozSetDataAt(aFormat, data, aIndex);
aRv = SetDataAtInternal(aFormat, data, aIndex, nsContentUtils::SubjectPrincipal());
}
}

View File

@ -68,6 +68,8 @@ public:
friend class mozilla::EventStateManager;
static DataTransfer* Cast(nsIDOMDataTransfer* aArg) { return static_cast<DataTransfer*>(aArg); }
protected:
// hide the default constructor
@ -183,6 +185,9 @@ public:
return mDragTarget;
}
nsresult GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex,
nsIVariant** aData);
// a readonly dataTransfer cannot have new data added or existing data removed.
// Only the dropEffect and effectAllowed may be modified.
void SetReadOnly() { mReadOnly = true; }
@ -246,6 +251,13 @@ protected:
// clipboard for a given index.
void FillInExternalData(TransferItem& aItem, uint32_t aIndex);
FileList* GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal);
nsresult GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal, nsIVariant** aData);
nsresult SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal);
friend class ContentParent;
void FillAllExternalData();

View File

@ -325,6 +325,10 @@ EventListenerManager::AddEventListenerInternal(
EnableDevice(eDeviceLight);
} else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
EnableDevice(eDeviceMotion);
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
} else if (aTypeAtom == nsGkAtoms::onorientationchange) {
EnableDevice(eOrientationChange);
#endif
#ifdef MOZ_B2G
} else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
@ -431,6 +435,9 @@ EventListenerManager::IsDeviceType(EventMessage aEventMessage)
case eDeviceLight:
case eDeviceProximity:
case eUserProximity:
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
case eOrientationChange:
#endif
return true;
default:
break;
@ -462,6 +469,11 @@ EventListenerManager::EnableDevice(EventMessage aEventMessage)
window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
window->EnableDeviceSensor(SENSOR_GYROSCOPE);
break;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
case eOrientationChange:
window->EnableOrientationChangeListener();
break;
#endif
default:
NS_WARNING("Enabling an unknown device sensor.");
break;
@ -492,6 +504,11 @@ EventListenerManager::DisableDevice(EventMessage aEventMessage)
case eDeviceLight:
window->DisableDeviceSensor(SENSOR_LIGHT);
break;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
case eOrientationChange:
window->DisableOrientationChangeListener();
break;
#endif
default:
NS_WARNING("Disabling an unknown device sensor.");
break;

View File

@ -507,6 +507,12 @@ WINDOW_EVENT(online,
eOnline,
EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
WINDOW_EVENT(orientationchange,
eOrientationChange,
EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
#endif
WINDOW_EVENT(pagehide,
ePageHide,
EventNameType_HTMLBodyOrFramesetOnly,

View File

@ -64,6 +64,25 @@ Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
return workerPrivate->RequestContextEnabled();
}
// static
bool
Request::RequestCacheEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.requestcache.enabled", false);
}
using namespace workers;
// Otherwise, check the pref via the WorkerPrivate
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->RequestCacheEnabled();
}
already_AddRefed<InternalRequest>
Request::GetInternalRequest()
{

View File

@ -36,6 +36,8 @@ public:
static bool
RequestContextEnabled(JSContext* aCx, JSObject* aObj);
static bool
RequestCacheEnabled(JSContext* aCx, JSObject* aObj);
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override

View File

@ -0,0 +1,19 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function boom()
{
var video = document.createElement("video");
var source = document.createElement("source");
source.setAttributeNS(null, "src", "http://127.0.0.1/");
video.appendChild(source);
document.body.appendChild(video);
setTimeout(function() { document.body.removeChild(video); }, 20);
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -23,6 +23,7 @@ load 468562-1.html
load 468562-2.html
load 494225.html
load 495543.svg
load 495546-1.html
load 504183-1.html
load 515829-1.html
load 515829-2.html

View File

@ -8,7 +8,7 @@
interface nsIVariant;
interface nsIDOMFileList;
[builtinclass, uuid(c71180e3-298b-4fbb-9ccb-82c822474741)]
[builtinclass, uuid(655078bf-1675-4aa0-a48d-a133e864ce57)]
interface nsIDOMDataTransfer : nsISupports
{
/**
@ -81,17 +81,6 @@ interface nsIDOMDataTransfer : nsISupports
*/
void clearData([optional] in DOMString format);
/**
* Set the data for a given format. If data for the format does not exist,
* it is added at the end, such that the last item in the types list will be
* the new format. If data for the format already exists, the existing data
* is replaced in the same position. That is, the order of the types list is
* not changed.
*
* @throws NS_ERROR_NULL_POINTER if the data is null
*/
void setData(in DOMString format, in DOMString data);
/**
* Retrieves the data for a given format, or an empty string if data for
* that format does not exist or the data transfer contains no data.
@ -171,40 +160,6 @@ interface nsIDOMDataTransfer : nsISupports
*/
void mozClearDataAt(in DOMString format, in unsigned long index);
/*
* A data transfer may store multiple items, each at a given zero-based
* index. setDataAt may only be called with an index argument less than
* itemCount in which case an existing item is modified, or equal to
* itemCount in which case a new item is added, and the itemCount is
* incremented by one.
*
* Data should be added in order of preference, with the most specific
* format added first and the least specific format added last. If data of
* the given format already exists, it is replaced in the same position as
* the old data.
*
* The data should be either a string, a primitive boolean or number type
* (which will be converted into a string) or an nsISupports.
*
* @param format the format to add
* @param data the data to add
* @throws NS_ERROR_NULL_POINTER if the data is null
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater than itemCount
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
void mozSetDataAt(in DOMString format, in nsIVariant data, in unsigned long index);
/**
* Retrieve the data associated with the given format for an item at the
* specified index, or null if it does not exist. The index should be in the
* range from zero to itemCount - 1.
*
* @param format the format of the data to look up
* @returns the data of the given format, or null if it doesn't exist.
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
*/
nsIVariant mozGetDataAt(in DOMString format, in unsigned long index);
/**
* Will be true when the user has cancelled the drag (typically by pressing
* Escape) and when the drag has been cancelled unexpectedly. This will be

View File

@ -151,7 +151,6 @@ public:
NS_IMETHOD BeginStartingDebugger() override;
NS_IMETHOD EndStartingDebugger() override;
NS_IMETHOD TerminatePlugin() override;
NS_IMETHOD TerminateProcess() override;
NS_IMETHOD UserCanceled() override;
NS_IMETHOD IsReportForBrowser(nsIFrameLoader* aFrameLoader, bool* aResult) override;
@ -820,6 +819,8 @@ HangMonitoredProcess::TerminatePlugin()
return NS_ERROR_UNEXPECTED;
}
// generates a crash report that includes a browser report taken here
// earlier, the content process, and any plugin process(es).
uint32_t id = mHangData.get_PluginHangData().pluginId();
plugins::TerminatePlugin(id, NS_LITERAL_CSTRING("HangMonitor"),
mBrowserDumpId);
@ -830,24 +831,6 @@ HangMonitoredProcess::TerminatePlugin()
return NS_OK;
}
NS_IMETHODIMP
HangMonitoredProcess::TerminateProcess()
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
if (!mContentParent) {
return NS_ERROR_UNEXPECTED;
}
if (mActor && mHangData.type() == HangData::TPluginHangData) {
uint32_t id = mHangData.get_PluginHangData().pluginId();
mActor->CleanupPluginHang(id, true);
}
mContentParent->KillHard("HangMonitor");
return NS_OK;
}
NS_IMETHODIMP
HangMonitoredProcess::IsReportForBrowser(nsIFrameLoader* aFrameLoader, bool* aResult)
{

View File

@ -18,7 +18,7 @@ interface nsIFrameLoader;
* process will continue to run uninhibitedly during this time.
*/
[scriptable, uuid(90cea731-dd3e-459e-b017-f9a14697b56e)]
[scriptable, uuid(5fcffbb9-be62-49b1-b8a1-36e820787a74)]
interface nsIHangReport : nsISupports
{
const unsigned long SLOW_SCRIPT = 1;
@ -50,10 +50,6 @@ interface nsIHangReport : nsISupports
// Only valid for PLUGIN_HANG reports.
void terminatePlugin();
// Terminate the hung content process unconditionally.
// Valid for any type of hang.
void terminateProcess();
// Ask the content process to start up the slow script debugger.
// Only valid for SLOW_SCRIPT reports.
void beginStartingDebugger();

View File

@ -501,11 +501,11 @@ StreamAndPromiseForOperation::StreamAndPromiseForOperation(MediaStream* aStream,
// MOZ_ASSERT(aPromise);
}
AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl, dom::AudioChannel aChannel)
AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl)
: GraphDriver(aGraphImpl)
, mIterationDurationMS(MEDIA_GRAPH_TARGET_PERIOD_MS)
, mStarted(false)
, mAudioChannel(aChannel)
, mAudioChannel(aGraphImpl->AudioChannel())
, mInCallback(false)
, mPauseRequested(false)
#ifdef XP_MACOSX

View File

@ -329,8 +329,7 @@ class AudioCallbackDriver : public GraphDriver,
public MixerCallbackReceiver
{
public:
explicit AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl,
dom::AudioChannel aChannel = dom::AudioChannel::Normal);
explicit AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl);
virtual ~AudioCallbackDriver();
virtual void Destroy() override;

View File

@ -1409,9 +1409,9 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
LIFECYCLE_LOG("Disconnecting MediaStreamGraph %p", this);
MediaStreamGraphImpl* graph;
if (gGraphs.Get(mAudioChannel, &graph) && graph == this) {
if (gGraphs.Get(uint32_t(mAudioChannel), &graph) && graph == this) {
// null out gGraph if that's the graph being shut down
gGraphs.Remove(mAudioChannel);
gGraphs.Remove(uint32_t(mAudioChannel));
}
}
} else {
@ -1566,8 +1566,8 @@ MediaStreamGraphImpl::AppendMessage(ControlMessage* aMessage)
mLifecycleState >= LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION) {
MediaStreamGraphImpl* graph;
if (gGraphs.Get(mAudioChannel, &graph) && graph == this) {
gGraphs.Remove(mAudioChannel);
if (gGraphs.Get(uint32_t(mAudioChannel), &graph) && graph == this) {
gGraphs.Remove(uint32_t(mAudioChannel));
}
Destroy();
@ -1653,7 +1653,7 @@ MediaStream::SetGraphImpl(MediaStreamGraphImpl* aGraph)
{
MOZ_ASSERT(!mGraph, "Should only be called once");
mGraph = aGraph;
mAudioChannelType = static_cast<AudioChannel>(aGraph->AudioChannel());
mAudioChannelType = aGraph->AudioChannel();
mBuffer.InitGraphRate(aGraph->GraphRate());
}
@ -2567,7 +2567,7 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
#ifdef DEBUG
, mCanRunMessagesSynchronously(false)
#endif
, mAudioChannel(static_cast<uint32_t>(aChannel))
, mAudioChannel(aChannel)
{
if (!gMediaStreamGraphLog) {
gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph");
@ -2575,7 +2575,7 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
if (mRealtime) {
if (aDriverRequested == AUDIO_THREAD_DRIVER) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this, aChannel);
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
mDriver = driver;
mMixer.AddCallback(driver);
} else {
@ -3082,7 +3082,7 @@ MediaStreamGraph::IsNonRealtime() const
const MediaStreamGraphImpl* impl = static_cast<const MediaStreamGraphImpl*>(this);
MediaStreamGraphImpl* graph;
return !gGraphs.Get(impl->AudioChannel(), &graph) || graph != impl;
return !gGraphs.Get(uint32_t(impl->AudioChannel()), &graph) || graph != impl;
}
void

View File

@ -717,7 +717,7 @@ public:
RefPtr<AudioOutputObserver> mFarendObserverRef;
#endif
uint32_t AudioChannel() const { return mAudioChannel; }
dom::AudioChannel AudioChannel() const { return mAudioChannel; }
private:
virtual ~MediaStreamGraphImpl();
@ -762,9 +762,7 @@ private:
bool mCanRunMessagesSynchronously;
#endif
// We use uint32_t instead AudioChannel because this is just used as key for
// the hashtable gGraphs.
uint32_t mAudioChannel;
dom::AudioChannel mAudioChannel;
};
} // namespace mozilla

View File

@ -29,8 +29,10 @@ namespace dom {
class SynthStreamListener : public MediaStreamListener
{
public:
explicit SynthStreamListener(nsSpeechTask* aSpeechTask) :
explicit SynthStreamListener(nsSpeechTask* aSpeechTask,
MediaStream* aStream) :
mSpeechTask(aSpeechTask),
mStream(aStream),
mStarted(false)
{
}
@ -63,6 +65,8 @@ public:
break;
case EVENT_REMOVED:
mSpeechTask = nullptr;
// Dereference MediaStream to destroy safety
mStream = nullptr;
break;
default:
break;
@ -83,6 +87,8 @@ private:
// Raw pointer; if we exist, the stream exists,
// and 'mSpeechTask' exclusively owns it and therefor exists as well.
nsSpeechTask* mSpeechTask;
// This is KungFuDeathGrip for MediaStream
RefPtr<MediaStream> mStream;
bool mStarted;
};
@ -132,6 +138,8 @@ nsSpeechTask::~nsSpeechTask()
mStream->Destroy();
}
// This will finally destroyed by SynthStreamListener becasue
// MediaStream::Destroy() is async.
mStream = nullptr;
}
@ -185,7 +193,7 @@ nsSpeechTask::Setup(nsISpeechTaskCallback* aCallback,
// mStream is set up in Init() that should be called before this.
MOZ_ASSERT(mStream);
mStream->AddListener(new SynthStreamListener(this));
mStream->AddListener(new SynthStreamListener(this, mStream));
// XXX: Support more than one channel
if(NS_WARN_IF(!(aChannels == 1))) {
@ -711,7 +719,7 @@ nsSpeechTask::WindowAudioCaptureChanged()
void
nsSpeechTask::SetAudioOutputVolume(float aVolume)
{
if (mStream) {
if (mStream && !mStream->IsDestroyed()) {
mStream->SetAudioOutputVolume(this, aVolume);
}
if (mIndirectAudio) {

View File

@ -7,7 +7,8 @@ function testScript(script) {
function setupPrefs() {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({
"set": [["dom.requestcontext.enabled", true],
"set": [["dom.requestcache.enabled", true],
["dom.requestcontext.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]

View File

@ -36,6 +36,7 @@ skip-if = buildapp == 'b2g' || (toolkit == 'android' && debug) # Bug 1137683 &&
[test_formdataparsing_sw_reroute.html]
skip-if = buildapp == 'b2g' # Bug 1137683
[test_request.html]
[test_request_cache.html]
[test_request_context.html]
[test_request_sw_reroute.html]
skip-if = buildapp == 'b2g' # Bug 1137683

View File

@ -10,7 +10,8 @@ function testScript(script) {
}
SpecialPowers.pushPrefEnv({
"set": [["dom.serviceWorkers.enabled", true],
"set": [["dom.requestcache.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.interception.opaque.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]

View File

@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Make sure that Request.cache is not exposed by default</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
var req = new Request("");
ok(!("cache" in req), "Request.cache should not be exposed by default");
</script>
</body>
</html>

View File

@ -212,7 +212,7 @@ function checkEntries(anEntryList) {
function firstCheck() {
is(window.performance.getEntriesByType("resource").length, 1, "The first xhr entry was not added.");
is(window.performance.getEntriesByType("resource")[0].initiatorType, "xmlhttprequest",
"The initiatorType is incorect for this entry");
"The initiatorType is incorrect for this entry");
makeXhr("test-data2.json", secondCheck);
}

View File

@ -13,6 +13,7 @@ interface Clients {
// The objects returned will be new instances every time
[Throws]
Promise<sequence<Client>?> matchAll(optional ClientQueryOptions options);
[Throws, Func="mozilla::dom::workers::ServiceWorkerGlobalScope::OpenWindowEnabled"]
Promise<WindowClient> openWindow(USVString url);
[Throws]
Promise<void> claim();

View File

@ -22,6 +22,7 @@ interface Request {
readonly attribute DOMString referrer;
readonly attribute RequestMode mode;
readonly attribute RequestCredentials credentials;
[Func="mozilla::dom::Request::RequestCacheEnabled"]
readonly attribute RequestCache cache;
readonly attribute RequestRedirect redirect;

View File

@ -398,6 +398,14 @@ Window implements TouchEventHandlers;
Window implements OnErrorEventHandlerForWindow;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
// https://compat.spec.whatwg.org/#windoworientation-interface
partial interface Window {
readonly attribute short orientation;
attribute EventHandler onorientationchange;
};
#endif
// ConsoleAPI
partial interface Window {
[Replaceable, GetterThrows]

View File

@ -168,7 +168,9 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_SERVICEWORKERS_TESTING_ENABLED "dom.serviceWorkers.testing.enabled"
#define PREF_INTERCEPTION_ENABLED "dom.serviceWorkers.interception.enabled"
#define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
#define PREF_OPEN_WINDOW_ENABLED "dom.serviceWorkers.openWindow.enabled"
#define PREF_PUSH_ENABLED "dom.push.enabled"
#define PREF_REQUESTCACHE_ENABLED "dom.requestcache.enabled"
#define PREF_REQUESTCONTEXT_ENABLED "dom.requestcontext.enabled"
#define PREF_OFFSCREENCANVAS_ENABLED "gfx.offscreencanvas.enabled"
@ -1940,6 +1942,10 @@ RuntimeService::Init()
WorkerPrefChanged,
PREF_INTERCEPTION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_OPEN_WINDOW_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OPEN_WINDOW_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_INTERCEPTION_OPAQUE_ENABLED,
@ -1960,6 +1966,10 @@ RuntimeService::Init()
WorkerPrefChanged,
PREF_PUSH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_REQUESTCACHE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCACHE))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
@ -2183,6 +2193,10 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_INTERCEPTION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_OPEN_WINDOW_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OPEN_WINDOW_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_SERVICEWORKERS_ENABLED,
@ -2203,6 +2217,10 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_PUSH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_REQUESTCACHE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCACHE))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
@ -2785,9 +2803,11 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
#endif
case WORKERPREF_INTERCEPTION_ENABLED:
case WORKERPREF_INTERCEPTION_OPAQUE_ENABLED:
case WORKERPREF_OPEN_WINDOW_ENABLED:
case WORKERPREF_SERVICEWORKERS:
case WORKERPREF_SERVICEWORKERS_TESTING:
case WORKERPREF_PUSH:
case WORKERPREF_REQUESTCACHE:
case WORKERPREF_REQUESTCONTEXT:
case WORKERPREF_OFFSCREENCANVAS:
sDefaultPreferences[key] = Preferences::GetBool(aPrefName, false);

View File

@ -16,6 +16,15 @@
#include "WorkerRunnable.h"
#include "WorkerScope.h"
#include "nsIDocShell.h"
#include "nsIDOMChromeWindow.h"
#include "nsIDOMWindow.h"
#include "nsIWebNavigation.h"
#include "nsIWindowMediator.h"
#include "nsIWebProgress.h"
#include "nsIWebProgressListener.h"
#include "nsWeakReference.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
@ -199,6 +208,337 @@ public:
}
};
class ResolveOpenWindowRunnable final : public WorkerRunnable
{
public:
ResolveOpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsresult aStatus)
: WorkerRunnable(aPromiseProxy->GetWorkerPrivate(), WorkerThreadModifyBusyCount)
, mPromiseProxy(aPromiseProxy)
, mClientInfo(Move(aClientInfo))
, mStatus(aStatus)
{
AssertIsOnMainThread();
MOZ_ASSERT(aPromiseProxy);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
Promise* promise = mPromiseProxy->WorkerPromise();
if (NS_WARN_IF(NS_FAILED(mStatus))) {
promise->MaybeReject(mStatus);
} else if (mClientInfo) {
RefPtr<ServiceWorkerWindowClient> client =
new ServiceWorkerWindowClient(promise->GetParentObject(),
*mClientInfo);
promise->MaybeResolve(client);
} else {
promise->MaybeResolve(JS::NullHandleValue);
}
mPromiseProxy->CleanUp(aCx);
return true;
}
private:
RefPtr<PromiseWorkerProxy> mPromiseProxy;
UniquePtr<ServiceWorkerClientInfo> mClientInfo;
const nsresult mStatus;
};
class WebProgressListener final : public nsIWebProgressListener,
public nsSupportsWeakReference
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebProgressListener, nsIWebProgressListener)
WebProgressListener(PromiseWorkerProxy* aPromiseProxy,
ServiceWorkerPrivate* aServiceWorkerPrivate,
nsPIDOMWindow* aWindow,
nsIURI* aBaseURI)
: mPromiseProxy(aPromiseProxy)
, mServiceWorkerPrivate(aServiceWorkerPrivate)
, mWindow(aWindow)
, mBaseURI(aBaseURI)
{
MOZ_ASSERT(aPromiseProxy);
MOZ_ASSERT(aServiceWorkerPrivate);
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsOuterWindow());
MOZ_ASSERT(aBaseURI);
AssertIsOnMainThread();
mServiceWorkerPrivate->StoreISupports(static_cast<nsIWebProgressListener*>(this));
}
NS_IMETHOD
OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aStateFlags, nsresult aStatus) override
{
if (!(aStateFlags & STATE_IS_DOCUMENT) ||
!(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
return NS_OK;
}
// Our caller keeps a strong reference, so it is safe to remove the listener
// from ServiceWorkerPrivate.
mServiceWorkerPrivate->RemoveISupports(static_cast<nsIWebProgressListener*>(this));
aWebProgress->RemoveProgressListener(this);
MutexAutoLock lock(mPromiseProxy->Lock());
if (mPromiseProxy->CleanedUp()) {
return NS_OK;
}
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
UniquePtr<ServiceWorkerClientInfo> clientInfo;
if (doc) {
// Check same origin.
nsCOMPtr<nsIScriptSecurityManager> securityManager =
nsContentUtils::GetSecurityManager();
nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
mBaseURI, false);
if (NS_SUCCEEDED(rv)) {
clientInfo.reset(new ServiceWorkerClientInfo(doc));
}
}
RefPtr<ResolveOpenWindowRunnable> r =
new ResolveOpenWindowRunnable(mPromiseProxy,
Move(clientInfo),
NS_OK);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
r->Dispatch(cx);
return NS_OK;
}
NS_IMETHOD
OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress) override
{
MOZ_ASSERT(false, "Unexpected notification.");
return NS_OK;
}
NS_IMETHOD
OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* aLocation,
uint32_t aFlags) override
{
MOZ_ASSERT(false, "Unexpected notification.");
return NS_OK;
}
NS_IMETHOD
OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus, const char16_t* aMessage) override
{
MOZ_ASSERT(false, "Unexpected notification.");
return NS_OK;
}
NS_IMETHOD
OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aState) override
{
MOZ_ASSERT(false, "Unexpected notification.");
return NS_OK;
}
private:
~WebProgressListener()
{ }
RefPtr<PromiseWorkerProxy> mPromiseProxy;
RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<nsIURI> mBaseURI;
};
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebProgressListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebProgressListener)
NS_IMPL_CYCLE_COLLECTION(WebProgressListener, mPromiseProxy,
mServiceWorkerPrivate, mWindow)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
class OpenWindowRunnable final : public nsRunnable
{
RefPtr<PromiseWorkerProxy> mPromiseProxy;
nsString mUrl;
nsString mScope;
public:
OpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
const nsAString& aUrl,
const nsAString& aScope)
: mPromiseProxy(aPromiseProxy)
, mUrl(aUrl)
, mScope(aScope)
{
MOZ_ASSERT(aPromiseProxy);
MOZ_ASSERT(aPromiseProxy->GetWorkerPrivate());
aPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
}
NS_IMETHOD
Run() override
{
AssertIsOnMainThread();
MutexAutoLock lock(mPromiseProxy->Lock());
if (mPromiseProxy->CleanedUp()) {
return NS_OK;
}
nsCOMPtr<nsPIDOMWindow> window;
nsresult rv = OpenWindow(getter_AddRefs(window));
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(window);
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
MOZ_ASSERT(workerPrivate);
WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
nsCOMPtr<nsIURI> baseURI;
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
if (!webProgress) {
return NS_ERROR_FAILURE;
}
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
MOZ_ASSERT(principal);
RefPtr<ServiceWorkerRegistrationInfo> registration =
swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
if (NS_WARN_IF(!registration)) {
return NS_ERROR_FAILURE;
}
RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID());
if (NS_WARN_IF(!serviceWorkerInfo)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIWebProgressListener> listener =
new WebProgressListener(mPromiseProxy, serviceWorkerInfo->WorkerPrivate(),
window, baseURI);
rv = webProgress->AddProgressListener(listener,
nsIWebProgress::NOTIFY_STATE_DOCUMENT);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return NS_OK;
}
RefPtr<ResolveOpenWindowRunnable> resolveRunnable =
new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv);
AutoJSAPI jsapi;
jsapi.Init();
NS_WARN_IF(!resolveRunnable->Dispatch(jsapi.cx()));
return NS_OK;
}
private:
nsresult
OpenWindow(nsPIDOMWindow** aWindow)
{
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
// [[1. Let url be the result of parsing url with entry settings object's API
// base URL.]]
nsCOMPtr<nsIURI> uri;
WorkerPrivate::LocationInfo& info = workerPrivate->GetLocationInfo();
nsCOMPtr<nsIURI> baseURI;
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), info.mOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_TYPE_ERR;
}
rv = NS_NewURI(getter_AddRefs(uri), mUrl, nullptr, baseURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_TYPE_ERR;
}
// [[6.1 Open Window]]
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID,
&rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Find the most recent browser window and open a new tab in it.
nsCOMPtr<nsIDOMWindow> browserWindow;
rv = wm->GetMostRecentWindow(MOZ_UTF16("navigator:browser"),
getter_AddRefs(browserWindow));
if (NS_WARN_IF(NS_FAILED(rv)) || !browserWindow) {
// It is possible to be running without a browser window on Mac OS, so
// we need to open a new chrome window.
// TODO(catalinb): open new chrome window. Bug 1218080
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(browserWindow);
if (NS_WARN_IF(!chromeWin)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIBrowserDOMWindow> bwin;
chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
if (NS_WARN_IF(!bwin)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMWindow> win;
rv = bwin->OpenURI(uri, nullptr,
nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
nsIBrowserDOMWindow::OPEN_NEW,
getter_AddRefs(win));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ENSURE_STATE(win);
nsCOMPtr<nsPIDOMWindow> pWin = do_QueryInterface(win);
pWin = pWin->GetOuterWindow();
pWin.forget(aWindow);
return NS_OK;
}
};
} // namespace
already_AddRefed<Promise>
@ -237,15 +577,51 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
}
already_AddRefed<Promise>
ServiceWorkerClients::OpenWindow(const nsAString& aUrl)
ServiceWorkerClients::OpenWindow(const nsAString& aUrl,
ErrorResult& aRv)
{
ErrorResult result;
RefPtr<Promise> promise = Promise::Create(mWorkerScope, result);
if (NS_WARN_IF(result.Failed())) {
// XXXcatalinb: This works only on non-multiprocess for now, bail if we're
// running in a content process.
if (XRE_IsContentProcess()) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
if (aUrl.EqualsLiteral("about:blank")) {
promise->MaybeReject(NS_ERROR_TYPE_ERR);
return promise.forget();
}
// [[4. If this algorithm is not allowed to show a popup ..]]
// In Gecko the service worker is allowed to show a popup only if the user
// just clicked on a notification.
if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
RefPtr<PromiseWorkerProxy> promiseProxy =
PromiseWorkerProxy::Create(workerPrivate, promise);
if (!promiseProxy) {
return nullptr;
}
nsString scope;
mWorkerScope->GetScope(scope);
RefPtr<OpenWindowRunnable> r = new OpenWindowRunnable(promiseProxy,
aUrl, scope);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
return promise.forget();
}

View File

@ -33,7 +33,7 @@ public:
MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv);
already_AddRefed<Promise>
OpenWindow(const nsAString& aUrl);
OpenWindow(const nsAString& aUrl, ErrorResult& aRv);
already_AddRefed<Promise>
Claim(ErrorResult& aRv);

View File

@ -382,6 +382,21 @@ ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo()
}
}
already_AddRefed<ServiceWorkerInfo>
ServiceWorkerRegistrationInfo::GetServiceWorkerInfoById(uint64_t aId)
{
RefPtr<ServiceWorkerInfo> serviceWorker;
if (mInstallingWorker && mInstallingWorker->ID() == aId) {
serviceWorker = mInstallingWorker;
} else if (mWaitingWorker && mWaitingWorker->ID() == aId) {
serviceWorker = mWaitingWorker;
} else if (mActiveWorker && mActiveWorker->ID() == aId) {
serviceWorker = mActiveWorker;
}
return serviceWorker.forget();
}
//////////////////////////
// ServiceWorkerManager //
//////////////////////////

View File

@ -96,6 +96,9 @@ public:
return newest.forget();
}
already_AddRefed<ServiceWorkerInfo>
GetServiceWorkerInfoById(uint64_t aId);
void
StartControllingADocument()
{

View File

@ -13,7 +13,13 @@ using namespace mozilla::dom;
BEGIN_WORKERS_NAMESPACE
NS_IMPL_ISUPPORTS0(ServiceWorkerPrivate)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerPrivate)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerPrivate)
NS_IMPL_CYCLE_COLLECTION(ServiceWorkerPrivate, mSupportsArray)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerPrivate)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
// Tracks the "dom.disable_open_click_delay" preference. Modified on main
// thread, read on worker threads.
@ -67,6 +73,7 @@ ServiceWorkerPrivate::~ServiceWorkerPrivate()
MOZ_ASSERT(!mWorkerPrivate);
MOZ_ASSERT(!mTokenCount);
MOZ_ASSERT(!mInfo);
MOZ_ASSERT(mSupportsArray.IsEmpty());
mIdleWorkerTimer->Cancel();
}
@ -1149,6 +1156,10 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
return NS_OK;
}
// Sanity check: mSupportsArray should be empty if we're about to
// spin up a new worker.
MOZ_ASSERT(mSupportsArray.IsEmpty());
if (NS_WARN_IF(!mInfo)) {
NS_WARNING("Trying to wake up a dead service worker.");
return NS_ERROR_FAILURE;
@ -1225,6 +1236,23 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
return NS_OK;
}
void
ServiceWorkerPrivate::StoreISupports(nsISupports* aSupports)
{
AssertIsOnMainThread();
MOZ_ASSERT(mWorkerPrivate);
MOZ_ASSERT(!mSupportsArray.Contains(aSupports));
mSupportsArray.AppendElement(aSupports);
}
void
ServiceWorkerPrivate::RemoveISupports(nsISupports* aSupports)
{
AssertIsOnMainThread();
mSupportsArray.RemoveElement(aSupports);
}
void
ServiceWorkerPrivate::TerminateWorker()
{
@ -1244,6 +1272,7 @@ ServiceWorkerPrivate::TerminateWorker()
jsapi.Init();
NS_WARN_IF(!mWorkerPrivate->Terminate(jsapi.cx()));
mWorkerPrivate = nullptr;
mSupportsArray.Clear();
}
}

View File

@ -61,7 +61,8 @@ class ServiceWorkerPrivate final : public nsISupports
friend class KeepAliveToken;
public:
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(ServiceWorkerPrivate)
explicit ServiceWorkerPrivate(ServiceWorkerInfo* aInfo);
@ -106,6 +107,12 @@ public:
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
bool aIsReload);
void
StoreISupports(nsISupports* aSupports);
void
RemoveISupports(nsISupports* aSupports);
// This will terminate the current running worker thread and drop the
// workerPrivate reference.
// Called by ServiceWorkerInfo when [[Clear Registration]] is invoked
@ -177,6 +184,12 @@ private:
RefPtr<KeepAliveToken> mKeepAliveToken;
uint64_t mTokenCount;
// Meant for keeping objects alive while handling requests from the worker
// on the main thread. Access to this array is provided through
// |StoreISupports| and |RemoveISupports|. Note that the array is also
// cleared whenever the worker is terminated.
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
};
} // namespace workers

View File

@ -1265,6 +1265,13 @@ public:
return mPreferences[WORKERPREF_INTERCEPTION_ENABLED];
}
bool
OpenWindowEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_OPEN_WINDOW_ENABLED];
}
bool
OpaqueInterceptionEnabled() const
{
@ -1307,6 +1314,13 @@ public:
return mPreferences[WORKERPREF_PUSH];
}
bool
RequestCacheEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_REQUESTCACHE];
}
bool
RequestContextEnabled() const
{

View File

@ -634,6 +634,15 @@ ServiceWorkerGlobalScope::InterceptionEnabled(JSContext* aCx, JSObject* aObj)
return worker->InterceptionEnabled();
}
bool
ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
{
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
return worker->OpenWindowEnabled();
}
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)

View File

@ -249,6 +249,9 @@ public:
static bool
InterceptionEnabled(JSContext* aCx, JSObject* aObj);
static bool
OpenWindowEnabled(JSContext* aCx, JSObject* aObj);
void
GetScope(nsString& aScope) const
{

View File

@ -201,6 +201,7 @@ enum WorkerPreference
WORKERPREF_DOM_CACHES, // dom.caches.enabled
WORKERPREF_SERVICEWORKERS, // dom.serviceWorkers.enabled
WORKERPREF_INTERCEPTION_ENABLED, // dom.serviceWorkers.interception.enabled
WORKERPREF_OPEN_WINDOW_ENABLED, // dom.serviceWorkers.openWindow.enabled
WORKERPREF_DOM_WORKERNOTIFICATION, // dom.webnotifications.workers.enabled
WORKERPREF_DOM_SERVICEWORKERNOTIFICATION, // dom.webnotifications.serviceworker.enabled
WORKERPREF_DOM_CACHES_TESTING, // dom.caches.testing.enabled
@ -208,6 +209,7 @@ enum WorkerPreference
WORKERPREF_INTERCEPTION_OPAQUE_ENABLED, // dom.serviceWorkers.interception.opaque.enabled
WORKERPREF_PERFORMANCE_LOGGING_ENABLED, // dom.performance.enable_user_timing_logging
WORKERPREF_PUSH, // dom.push.enabled
WORKERPREF_REQUESTCACHE, // dom.requestcache.enabled
WORKERPREF_REQUESTCONTEXT, // dom.requestcontext.enabled
WORKERPREF_OFFSCREENCANVAS, // gfx.offscreencanvas.enabled
WORKERPREF_COUNT

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var x = new XMLHttpRequest();
x.open('GET', "data:text/plain,2", false);
x.send();
new Worker("data:text/javascript,3");
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -1,2 +1,3 @@
load 779707.html
load 943516.html
load 1158031.html

View File

@ -184,6 +184,8 @@ support-files =
xslt/*
unresolved_fetch_worker.js
header_checker.sjs
openWindow_worker.js
redirect.sjs
[test_app_protocol.html]
skip-if = release_build
@ -283,3 +285,5 @@ skip-if = e10s # Bug 1214305
[test_csp_upgrade-insecure_intercept.html]
skip-if = e10s # Bug 1214305
[test_serviceworker_header.html]
[test_openWindow.html]
skip-if = toolkit == "android" || toolkit == "gonk" || e10s

View File

@ -0,0 +1,90 @@
// the worker won't shut down between events because we increased
// the timeout values.
var client;
function testForUrl(url, throwType, clientProperties, resultsArray) {
return clients.openWindow(url)
.then(function(e) {
if (throwType != null) {
resultsArray.push({
result: false,
message: "openWindow should throw " + throwType
});
} else if (clientProperties) {
resultsArray.push({
result: (e instanceof WindowClient),
message: "openWindow should resolve to a WindowClient"
});
resultsArray.push({
result: e.url == clientProperties.url,
message: "Client url should be " + clientProperties.url
});
// Add more properties
} else {
resultsArray.push({
result: e == null,
message: "Open window should resolve to null. Got: " + e
});
}
})
.catch(function(err) {
if (throwType == null) {
resultsArray.push({
result: false,
message: "Unexpected throw: " + err
});
} else {
resultsArray.push({
result: err.toString().indexOf(throwType) >= 0,
message: "openWindow should throw: " + err
});
}
})
}
onmessage = function(event) {
client = event.source;
var results = [];
var promises = [];
promises.push(testForUrl("about:blank", "TypeError", null, results));
promises.push(testForUrl("http://example.com", "InvalidAccessError", null, results));
promises.push(testForUrl("_._*`InvalidURL", "InvalidAccessError", null, results));
Promise.all(promises).then(function(e) {
client.postMessage(results);
});
}
onnotificationclick = function(e) {
var results = [];
var promises = [];
promises.push(testForUrl("about:blank", "TypeError", null, results));
promises.push(testForUrl("http://example.com", null, null, results));
promises.push(testForUrl("http://mochi.test:8888/same_origin.html", null,
{url: "http://mochi.test:8888/same_origin.html"}, results));
// redirect tests
var redirect = "http://mochi.test:8888/tests/dom/workers/test/serviceworkers/redirect.sjs?"
var baseURL = "http://mochi.test:8888/tests/dom/workers/test/serviceworkers/"
promises.push(testForUrl(redirect + "same_origin_redirect.html", null,
{url: baseURL + "same_origin_redirect.html"}, results));
promises.push(testForUrl(redirect + "http://example.com/redirect_to_other_origin.html", null,
null, results));
var redirect_xorigin = "http://example.com/tests/dom/workers/test/serviceworkers/redirect.sjs?"
promises.push(testForUrl(redirect_xorigin + "xorigin_redirect.html", null,
null, results));
promises.push(testForUrl(redirect_xorigin + "http://mochi.test:8888/xorigin_to_same_origin.html", null,
{url: "http://mochi.test:8888/xorigin_to_same_origin.html"}, results));
Promise.all(promises).then(function(e) {
client.postMessage(results);
});
}
onfetch = function(e) {
if (e.request.url.indexOf(same_origin) >= 0) {
e.respondWith(new Response("same_origin_window"));
}
}

View File

@ -0,0 +1,5 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
response.setHeader("Location", request.queryString, false);
}

View File

@ -0,0 +1,111 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1172870
-->
<head>
<title>Bug 1172870 - Test clients.openWindow</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
<script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1172870">Bug 1172870</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="text/javascript">
SimpleTest.requestFlakyTimeout("Mock alert service dispatches show and click events.");
function setup(ctx) {
MockServices.register();
return navigator.serviceWorker.register("openWindow_worker.js", {scope: "./"})
.then(function(swr) {
ok(swr, "Registration successful");
ctx.registration = swr;
return ctx;
});
}
function waitForActiveServiceWorker(ctx) {
return navigator.serviceWorker.ready.then(function(result) {
ok(ctx.registration.active, "Service Worker is active");
return ctx;
});
}
function setupMessageHandler(ctx) {
return new Promise(function(res, rej) {
navigator.serviceWorker.onmessage = function(event) {
navigator.serviceWorker.onmessage = null;
for (i = 0; i < event.data.length; i++) {
ok(event.data[i].result, event.data[i].message);
}
res(ctx);
}
});
}
function testPopupNotAllowed(ctx) {
var p = setupMessageHandler(ctx);
ok(ctx.registration.active, "Worker is active.");
ctx.registration.active.postMessage("testNoPopup");
return p;
}
function testPopupAllowed(ctx) {
var p = setupMessageHandler(ctx);
ctx.registration.showNotification("testPopup");
return p;
}
function clear(ctx) {
MockServices.unregister();
var browser = SpecialPowers.Services.wm.getMostRecentWindow("navigator:browser").gBrowser;
ok(browser.tabs.length == 7, "Total number of tabs is correct.");
while (browser.tabs.length > 1) {
browser.removeTab(browser.tabs[1]);
}
return ctx.registration.unregister().then(function(result) {
ctx.registration = null;
ok(result, "Unregister was successful.");
});
}
function runTest() {
setup({})
.then(waitForActiveServiceWorker)
// Permission to allow popups persists for some time after a notification
// click event, so the order here is important.
.then(testPopupNotAllowed)
.then(testPopupAllowed)
.then(clear)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.webnotifications.workers.enabled", true],
["dom.webnotifications.serviceworker.enabled", true],
["notification.prompt.testing", true],
["dom.disable_open_click_delay", 1000],
["dom.serviceWorkers.idle_timeout", 299999],
["dom.serviceWorkers.idle_extended_timeout", 299999]
]}, runTest);
</script>
</body>
</html>

View File

@ -3,4 +3,4 @@ load 407062-1.html
load 419563-1.xhtml
load 428844-1.html
load 461049-1.html
asserts(0-1) asserts-if(winWidget||Android,0-2) load removing-editable-xslt.html # bug 500847
load removing-editable-xslt.html

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
document.body.style.cssFloat = "left";
document.createElement("div").appendChild(document.querySelector("legend"));
}
</script>
</head>
<body onload="boom();"><fieldset><legend></legend><textarea></textarea></fieldset></body>
</html>

View File

@ -36,6 +36,7 @@ load 633709.xhtml
load 636074-1.html
load 639736-1.xhtml
load 643786-1.html
load 667321-1.html
load 682650-1.html
load 713427-1.html
load 713427-2.xhtml

View File

@ -1209,7 +1209,7 @@ GetStringFromDataTransfer(nsIDOMDataTransfer *aDataTransfer, const nsAString& aT
int32_t aIndex, nsAString& aOutputString)
{
nsCOMPtr<nsIVariant> variant;
aDataTransfer->MozGetDataAt(aType, aIndex, getter_AddRefs(variant));
DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(aType, aIndex, getter_AddRefs(variant));
if (variant)
variant->GetAsAString(aOutputString);
}
@ -1244,7 +1244,7 @@ nsresult nsHTMLEditor::InsertFromDataTransfer(DataTransfer *aDataTransfer,
type.EqualsLiteral(kPNGImageMime) ||
type.EqualsLiteral(kGIFImageMime)) {
nsCOMPtr<nsIVariant> variant;
aDataTransfer->MozGetDataAt(type, aIndex, getter_AddRefs(variant));
DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(type, aIndex, getter_AddRefs(variant));
if (variant) {
nsCOMPtr<nsISupports> object;
variant->GetAsISupports(getter_AddRefs(object));

View File

@ -145,8 +145,8 @@ nsresult nsPlaintextEditor::InsertFromDataTransfer(DataTransfer *aDataTransfer,
bool aDoDeleteSelection)
{
nsCOMPtr<nsIVariant> data;
aDataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), aIndex,
getter_AddRefs(data));
DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(NS_LITERAL_STRING("text/plain"), aIndex,
getter_AddRefs(data));
if (data) {
nsAutoString insertText;
data->GetAsAString(insertText);

View File

@ -7,7 +7,6 @@
#define MOZILLA_GFX_SCALEFACTORS2D_H_
#include <ostream>
#include <iomanip>
#include "mozilla/Attributes.h"
#include "mozilla/FloatingPoint.h"

View File

@ -112,11 +112,21 @@ SOURCES += [
if CONFIG['GNU_CXX']:
CXXFLAGS += [
'-Wno-attributes',
'-Wno-shadow',
'-Wno-sign-compare',
'-Wno-unknown-pragmas',
'-Wno-unreachable-code',
]
if CONFIG['CLANG_CXX']:
CXXFLAGS += ['-Wno-unused-private-field']
CXXFLAGS += [
'-Wno-inconsistent-missing-override',
'-Wno-unused-private-field',
]
else:
CXXFLAGS += [
'-Wno-shadow-compatible-local',
'-Wno-shadow-local',
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]

View File

@ -260,11 +260,21 @@ if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
if CONFIG['GNU_CXX']:
CXXFLAGS += [
'-Wno-attributes',
'-Wno-shadow',
'-Wno-sign-compare',
'-Wno-unknown-pragmas',
'-Wno-unreachable-code',
]
if CONFIG['CLANG_CXX']:
CXXFLAGS += ['-Wno-unused-private-field']
CXXFLAGS += [
'-Wno-inconsistent-missing-override',
'-Wno-unused-private-field',
]
else:
CXXFLAGS += [
'-Wno-shadow-compatible-local',
'-Wno-shadow-local',
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]

View File

@ -16,11 +16,21 @@ UNIFIED_SOURCES += [
if CONFIG['GNU_CXX']:
CXXFLAGS += [
'-Wno-attributes',
'-Wno-shadow',
'-Wno-sign-compare',
'-Wno-unknown-pragmas',
'-Wno-unreachable-code',
]
if CONFIG['CLANG_CXX']:
CXXFLAGS += ['-Wno-unused-private-field']
CXXFLAGS += [
'-Wno-inconsistent-missing-override',
'-Wno-unused-private-field',
]
else:
CXXFLAGS += [
'-Wno-shadow-compatible-local',
'-Wno-shadow-local',
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]

View File

@ -22,11 +22,21 @@ UNIFIED_SOURCES += [
if CONFIG['GNU_CXX']:
CXXFLAGS += [
'-Wno-attributes',
'-Wno-shadow',
'-Wno-sign-compare',
'-Wno-unknown-pragmas',
'-Wno-unreachable-code',
]
if CONFIG['CLANG_CXX']:
CXXFLAGS += ['-Wno-unused-private-field']
CXXFLAGS += [
'-Wno-inconsistent-missing-override',
'-Wno-unused-private-field',
]
else:
CXXFLAGS += [
'-Wno-shadow-compatible-local',
'-Wno-shadow-local',
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]

View File

@ -736,7 +736,7 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
}
/* The PDF CTM is transformed to the user space CTM when stroking
* so the corect pen shape will be used. This also requires that
* so the correct pen shape will be used. This also requires that
* the path be transformed to user space when emitted. The
* conversion of path coordinates to user space may cause rounding
* errors. For example the device space point (1.234, 3.142) when

View File

@ -6,7 +6,7 @@
#include "TaskThrottler.h"
#include "base/message_loop.h"
#include "mozilla/layers/APZThreadUtils.h"
#define TASK_LOG(...)
// #define TASK_LOG(...) printf_stderr("TASK: " __VA_ARGS__)
@ -49,8 +49,7 @@ TaskThrottler::PostTask(const tracked_objects::Location& aLocation,
// even if we don't get a TaskComplete() until then.
TimeDuration timeout = mMaxWait - TimeSinceLastRequest(aTimeStamp, lock);
mTimeoutTask = NewRunnableMethod(this, &TaskThrottler::OnTimeout);
MessageLoop::current()->PostDelayedTask(FROM_HERE, mTimeoutTask,
timeout.ToMilliseconds());
APZThreadUtils::RunDelayedTaskOnCurrentThread(mTimeoutTask, timeout);
return;
}
// we've been waiting for more than the max-wait limit, so just fall through

View File

@ -81,6 +81,23 @@ APZThreadUtils::RunOnControllerThread(Task* aTask)
#endif
}
/*static*/ void
APZThreadUtils::RunDelayedTaskOnCurrentThread(Task* aTask,
const TimeDuration& aDelay)
{
if (MessageLoop* messageLoop = MessageLoop::current()) {
messageLoop->PostDelayedTask(FROM_HERE, aTask, aDelay.ToMilliseconds());
} else {
#ifdef MOZ_ANDROID_APZ
// Fennec does not have a MessageLoop::current() on the controller thread.
AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelay.ToMilliseconds());
#else
// Other platforms should.
MOZ_RELEASE_ASSERT(false, "This non-Fennec platform should have a MessageLoop::current()");
#endif
}
}
NS_IMPL_ISUPPORTS(GenericTimerCallbackBase, nsITimerCallback)
} // namespace layers

View File

@ -7,6 +7,7 @@
#define mozilla_layers_APZThreadUtils_h
#include "base/message_loop.h"
#include "mozilla/TimeStamp.h" // for TimeDuration
#include "nsITimer.h"
class Task;
@ -50,6 +51,12 @@ public:
* run immediately without getting queued.
*/
static void RunOnControllerThread(Task* aTask);
/**
* Runs the given task on the current thread after a delay of |aDelay|.
*/
static void RunDelayedTaskOnCurrentThread(Task* aTask,
const TimeDuration& aDelay);
};
// A base class for GenericTimerCallback<Function>.

View File

@ -227,6 +227,11 @@ ContentHostTexture::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
MOZ_ASSERT(t.mPictureRect.IsEqualInterior(
nsIntRect(nsIntPoint(0, 0), nsIntSize(t.mTexture->GetSize()))),
"Only default picture rect supported");
if (t.mTexture != mTextureHost) {
mReceivedNewHost = true;
}
mTextureHost = t.mTexture;
mTextureHostOnWhite = nullptr;
mTextureSourceOnWhite = nullptr;
@ -330,6 +335,11 @@ ContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
// updated is in screen coordinates. Convert it to buffer coordinates.
nsIntRegion destRegion(aUpdated);
if (mReceivedNewHost) {
destRegion.Or(destRegion, aOldValidRegionBack);
mReceivedNewHost = false;
}
destRegion.MoveBy(-aData.rect().TopLeft());
if (!aData.rect().Contains(aUpdated.GetBounds()) ||

Some files were not shown because too many files have changed in this diff Show More