Merge mozilla-central to b2g-inbound
@ -1378,6 +1378,7 @@ pref("devtools.webide.enabled", true);
|
||||
pref("devtools.toolbox.footer.height", 250);
|
||||
pref("devtools.toolbox.sidebar.width", 500);
|
||||
pref("devtools.toolbox.host", "bottom");
|
||||
pref("devtools.toolbox.previousHost", "side");
|
||||
pref("devtools.toolbox.selectedTool", "webconsole");
|
||||
pref("devtools.toolbox.toolbarSpec", '["splitconsole", "paintflashing toggle","tilt toggle","scratchpad","resize toggle","eyedropper","screenshot --fullpage", "rulers"]');
|
||||
pref("devtools.toolbox.sideEnabled", true);
|
||||
|
@ -1241,14 +1241,9 @@
|
||||
|
||||
<svg:svg height="0">
|
||||
#include tab-shape.inc.svg
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
<svg:clipPath id="urlbar-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="m 1,-5 l 0,50 l 10000,0 l 0,-50 z"/>
|
||||
</svg:clipPath>
|
||||
#endif
|
||||
<svg:clipPath id="urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
#ifndef XP_MACOSX
|
||||
<svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22 l 10000,0 l 0,-50 l -10000,0 z"/>
|
||||
<svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22l10000,0 l 0,-50 l -10000,0 z"/>
|
||||
#else
|
||||
<svg:path d="M -11,-5 a 16 16 0 0 1 0,34 l 10000,0 l 0,-34 l -10000,0 z"/>
|
||||
#endif
|
||||
|
@ -102,12 +102,15 @@ let handleContentContextMenu = function (event) {
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
|
||||
let disableSetDesktopBg = null;
|
||||
// Media related cache info parent needs for saving
|
||||
let contentType = null;
|
||||
let contentDisposition = null;
|
||||
if (event.target.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
|
||||
event.target instanceof Ci.nsIImageLoadingContent &&
|
||||
event.target.currentURI) {
|
||||
disableSetDesktopBg = disableSetDesktopBackground(event.target);
|
||||
|
||||
try {
|
||||
let imageCache =
|
||||
Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
@ -148,7 +151,7 @@ let handleContentContextMenu = function (event) {
|
||||
{ editFlags, spellInfo, customMenuItems, addonInfo,
|
||||
principal, docLocation, charSet, baseURI, referrer,
|
||||
referrerPolicy, contentType, contentDisposition,
|
||||
frameOuterWindowID, selectionInfo },
|
||||
frameOuterWindowID, selectionInfo, disableSetDesktopBg },
|
||||
{ event, popupNode: event.target });
|
||||
}
|
||||
else {
|
||||
@ -169,6 +172,7 @@ let handleContentContextMenu = function (event) {
|
||||
contentType: contentType,
|
||||
contentDisposition: contentDisposition,
|
||||
selectionInfo: selectionInfo,
|
||||
disableSetDesktopBackground: disableSetDesktopBg,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -753,3 +757,52 @@ addMessageListener("ContextMenu:SearchFieldBookmarkData", (message) => {
|
||||
sendAsyncMessage("ContextMenu:SearchFieldBookmarkData:Result",
|
||||
{ spec, title, description, postData, charset });
|
||||
});
|
||||
|
||||
function disableSetDesktopBackground(aTarget) {
|
||||
// Disable the Set as Desktop Background menu item if we're still trying
|
||||
// to load the image or the load failed.
|
||||
if (!(aTarget instanceof Ci.nsIImageLoadingContent))
|
||||
return true;
|
||||
|
||||
if (("complete" in aTarget) && !aTarget.complete)
|
||||
return true;
|
||||
|
||||
if (aTarget.currentURI.schemeIs("javascript"))
|
||||
return true;
|
||||
|
||||
let request = aTarget.QueryInterface(Ci.nsIImageLoadingContent)
|
||||
.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
if (!request)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
addMessageListener("ContextMenu:SetAsDesktopBackground", (message) => {
|
||||
let target = message.objects.target;
|
||||
|
||||
// Paranoia: check disableSetDesktopBackground again, in case the
|
||||
// image changed since the context menu was initiated.
|
||||
let disable = disableSetDesktopBackground(target);
|
||||
|
||||
if (!disable) {
|
||||
try {
|
||||
BrowserUtils.urlSecurityCheck(target.currentURI.spec, target.ownerDocument.nodePrincipal);
|
||||
let canvas = content.document.createElement("canvas");
|
||||
canvas.width = target.naturalWidth;
|
||||
canvas.height = target.naturalHeight;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(target, 0, 0);
|
||||
let dataUrl = canvas.toDataURL();
|
||||
sendAsyncMessage("ContextMenu:SetAsDesktopBackground:Result",
|
||||
{ dataUrl });
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError(e);
|
||||
disable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (disable)
|
||||
sendAsyncMessage("ContextMenu:SetAsDesktopBackground:Result", { disable });
|
||||
});
|
||||
|
@ -241,7 +241,7 @@ nsContextMenu.prototype = {
|
||||
|
||||
if (haveSetDesktopBackground && this.onLoadedImage) {
|
||||
document.getElementById("context-setDesktopBackground")
|
||||
.disabled = this.disableSetDesktopBackground();
|
||||
.disabled = gContextMenuContentData.disableSetDesktopBackground;
|
||||
}
|
||||
|
||||
// Reload image depends on an image that's not fully loaded
|
||||
@ -1134,60 +1134,49 @@ nsContextMenu.prototype = {
|
||||
referrerURI: gContextMenuContentData.documentURIObject });
|
||||
},
|
||||
|
||||
disableSetDesktopBackground: function() {
|
||||
// Disable the Set as Desktop Background menu item if we're still trying
|
||||
// to load the image or the load failed.
|
||||
if (!(this.target instanceof Ci.nsIImageLoadingContent))
|
||||
return true;
|
||||
|
||||
if (("complete" in this.target) && !this.target.complete)
|
||||
return true;
|
||||
|
||||
if (this.target.currentURI.schemeIs("javascript"))
|
||||
return true;
|
||||
|
||||
var request = this.target
|
||||
.QueryInterface(Ci.nsIImageLoadingContent)
|
||||
.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
if (!request)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
setDesktopBackground: function() {
|
||||
// Paranoia: check disableSetDesktopBackground again, in case the
|
||||
// image changed since the context menu was initiated.
|
||||
if (this.disableSetDesktopBackground())
|
||||
return;
|
||||
let mm = this.browser.messageManager;
|
||||
|
||||
var doc = this.target.ownerDocument;
|
||||
urlSecurityCheck(this.target.currentURI.spec, this.principal);
|
||||
mm.sendAsyncMessage("ContextMenu:SetAsDesktopBackground", null,
|
||||
{ target: this.target });
|
||||
|
||||
// Confirm since it's annoying if you hit this accidentally.
|
||||
const kDesktopBackgroundURL =
|
||||
"chrome://browser/content/setDesktopBackground.xul";
|
||||
let onMessage = (message) => {
|
||||
mm.removeMessageListener("ContextMenu:SetAsDesktopBackground:Result",
|
||||
onMessage);
|
||||
|
||||
if (message.data.disable)
|
||||
return;
|
||||
|
||||
let image = document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
|
||||
image.src = message.data.dataUrl;
|
||||
|
||||
// Confirm since it's annoying if you hit this accidentally.
|
||||
const kDesktopBackgroundURL =
|
||||
"chrome://browser/content/setDesktopBackground.xul";
|
||||
#ifdef XP_MACOSX
|
||||
// On Mac, the Set Desktop Background window is not modal.
|
||||
// Don't open more than one Set Desktop Background window.
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var dbWin = wm.getMostRecentWindow("Shell:SetDesktopBackground");
|
||||
if (dbWin) {
|
||||
dbWin.gSetBackground.init(this.target);
|
||||
dbWin.focus();
|
||||
}
|
||||
else {
|
||||
openDialog(kDesktopBackgroundURL, "",
|
||||
"centerscreen,chrome,dialog=no,dependent,resizable=no",
|
||||
this.target);
|
||||
}
|
||||
// On Mac, the Set Desktop Background window is not modal.
|
||||
// Don't open more than one Set Desktop Background window.
|
||||
const wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
let dbWin = wm.getMostRecentWindow("Shell:SetDesktopBackground");
|
||||
if (dbWin) {
|
||||
dbWin.gSetBackground.init(image);
|
||||
dbWin.focus();
|
||||
}
|
||||
else {
|
||||
openDialog(kDesktopBackgroundURL, "",
|
||||
"centerscreen,chrome,dialog=no,dependent,resizable=no",
|
||||
image);
|
||||
}
|
||||
#else
|
||||
// On non-Mac platforms, the Set Wallpaper dialog is modal.
|
||||
openDialog(kDesktopBackgroundURL, "",
|
||||
"centerscreen,chrome,dialog,modal,dependent",
|
||||
this.target);
|
||||
// On non-Mac platforms, the Set Wallpaper dialog is modal.
|
||||
openDialog(kDesktopBackgroundURL, "",
|
||||
"centerscreen,chrome,dialog,modal,dependent",
|
||||
image);
|
||||
#endif
|
||||
};
|
||||
|
||||
mm.addMessageListener("ContextMenu:SetAsDesktopBackground:Result", onMessage);
|
||||
},
|
||||
|
||||
// Save URL of clicked-on frame.
|
||||
@ -1298,7 +1287,9 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// set up a channel to do the saving
|
||||
// setting up a new channel for 'right click - save link as ...'
|
||||
// which should be treated the same way as a toplevel load, hence
|
||||
// we use TYPE_DOCUMENT, see also bug: 1136055
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var channel = ioService.newChannelFromURI2(makeURI(linkURL),
|
||||
@ -1306,7 +1297,7 @@ nsContextMenu.prototype = {
|
||||
this.principal, // aLoadingPrincipal
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
Ci.nsIContentPolicy.TYPE_DOCUMENT);
|
||||
if (linkDownload)
|
||||
channel.contentDispositionFilename = linkDownload;
|
||||
if (channel instanceof Ci.nsIPrivateBrowsingChannel) {
|
||||
|
@ -3890,6 +3890,7 @@
|
||||
contentDisposition: aMessage.data.contentDisposition,
|
||||
frameOuterWindowID: aMessage.data.frameOuterWindowID,
|
||||
selectionInfo: aMessage.data.selectionInfo,
|
||||
disableSetDesktopBackground: aMessage.data.disableSetDesktopBg,
|
||||
};
|
||||
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
||||
let event = gContextMenuContentData.event;
|
||||
|
@ -137,7 +137,7 @@ skip-if = e10s # Bug 1101993 - times out for unknown reasons when run in the dir
|
||||
[browser_autocomplete_oldschool_wrap.js]
|
||||
[browser_autocomplete_tag_star_visibility.js]
|
||||
[browser_backButtonFitts.js]
|
||||
skip-if = os != "win" # The Fitts Law back button is only supported on Windows (bug 571454)
|
||||
skip-if = os == "mac" # The Fitt's Law back button is not supported on OS X
|
||||
[browser_beforeunload_duplicate_dialogs.js]
|
||||
skip-if = e10s # bug 967873 means permitUnload doesn't work in e10s mode
|
||||
[browser_blob-channelname.js]
|
||||
|
@ -36,10 +36,19 @@ add_task(function* test_reader_button() {
|
||||
is_element_hidden(readerButton, "Reader mode button is not present on a new tab");
|
||||
// Point tab to a test page that is not reader-able due to hidden nodes.
|
||||
let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
|
||||
yield promiseTabLoadEvent(tab, url);
|
||||
yield ContentTask.spawn(tab.linkedBrowser, "", function() {
|
||||
return ContentTaskUtils.waitForEvent(content, "MozAfterPaint");
|
||||
let paintPromise = ContentTask.spawn(tab.linkedBrowser, "", function() {
|
||||
return new Promise(resolve => {
|
||||
addEventListener("DOMContentLoaded", function onDCL() {
|
||||
removeEventListener("DOMContentLoaded", onDCL);
|
||||
addEventListener("MozAfterPaint", function onPaint() {
|
||||
removeEventListener("MozAfterPaint", onPaint);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
yield paintPromise;
|
||||
|
||||
is_element_hidden(readerButton, "Reader mode button is still not present on tab with unreadable content.");
|
||||
});
|
||||
|
@ -1,267 +1,272 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="application/javascript;version=1.7"
|
||||
src="healthreport_pingData.js">
|
||||
</script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function init() {
|
||||
window.addEventListener("message", function process(e) {
|
||||
// The init function of abouthealth.js schedules an initial payload event,
|
||||
// which will be sent after the payload data has been collected. This extra
|
||||
// event can cause unexpected successes/failures in this test, so we wait
|
||||
// for the extra event to arrive here before progressing with the actual
|
||||
// test.
|
||||
if (e.data.type == "payload") {
|
||||
window.removeEventListener("message", process, false);
|
||||
|
||||
window.addEventListener("message", doTest, false);
|
||||
doTest();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
function checkSubmissionValue(payload, expectedValue) {
|
||||
return payload.enabled == expectedValue;
|
||||
}
|
||||
|
||||
function validatePayload(payload) {
|
||||
payload = JSON.parse(payload);
|
||||
|
||||
// xxxmpc - this is some pretty low-bar validation, but we have plenty of tests of that API elsewhere
|
||||
if (!payload.thisPingDate)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isArray(arg) {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]';
|
||||
}
|
||||
|
||||
function writeDiagnostic(text) {
|
||||
let node = document.createTextNode(text);
|
||||
let br = document.createElement("br");
|
||||
document.body.appendChild(node);
|
||||
document.body.appendChild(br);
|
||||
}
|
||||
|
||||
function validateCurrentTelemetryEnvironment(data) {
|
||||
// Simple check for now: check that the received object has the expected
|
||||
// top-level properties.
|
||||
const expectedKeys = ["profile", "settings", "system", "build", "partner", "addons"];
|
||||
return expectedKeys.every(key => (key in data));
|
||||
}
|
||||
|
||||
function validateCurrentTelemetryPingData(ping) {
|
||||
// Simple check for now: check that the received object has the expected
|
||||
// top-level properties and that the type and reason match.
|
||||
const expectedKeys = ["environment", "clientId", "payload", "application",
|
||||
"version", "type", "id"];
|
||||
return expectedKeys.every(key => (key in ping)) &&
|
||||
(ping.type == "main") &&
|
||||
("info" in ping.payload) &&
|
||||
("reason" in ping.payload.info) &&
|
||||
(ping.payload.info.reason == "gather-subsession-payload");
|
||||
}
|
||||
|
||||
function validateTelemetryPingList(list) {
|
||||
if (!isArray(list)) {
|
||||
console.log("Telemetry ping list is not an array.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (list.length != TEST_PINGS.length) {
|
||||
console.log("Telemetry ping length is not correct.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let valid = true;
|
||||
for (let i=0; i<list.length; ++i) {
|
||||
let received = list[i];
|
||||
let expected = TEST_PINGS[i];
|
||||
if (received.type != expected.type ||
|
||||
received.timestampCreated != expected.date.getTime()) {
|
||||
writeDiagnostic("Telemetry ping " + i + " does not match.");
|
||||
writeDiagnostic("Expected: " + JSON.stringify(expected));
|
||||
writeDiagnostic("Received: " + JSON.stringify(received));
|
||||
valid = false;
|
||||
} else {
|
||||
writeDiagnostic("Telemetry ping " + i + " matches.");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateTelemetryPingData(expected, received) {
|
||||
const receivedDate = new Date(received.creationDate);
|
||||
if (received.id != expected.id ||
|
||||
received.type != expected.type ||
|
||||
receivedDate.getTime() != expected.date.getTime()) {
|
||||
writeDiagnostic("Telemetry ping data for " + expected.id + " doesn't match.");
|
||||
writeDiagnostic("Expected: " + JSON.stringify(expected));
|
||||
writeDiagnostic("Received: " + JSON.stringify(received));
|
||||
return false;
|
||||
}
|
||||
|
||||
writeDiagnostic("Telemetry ping data for " + expected.id + " matched.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{
|
||||
info: "Checking initial value is enabled",
|
||||
event: "RequestCurrentPrefs",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, true);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying disabling works",
|
||||
event: "DisableDataSubmission",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, false);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we're still disabled",
|
||||
event: "RequestCurrentPrefs",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, false);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we can get a payload while submission is disabled",
|
||||
event: "RequestCurrentPayload",
|
||||
payloadType: "payload",
|
||||
validateResponse: function(payload) {
|
||||
return validatePayload(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying enabling works",
|
||||
event: "EnableDataSubmission",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, true);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we're still re-enabled",
|
||||
event: "RequestCurrentPrefs",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, true);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we can get a payload after re-enabling",
|
||||
event: "RequestCurrentPayload",
|
||||
payloadType: "payload",
|
||||
validateResponse: function(payload) {
|
||||
return validatePayload(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying that we can get the current Telemetry environment data",
|
||||
event: "RequestCurrentEnvironment",
|
||||
payloadType: "telemetry-current-environment-data",
|
||||
validateResponse: function(payload) {
|
||||
return validateCurrentTelemetryEnvironment(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying that we can get the current Telemetry ping data",
|
||||
event: "RequestCurrentPingData",
|
||||
payloadType: "telemetry-current-ping-data",
|
||||
validateResponse: function(payload) {
|
||||
return validateCurrentTelemetryPingData(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying that we get the proper Telemetry ping list",
|
||||
event: "RequestTelemetryPingList",
|
||||
payloadType: "telemetry-ping-list",
|
||||
validateResponse: function(payload) {
|
||||
// Validate the ping list
|
||||
if (!validateTelemetryPingList(payload)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now that we received the ping ids, set up additional test tasks
|
||||
// that check loading the individual pings.
|
||||
for (let i=0; i<TEST_PINGS.length; ++i) {
|
||||
TEST_PINGS[i].id = payload[i].id;
|
||||
tests.push({
|
||||
info: "Verifying that we can get the proper Telemetry ping data #" + (i + 1),
|
||||
event: "RequestTelemetryPingData",
|
||||
eventData: { id: TEST_PINGS[i].id },
|
||||
payloadType: "telemetry-ping-data",
|
||||
validateResponse: function(payload) {
|
||||
return validateTelemetryPingData(TEST_PINGS[i], payload.pingData);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
var currentTest = -1;
|
||||
function doTest(evt) {
|
||||
if (evt) {
|
||||
if (currentTest < 0 || !evt.data.content)
|
||||
return; // not yet testing
|
||||
|
||||
var test = tests[currentTest];
|
||||
if (evt.data.type != test.payloadType)
|
||||
return; // skip unrequested events
|
||||
|
||||
var error = JSON.stringify(evt.data.content);
|
||||
var pass = false;
|
||||
try {
|
||||
pass = test.validateResponse(evt.data.content)
|
||||
} catch (e) {}
|
||||
reportResult(test.info, pass, error);
|
||||
}
|
||||
// start the next test if there are any left
|
||||
if (tests[++currentTest])
|
||||
sendToBrowser(tests[currentTest].event, tests[currentTest].eventData);
|
||||
else
|
||||
reportFinished();
|
||||
}
|
||||
|
||||
function reportResult(info, pass, error) {
|
||||
var data = {type: "testResult", info: info, pass: pass, error: error};
|
||||
var event = new CustomEvent("FirefoxHealthReportTestResponse", {detail: {data: data}, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function reportFinished(cmd) {
|
||||
var data = {type: "testsComplete", count: tests.length};
|
||||
var event = new CustomEvent("FirefoxHealthReportTestResponse", {detail: {data: data}, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function sendToBrowser(type, eventData) {
|
||||
eventData = eventData || {};
|
||||
let detail = {command: type};
|
||||
for (let key of Object.keys(eventData)) {
|
||||
detail[key] = eventData[key];
|
||||
}
|
||||
|
||||
var event = new CustomEvent("RemoteHealthReportCommand", {detail: detail, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
</body>
|
||||
</html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="application/javascript;version=1.7"
|
||||
src="healthreport_pingData.js">
|
||||
</script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function init() {
|
||||
window.addEventListener("message", function process(e) {
|
||||
// The init function of abouthealth.js schedules an initial payload event,
|
||||
// which will be sent after the payload data has been collected. This extra
|
||||
// event can cause unexpected successes/failures in this test, so we wait
|
||||
// for the extra event to arrive here before progressing with the actual
|
||||
// test.
|
||||
if (e.data.type == "payload") {
|
||||
window.removeEventListener("message", process, false);
|
||||
|
||||
window.addEventListener("message", doTest, false);
|
||||
doTest();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
function checkSubmissionValue(payload, expectedValue) {
|
||||
return payload.enabled == expectedValue;
|
||||
}
|
||||
|
||||
function validatePayload(payload) {
|
||||
payload = JSON.parse(payload);
|
||||
|
||||
// xxxmpc - this is some pretty low-bar validation, but we have plenty of tests of that API elsewhere
|
||||
if (!payload.thisPingDate)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isArray(arg) {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]';
|
||||
}
|
||||
|
||||
function writeDiagnostic(text) {
|
||||
let node = document.createTextNode(text);
|
||||
let br = document.createElement("br");
|
||||
document.body.appendChild(node);
|
||||
document.body.appendChild(br);
|
||||
}
|
||||
|
||||
function validateCurrentTelemetryEnvironment(data) {
|
||||
// Simple check for now: check that the received object has the expected
|
||||
// top-level properties.
|
||||
const expectedKeys = ["profile", "settings", "system", "build", "partner", "addons"];
|
||||
return expectedKeys.every(key => (key in data));
|
||||
}
|
||||
|
||||
function validateCurrentTelemetryPingData(ping) {
|
||||
// Simple check for now: check that the received object has the expected
|
||||
// top-level properties and that the type and reason match.
|
||||
const expectedKeys = ["environment", "clientId", "payload", "application",
|
||||
"version", "type", "id"];
|
||||
return expectedKeys.every(key => (key in ping)) &&
|
||||
(ping.type == "main") &&
|
||||
("info" in ping.payload) &&
|
||||
("reason" in ping.payload.info) &&
|
||||
(ping.payload.info.reason == "gather-subsession-payload");
|
||||
}
|
||||
|
||||
function validateTelemetryPingList(list) {
|
||||
if (!isArray(list)) {
|
||||
console.log("Telemetry ping list is not an array.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Telemetry may generate other pings (e.g. "deletion" pings), so filter those
|
||||
// out.
|
||||
const TEST_TYPES_REGEX = /^test-telemetryArchive/;
|
||||
list = list.filter(p => TEST_TYPES_REGEX.test(p.type));
|
||||
|
||||
if (list.length != TEST_PINGS.length) {
|
||||
console.log("Telemetry ping length is not correct.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let valid = true;
|
||||
for (let i=0; i<list.length; ++i) {
|
||||
let received = list[i];
|
||||
let expected = TEST_PINGS[i];
|
||||
if (received.type != expected.type ||
|
||||
received.timestampCreated != expected.date.getTime()) {
|
||||
writeDiagnostic("Telemetry ping " + i + " does not match.");
|
||||
writeDiagnostic("Expected: " + JSON.stringify(expected));
|
||||
writeDiagnostic("Received: " + JSON.stringify(received));
|
||||
valid = false;
|
||||
} else {
|
||||
writeDiagnostic("Telemetry ping " + i + " matches.");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateTelemetryPingData(expected, received) {
|
||||
const receivedDate = new Date(received.creationDate);
|
||||
if (received.id != expected.id ||
|
||||
received.type != expected.type ||
|
||||
receivedDate.getTime() != expected.date.getTime()) {
|
||||
writeDiagnostic("Telemetry ping data for " + expected.id + " doesn't match.");
|
||||
writeDiagnostic("Expected: " + JSON.stringify(expected));
|
||||
writeDiagnostic("Received: " + JSON.stringify(received));
|
||||
return false;
|
||||
}
|
||||
|
||||
writeDiagnostic("Telemetry ping data for " + expected.id + " matched.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{
|
||||
info: "Checking initial value is enabled",
|
||||
event: "RequestCurrentPrefs",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, true);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying disabling works",
|
||||
event: "DisableDataSubmission",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, false);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we're still disabled",
|
||||
event: "RequestCurrentPrefs",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, false);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we can get a payload while submission is disabled",
|
||||
event: "RequestCurrentPayload",
|
||||
payloadType: "payload",
|
||||
validateResponse: function(payload) {
|
||||
return validatePayload(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying enabling works",
|
||||
event: "EnableDataSubmission",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, true);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we're still re-enabled",
|
||||
event: "RequestCurrentPrefs",
|
||||
payloadType: "prefs",
|
||||
validateResponse: function(payload) {
|
||||
return checkSubmissionValue(payload, true);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying we can get a payload after re-enabling",
|
||||
event: "RequestCurrentPayload",
|
||||
payloadType: "payload",
|
||||
validateResponse: function(payload) {
|
||||
return validatePayload(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying that we can get the current Telemetry environment data",
|
||||
event: "RequestCurrentEnvironment",
|
||||
payloadType: "telemetry-current-environment-data",
|
||||
validateResponse: function(payload) {
|
||||
return validateCurrentTelemetryEnvironment(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying that we can get the current Telemetry ping data",
|
||||
event: "RequestCurrentPingData",
|
||||
payloadType: "telemetry-current-ping-data",
|
||||
validateResponse: function(payload) {
|
||||
return validateCurrentTelemetryPingData(payload);
|
||||
},
|
||||
},
|
||||
{
|
||||
info: "Verifying that we get the proper Telemetry ping list",
|
||||
event: "RequestTelemetryPingList",
|
||||
payloadType: "telemetry-ping-list",
|
||||
validateResponse: function(payload) {
|
||||
// Validate the ping list
|
||||
if (!validateTelemetryPingList(payload)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now that we received the ping ids, set up additional test tasks
|
||||
// that check loading the individual pings.
|
||||
for (let i=0; i<TEST_PINGS.length; ++i) {
|
||||
TEST_PINGS[i].id = payload[i].id;
|
||||
tests.push({
|
||||
info: "Verifying that we can get the proper Telemetry ping data #" + (i + 1),
|
||||
event: "RequestTelemetryPingData",
|
||||
eventData: { id: TEST_PINGS[i].id },
|
||||
payloadType: "telemetry-ping-data",
|
||||
validateResponse: function(payload) {
|
||||
return validateTelemetryPingData(TEST_PINGS[i], payload.pingData);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
var currentTest = -1;
|
||||
function doTest(evt) {
|
||||
if (evt) {
|
||||
if (currentTest < 0 || !evt.data.content)
|
||||
return; // not yet testing
|
||||
|
||||
var test = tests[currentTest];
|
||||
if (evt.data.type != test.payloadType)
|
||||
return; // skip unrequested events
|
||||
|
||||
var error = JSON.stringify(evt.data.content);
|
||||
var pass = false;
|
||||
try {
|
||||
pass = test.validateResponse(evt.data.content)
|
||||
} catch (e) {}
|
||||
reportResult(test.info, pass, error);
|
||||
}
|
||||
// start the next test if there are any left
|
||||
if (tests[++currentTest])
|
||||
sendToBrowser(tests[currentTest].event, tests[currentTest].eventData);
|
||||
else
|
||||
reportFinished();
|
||||
}
|
||||
|
||||
function reportResult(info, pass, error) {
|
||||
var data = {type: "testResult", info: info, pass: pass, error: error};
|
||||
var event = new CustomEvent("FirefoxHealthReportTestResponse", {detail: {data: data}, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function reportFinished(cmd) {
|
||||
var data = {type: "testsComplete", count: tests.length};
|
||||
var event = new CustomEvent("FirefoxHealthReportTestResponse", {detail: {data: data}, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function sendToBrowser(type, eventData) {
|
||||
eventData = eventData || {};
|
||||
let detail = {command: type};
|
||||
for (let key of Object.keys(eventData)) {
|
||||
detail[key] = eventData[key];
|
||||
}
|
||||
|
||||
var event = new CustomEvent("RemoteHealthReportCommand", {detail: detail, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3071,6 +3071,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
let viewsLeft = this._viewsLeft;
|
||||
if (viewsLeft) {
|
||||
let notification = this._panel.firstElementChild.notification;
|
||||
if (this._notificationType == "passwords" && notification && notification.options &&
|
||||
notification.options.origin) {
|
||||
let fxAOrigin = new URL(Services.prefs.getCharPref("identity.fxaccounts.remote.signup.uri")).origin
|
||||
if (notification.options.origin == fxAOrigin) {
|
||||
// Somewhat gross hack - we don't want to show the sync promo while
|
||||
// the user may be logging into Sync.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue("services.sync.username") &&
|
||||
this._notificationType != "addons-sync-disabled") {
|
||||
// If the user has already setup Sync, don't show the notification.
|
||||
|
@ -12,6 +12,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryController.jsm");
|
||||
|
||||
Cu.importGlobalProperties(["URL"]);
|
||||
|
||||
@ -1978,6 +1979,16 @@ const DAILY_DISCRETE_TEXT_FIELD = Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT;
|
||||
*/
|
||||
const UITourHealthReport = {
|
||||
recordTreatmentTag: function(tag, value) {
|
||||
TelemetryController.submitExternalPing("uitour-tag",
|
||||
{
|
||||
version: 1,
|
||||
tagName: tag,
|
||||
tagValue: value,
|
||||
},
|
||||
{
|
||||
addClientId: true,
|
||||
addEnvironment: true,
|
||||
});
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
Task.spawn(function*() {
|
||||
let reporter = Cc["@mozilla.org/datareporting/service;1"]
|
||||
|
@ -8,6 +8,7 @@ let gContentAPI;
|
||||
let gContentWindow;
|
||||
|
||||
Components.utils.import("resource:///modules/UITour.jsm");
|
||||
Components.utils.import("resource://testing-common/TelemetryArchiveTesting.jsm", this);
|
||||
|
||||
function test() {
|
||||
UITourTest();
|
||||
@ -400,13 +401,24 @@ let tests = [
|
||||
});
|
||||
});
|
||||
},
|
||||
function test_treatment_tag(done) {
|
||||
taskify(function* test_treatment_tag(done) {
|
||||
let ac = new TelemetryArchiveTesting.Checker();
|
||||
yield ac.promiseInit();
|
||||
gContentAPI.setTreatmentTag("foobar", "baz");
|
||||
gContentAPI.getTreatmentTag("foobar", (data) => {
|
||||
is(data.value, "baz", "set and retrieved treatmentTag");
|
||||
done();
|
||||
ac.promiseFindPing("uitour-tag", [
|
||||
[["payload", "tagName"], "foobar"],
|
||||
[["payload", "tagValue"], "baz"],
|
||||
]).then((found) => {
|
||||
ok(found, "Telemetry ping submitted for setTreatmentTag");
|
||||
done();
|
||||
}, (err) => {
|
||||
ok(false, "Exeption finding uitour telemetry ping: " + err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
// Make sure this test is last in the file so the appMenu gets left open and done will confirm it got tore down.
|
||||
taskify(function* cleanupMenus() {
|
||||
|
@ -1,3 +1 @@
|
||||
41.0a1
|
||||
# Version to display in the about box:
|
||||
41.0a1
|
||||
|
1
browser/config/version_about.txt
Normal file
@ -0,0 +1 @@
|
||||
41.0a1
|
@ -22,6 +22,7 @@ support-files =
|
||||
[browser_ignore_toolbox_network_requests.js]
|
||||
[browser_keybindings_01.js]
|
||||
[browser_keybindings_02.js]
|
||||
[browser_keybindings_03.js]
|
||||
[browser_new_activation_workflow.js]
|
||||
[browser_target_events.js]
|
||||
[browser_target_remote.js]
|
||||
|
43
browser/devtools/framework/test/browser_keybindings_03.js
Normal file
@ -0,0 +1,43 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the toolbox 'switch to previous host' feature works.
|
||||
// Pressing ctrl/cmd+shift+d should switch to the last used host.
|
||||
|
||||
const URL = "data:text/html;charset=utf8,test page for toolbox switching";
|
||||
|
||||
add_task(function*() {
|
||||
info("Create a test tab and open the toolbox");
|
||||
let tab = yield addTab(URL);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "webconsole");
|
||||
|
||||
let keyElement = toolbox.doc.getElementById("toolbox-toggle-host-key");
|
||||
|
||||
let {SIDE, BOTTOM, WINDOW} = devtools.Toolbox.HostType;
|
||||
checkHostType(toolbox, BOTTOM, SIDE);
|
||||
|
||||
info ("Switching from bottom to side");
|
||||
synthesizeKeyElement(keyElement);
|
||||
yield toolbox.once("host-changed");
|
||||
checkHostType(toolbox, SIDE, BOTTOM);
|
||||
|
||||
info ("Switching from side to bottom");
|
||||
synthesizeKeyElement(keyElement);
|
||||
yield toolbox.once("host-changed");
|
||||
checkHostType(toolbox, BOTTOM, SIDE);
|
||||
|
||||
info ("Switching to window");
|
||||
yield toolbox.switchHost(WINDOW);
|
||||
checkHostType(toolbox, WINDOW, BOTTOM);
|
||||
|
||||
info ("Switching from window to bottom");
|
||||
synthesizeKeyElement(keyElement);
|
||||
yield toolbox.once("host-changed");
|
||||
checkHostType(toolbox, BOTTOM, WINDOW);
|
||||
|
||||
yield toolbox.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
@ -2,37 +2,35 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let temp = {}
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm", temp);
|
||||
let DevTools = temp.DevTools;
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", temp);
|
||||
let devtools = temp.devtools;
|
||||
|
||||
let Toolbox = devtools.Toolbox;
|
||||
"use strict";
|
||||
|
||||
let {SIDE, BOTTOM, WINDOW} = devtools.Toolbox.HostType;
|
||||
let toolbox, target;
|
||||
|
||||
function test()
|
||||
{
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
const URL = "data:text/html;charset=utf8,test for opening toolbox in different hosts";
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
gDevTools.showToolbox(target)
|
||||
.then(testBottomHost, console.error)
|
||||
.then(null, console.error);
|
||||
}, true);
|
||||
add_task(function* runTest() {
|
||||
info("Create a test tab and open the toolbox");
|
||||
let tab = yield addTab(URL);
|
||||
target = TargetFactory.forTab(tab);
|
||||
toolbox = yield gDevTools.showToolbox(target, "webconsole");
|
||||
|
||||
content.location = "data:text/html,test for opening toolbox in different hosts";
|
||||
}
|
||||
yield testBottomHost();
|
||||
yield testSidebarHost();
|
||||
yield testWindowHost();
|
||||
yield testToolSelect();
|
||||
yield testDestroy();
|
||||
yield testRememberHost();
|
||||
yield testPreviousHost();
|
||||
|
||||
function testBottomHost(aToolbox)
|
||||
{
|
||||
toolbox = aToolbox;
|
||||
yield toolbox.destroy();
|
||||
|
||||
checkHostType(Toolbox.HostType.BOTTOM);
|
||||
toolbox = target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function* testBottomHost() {
|
||||
checkHostType(toolbox, BOTTOM);
|
||||
|
||||
// test UI presence
|
||||
let nbox = gBrowser.getNotificationBox();
|
||||
@ -40,13 +38,11 @@ function testBottomHost(aToolbox)
|
||||
ok(iframe, "toolbox bottom iframe exists");
|
||||
|
||||
checkToolboxLoaded(iframe);
|
||||
|
||||
toolbox.switchHost(Toolbox.HostType.SIDE).then(testSidebarHost);
|
||||
}
|
||||
|
||||
function testSidebarHost()
|
||||
{
|
||||
checkHostType(Toolbox.HostType.SIDE);
|
||||
function* testSidebarHost() {
|
||||
yield toolbox.switchHost(SIDE);
|
||||
checkHostType(toolbox, SIDE);
|
||||
|
||||
// test UI presence
|
||||
let nbox = gBrowser.getNotificationBox();
|
||||
@ -57,13 +53,11 @@ function testSidebarHost()
|
||||
ok(iframe, "toolbox side iframe exists");
|
||||
|
||||
checkToolboxLoaded(iframe);
|
||||
|
||||
toolbox.switchHost(Toolbox.HostType.WINDOW).then(testWindowHost);
|
||||
}
|
||||
|
||||
function testWindowHost()
|
||||
{
|
||||
checkHostType(Toolbox.HostType.WINDOW);
|
||||
function* testWindowHost() {
|
||||
yield toolbox.switchHost(WINDOW);
|
||||
checkHostType(toolbox, WINDOW);
|
||||
|
||||
let nbox = gBrowser.getNotificationBox();
|
||||
let sidebar = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-side-iframe");
|
||||
@ -74,57 +68,70 @@ function testWindowHost()
|
||||
|
||||
let iframe = win.document.getElementById("toolbox-iframe");
|
||||
checkToolboxLoaded(iframe);
|
||||
|
||||
testToolSelect();
|
||||
}
|
||||
|
||||
function testToolSelect()
|
||||
{
|
||||
function* testToolSelect() {
|
||||
// make sure we can load a tool after switching hosts
|
||||
toolbox.selectTool("inspector").then(testDestroy);
|
||||
yield toolbox.selectTool("inspector");
|
||||
}
|
||||
|
||||
function testDestroy()
|
||||
{
|
||||
toolbox.destroy().then(function() {
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target).then(testRememberHost);
|
||||
});
|
||||
function* testDestroy() {
|
||||
yield toolbox.destroy();
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
toolbox = yield gDevTools.showToolbox(target);
|
||||
}
|
||||
|
||||
function testRememberHost(aToolbox)
|
||||
{
|
||||
toolbox = aToolbox;
|
||||
function* testRememberHost() {
|
||||
// last host was the window - make sure it's the same when re-opening
|
||||
is(toolbox.hostType, Toolbox.HostType.WINDOW, "host remembered");
|
||||
is(toolbox.hostType, WINDOW, "host remembered");
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("devtools:toolbox");
|
||||
ok(win, "toolbox separate window exists");
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
function checkHostType(hostType)
|
||||
{
|
||||
is(toolbox.hostType, hostType, "host type is " + hostType);
|
||||
function* testPreviousHost() {
|
||||
// last host was the window - make sure it's the same when re-opening
|
||||
is(toolbox.hostType, WINDOW, "host remembered");
|
||||
|
||||
let pref = Services.prefs.getCharPref("devtools.toolbox.host");
|
||||
is(pref, hostType, "host pref is " + hostType);
|
||||
info("Switching to side");
|
||||
yield toolbox.switchHost(SIDE);
|
||||
checkHostType(toolbox, SIDE, WINDOW);
|
||||
|
||||
info("Switching to bottom");
|
||||
yield toolbox.switchHost(BOTTOM);
|
||||
checkHostType(toolbox, BOTTOM, SIDE);
|
||||
|
||||
info("Switching from bottom to side");
|
||||
yield toolbox.switchToPreviousHost();
|
||||
checkHostType(toolbox, SIDE, BOTTOM);
|
||||
|
||||
info("Switching from side to bottom");
|
||||
yield toolbox.switchToPreviousHost();
|
||||
checkHostType(toolbox, BOTTOM, SIDE);
|
||||
|
||||
info("Switching to window");
|
||||
yield toolbox.switchHost(WINDOW);
|
||||
checkHostType(toolbox, WINDOW, BOTTOM);
|
||||
|
||||
info("Switching from window to bottom");
|
||||
yield toolbox.switchToPreviousHost();
|
||||
checkHostType(toolbox, BOTTOM, WINDOW);
|
||||
|
||||
info("Forcing the previous host to match the current (bottom)")
|
||||
Services.prefs.setCharPref("devtools.toolbox.previousHost", BOTTOM);
|
||||
|
||||
info("Switching from bottom to side (since previous=current=bottom");
|
||||
yield toolbox.switchToPreviousHost();
|
||||
checkHostType(toolbox, SIDE, BOTTOM);
|
||||
|
||||
info("Forcing the previous host to match the current (side)")
|
||||
Services.prefs.setCharPref("devtools.toolbox.previousHost", SIDE);
|
||||
info("Switching from side to bottom (since previous=current=side");
|
||||
yield toolbox.switchToPreviousHost();
|
||||
checkHostType(toolbox, BOTTOM, SIDE);
|
||||
}
|
||||
|
||||
function checkToolboxLoaded(iframe)
|
||||
{
|
||||
function checkToolboxLoaded(iframe) {
|
||||
let tabs = iframe.contentDocument.getElementById("toolbox-tabs");
|
||||
ok(tabs, "toolbox UI has been loaded into iframe");
|
||||
}
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM);
|
||||
|
||||
toolbox.destroy().then(function() {
|
||||
DevTools = Toolbox = toolbox = target = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -68,15 +68,6 @@ function testAllTheTools(docked, callback, toolNum=0) {
|
||||
});
|
||||
}
|
||||
|
||||
function synthesizeKeyForToolbox(keyId) {
|
||||
let el = toolbox.doc.getElementById(keyId);
|
||||
let key = el.getAttribute("key") || el.getAttribute("keycode");
|
||||
let mod = {};
|
||||
el.getAttribute("modifiers").split(" ").forEach((m) => mod[m+"Key"] = true);
|
||||
info("Synthesizing: key="+key+", mod="+JSON.stringify(mod));
|
||||
EventUtils.synthesizeKey(key, mod, toolbox.doc.defaultView);
|
||||
}
|
||||
|
||||
function testReload(key, docked, toolID, callback) {
|
||||
let complete = () => {
|
||||
gBrowser.selectedBrowser.messageManager.removeMessageListener("devtools:test:load", complete);
|
||||
@ -86,7 +77,8 @@ function testReload(key, docked, toolID, callback) {
|
||||
|
||||
description = docked+" devtools with tool "+toolID+", key #" + key;
|
||||
info("Testing reload in "+description);
|
||||
synthesizeKeyForToolbox(key);
|
||||
let el = toolbox.doc.getElementById(key);
|
||||
synthesizeKeyElement(el);
|
||||
reloadsSent++;
|
||||
}
|
||||
|
||||
|
@ -109,3 +109,36 @@ function executeInContent(name, data={}, objects={}, expectResponse=true) {
|
||||
return promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a keypress from a <key> element, taking into account
|
||||
* any modifiers.
|
||||
* @param {Element} el the <key> element to synthesize
|
||||
*/
|
||||
function synthesizeKeyElement(el) {
|
||||
let key = el.getAttribute("key") || el.getAttribute("keycode");
|
||||
let mod = {};
|
||||
el.getAttribute("modifiers").split(" ").forEach((m) => mod[m+"Key"] = true);
|
||||
info(`Synthesizing: key=${key}, mod=${JSON.stringify(mod)}`);
|
||||
EventUtils.synthesizeKey(key, mod, el.ownerDocument.defaultView);
|
||||
}
|
||||
|
||||
/* Check the toolbox host type and prefs to make sure they match the
|
||||
* expected values
|
||||
* @param {Toolbox}
|
||||
* @param {HostType} hostType
|
||||
* One of {SIDE, BOTTOM, WINDOW} from devtools.Toolbox.HostType
|
||||
* @param {HostType} Optional previousHostType
|
||||
* The host that will be switched to when calling switchToPreviousHost
|
||||
*/
|
||||
function checkHostType(toolbox, hostType, previousHostType) {
|
||||
is(toolbox.hostType, hostType, "host type is " + hostType);
|
||||
|
||||
let pref = Services.prefs.getCharPref("devtools.toolbox.host");
|
||||
is(pref, hostType, "host pref is " + hostType);
|
||||
|
||||
if (previousHostType) {
|
||||
is (Services.prefs.getCharPref("devtools.toolbox.previousHost"),
|
||||
previousHostType, "The previous host is correct");
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,11 @@ function getFrameScript() {
|
||||
}
|
||||
|
||||
gDevTools.testing = true;
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
registerCleanupFunction(() => {
|
||||
gDevTools.testing = false;
|
||||
Services.prefs.clearUserPref("devtools.dump.emit");
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
Services.prefs.clearUserPref("devtools.toolbox.previousHost");
|
||||
});
|
||||
|
||||
registerCleanupFunction(function cleanup() {
|
||||
|
@ -188,7 +188,8 @@ Toolbox.prototype = {
|
||||
_prefs: {
|
||||
LAST_HOST: "devtools.toolbox.host",
|
||||
LAST_TOOL: "devtools.toolbox.selectedTool",
|
||||
SIDE_ENABLED: "devtools.toolbox.sideEnabled"
|
||||
SIDE_ENABLED: "devtools.toolbox.sideEnabled",
|
||||
PREVIOUS_HOST: "devtools.toolbox.previousHost"
|
||||
},
|
||||
|
||||
currentToolId: null,
|
||||
@ -497,12 +498,16 @@ Toolbox.prototype = {
|
||||
_addHostListeners: function() {
|
||||
let nextKey = this.doc.getElementById("toolbox-next-tool-key");
|
||||
nextKey.addEventListener("command", this.selectNextTool.bind(this), true);
|
||||
|
||||
let prevKey = this.doc.getElementById("toolbox-previous-tool-key");
|
||||
prevKey.addEventListener("command", this.selectPreviousTool.bind(this), true);
|
||||
|
||||
let minimizeKey = this.doc.getElementById("toolbox-minimize-key");
|
||||
minimizeKey.addEventListener("command", this._toggleMinimizeMode, true);
|
||||
|
||||
let toggleKey = this.doc.getElementById("toolbox-toggle-host-key");
|
||||
toggleKey.addEventListener("command", this.switchToPreviousHost.bind(this), true);
|
||||
|
||||
// Split console uses keypress instead of command so the event can be
|
||||
// cancelled with stopPropagation on the keypress, and not preventDefault.
|
||||
this.doc.addEventListener("keypress", this._splitConsoleOnKeypress, false);
|
||||
@ -1579,6 +1584,26 @@ Toolbox.prototype = {
|
||||
return newHost;
|
||||
},
|
||||
|
||||
/**
|
||||
* Switch to the last used host for the toolbox UI.
|
||||
* This is determined by the devtools.toolbox.previousHost pref.
|
||||
*/
|
||||
switchToPreviousHost: function() {
|
||||
let hostType = Services.prefs.getCharPref(this._prefs.PREVIOUS_HOST);
|
||||
|
||||
// Handle the case where the previous host happens to match the current
|
||||
// host. If so, switch to bottom if it's not already used, and side if not.
|
||||
if (hostType === this._host.type) {
|
||||
if (hostType === Toolbox.HostType.BOTTOM) {
|
||||
hostType = Toolbox.HostType.SIDE;
|
||||
} else {
|
||||
hostType = Toolbox.HostType.BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
return this.switchHost(hostType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Switch to a new host for the toolbox UI. E.g. bottom, sidebar, window,
|
||||
* and focus the window when done.
|
||||
@ -1607,10 +1632,12 @@ Toolbox.prototype = {
|
||||
this._host.off("window-closed", this.destroy);
|
||||
this.destroyHost();
|
||||
|
||||
let prevHostType = this._host.type;
|
||||
this._host = newHost;
|
||||
|
||||
if (this.hostType != Toolbox.HostType.CUSTOM) {
|
||||
Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
|
||||
Services.prefs.setCharPref(this._prefs.PREVIOUS_HOST, prevHostType);
|
||||
}
|
||||
|
||||
this._buildDockButtons();
|
||||
|
@ -74,6 +74,10 @@
|
||||
key="&toolboxToggleMinimize.key;"
|
||||
oncommand="void(0);"
|
||||
modifiers="shift, accel"/>
|
||||
<key id="toolbox-toggle-host-key"
|
||||
key="&toolboxToggle.key;"
|
||||
oncommand="void(0);"
|
||||
modifiers="accel shift"/>
|
||||
</keyset>
|
||||
|
||||
<popupset>
|
||||
|
@ -264,8 +264,13 @@ var Scratchpad = {
|
||||
this._updateViewMenuItem(SHOW_LINE_NUMBERS, "sp-menu-line-numbers");
|
||||
this._updateViewMenuItem(WRAP_TEXT, "sp-menu-word-wrap");
|
||||
this._updateViewMenuItem(SHOW_TRAILING_SPACE, "sp-menu-highlight-trailing-space");
|
||||
this._updateViewFontMenuItem(MINIMUM_FONT_SIZE, "sp-cmd-smaller-font");
|
||||
this._updateViewFontMenuItem(MAXIMUM_FONT_SIZE, "sp-cmd-larger-font");
|
||||
},
|
||||
|
||||
/**
|
||||
* Check or uncheck view menu item according to stored preferences.
|
||||
*/
|
||||
_updateViewMenuItem: function SP_updateViewMenuItem(preferenceName, menuId) {
|
||||
let checked = Services.prefs.getBoolPref(preferenceName);
|
||||
if (checked) {
|
||||
@ -275,6 +280,16 @@ var Scratchpad = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable view menu item if the stored font size is equals to the given one.
|
||||
*/
|
||||
_updateViewFontMenuItem: function SP_updateViewFontMenuItem(fontSize, commandId) {
|
||||
let prefFontSize = Services.prefs.getIntPref(EDITOR_FONT_SIZE);
|
||||
if (prefFontSize === fontSize) {
|
||||
document.getElementById(commandId).setAttribute('disabled', true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The script execution context. This tells Scratchpad in which context the
|
||||
* script shall execute.
|
||||
@ -1939,6 +1954,12 @@ var Scratchpad = {
|
||||
let newFontSize = size + 1;
|
||||
this.editor.setFontSize(newFontSize);
|
||||
Services.prefs.setIntPref(EDITOR_FONT_SIZE, newFontSize);
|
||||
|
||||
if (newFontSize === MAXIMUM_FONT_SIZE) {
|
||||
document.getElementById("sp-cmd-larger-font").setAttribute('disabled', true);
|
||||
}
|
||||
|
||||
document.getElementById("sp-cmd-smaller-font").removeAttribute('disabled');
|
||||
}
|
||||
},
|
||||
|
||||
@ -1953,7 +1974,13 @@ var Scratchpad = {
|
||||
let newFontSize = size - 1;
|
||||
this.editor.setFontSize(newFontSize);
|
||||
Services.prefs.setIntPref(EDITOR_FONT_SIZE, newFontSize);
|
||||
|
||||
if (newFontSize === MINIMUM_FONT_SIZE) {
|
||||
document.getElementById("sp-cmd-smaller-font").setAttribute('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("sp-cmd-larger-font").removeAttribute('disabled');
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1963,6 +1990,9 @@ var Scratchpad = {
|
||||
{
|
||||
this.editor.setFontSize(NORMAL_FONT_SIZE);
|
||||
Services.prefs.setIntPref(EDITOR_FONT_SIZE, NORMAL_FONT_SIZE);
|
||||
|
||||
document.getElementById("sp-cmd-larger-font").removeAttribute('disabled');
|
||||
document.getElementById("sp-cmd-smaller-font").removeAttribute('disabled');
|
||||
},
|
||||
|
||||
_observers: [],
|
||||
|
@ -44,3 +44,4 @@ support-files = NS_ERROR_ILLEGAL_INPUT.txt
|
||||
[browser_scratchpad_ui.js]
|
||||
[browser_scratchpad_close_toolbox.js]
|
||||
[browser_scratchpad_remember_view_options.js]
|
||||
[browser_scratchpad_disable_view_menu_items.js]
|
||||
|
@ -0,0 +1,66 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test if the view menu items "Larger Font" and "Smaller Font" are disabled
|
||||
// when the font size reaches the maximum/minimum values.
|
||||
|
||||
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|
||||
function test() {
|
||||
const options = {
|
||||
tabContent: 'test if view menu items "Larger Font" and "Smaller Font" are enabled/disabled.'
|
||||
};
|
||||
openTabAndScratchpad(options)
|
||||
.then(Task.async(runTests))
|
||||
.then(finish, console.error);
|
||||
}
|
||||
|
||||
function* runTests([win, sp]) {
|
||||
yield testMaximumFontSize(win, sp);
|
||||
|
||||
yield testMinimumFontSize(win, sp);
|
||||
}
|
||||
|
||||
const MAXIMUM_FONT_SIZE = 96;
|
||||
const MINIMUM_FONT_SIZE = 6;
|
||||
const NORMAL_FONT_SIZE = 12;
|
||||
|
||||
let testMaximumFontSize = Task.async(function* (win, sp) {
|
||||
let doc = win.document;
|
||||
|
||||
Services.prefs.clearUserPref('devtools.scratchpad.editorFontSize');
|
||||
|
||||
let menu = doc.getElementById('sp-menu-larger-font');
|
||||
|
||||
for (let i = NORMAL_FONT_SIZE; i <= MAXIMUM_FONT_SIZE; i++) {
|
||||
menu.doCommand();
|
||||
}
|
||||
|
||||
let cmd = doc.getElementById('sp-cmd-larger-font');
|
||||
ok(cmd.getAttribute('disabled') === 'true', 'Command "sp-cmd-larger-font" is disabled.');
|
||||
|
||||
menu = doc.getElementById('sp-menu-smaller-font');
|
||||
menu.doCommand();
|
||||
|
||||
ok(cmd.hasAttribute('disabled') === false, 'Command "sp-cmd-larger-font" is enabled.');
|
||||
});
|
||||
|
||||
let testMinimumFontSize = Task.async(function* (win, sp) {
|
||||
let doc = win.document;
|
||||
|
||||
let menu = doc.getElementById('sp-menu-smaller-font');
|
||||
|
||||
for (let i = MAXIMUM_FONT_SIZE; i >= MINIMUM_FONT_SIZE; i--) {
|
||||
menu.doCommand();
|
||||
}
|
||||
|
||||
let cmd = doc.getElementById('sp-cmd-smaller-font');
|
||||
ok(cmd.getAttribute('disabled') === 'true', 'Command "sp-cmd-smaller-font" is disabled.');
|
||||
|
||||
menu = doc.getElementById('sp-menu-larger-font');
|
||||
menu.doCommand();
|
||||
|
||||
ok(cmd.hasAttribute('disabled') === false, 'Command "sp-cmd-smaller-font" is enabled.');
|
||||
|
||||
Services.prefs.clearUserPref('devtools.scratchpad.editorFontSize');
|
||||
});
|
@ -24,6 +24,7 @@
|
||||
<!-- This key is used with the accel+shift modifiers to minimize the toolbox -->
|
||||
<!ENTITY toolboxToggleMinimize.key "U">
|
||||
|
||||
<!ENTITY toolboxToggle.key "d">
|
||||
<!-- LOCALIZATION NOTE (toolboxFramesButton): This is the label for
|
||||
- the iframes menu list that appears only when the document has some.
|
||||
- It allows you to switch the context of the whole toolbox. -->
|
||||
|
@ -680,17 +680,17 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
}
|
||||
|
||||
#back-button {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
-moz-margin-start: 5px;
|
||||
padding: 0;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
-moz-padding-start: 5px;
|
||||
-moz-padding-end: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
border-radius: 10000px;
|
||||
border-radius: 0 10000px 10000px 0;
|
||||
}
|
||||
|
||||
#back-button:not(:-moz-lwtheme) {
|
||||
background-color: -moz-dialog;
|
||||
#back-button:-moz-locale-dir(rtl) {
|
||||
border-radius: 10000px 0 0 10000px;
|
||||
}
|
||||
|
||||
#back-button > menupopup {
|
||||
@ -894,17 +894,13 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@ {
|
||||
clip-path: url("chrome://browser/content/browser.xul#urlbar-clip-path");
|
||||
-moz-margin-start: -5px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:-moz-lwtheme {
|
||||
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
|
||||
-moz-margin-start: -5px;
|
||||
}
|
||||
|
||||
@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl),
|
||||
@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) {
|
||||
/* Let clip-path clip the urlbar-wrapper's right side for RTL. */
|
||||
/* let urlbar-back-button-clip-path clip the urlbar's right side for RTL */
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
|
@ -117,15 +117,24 @@ browser.jar:
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
* skin/classic/browser/readinglist/sidebar.css (readinglist/sidebar.css)
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/browser/webRTC-shareDevice-16.png (../shared/webrtc/webRTC-shareDevice-16.png)
|
||||
skin/classic/browser/webRTC-shareDevice-16@2x.png (../shared/webrtc/webRTC-shareDevice-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareDevice-64.png (../shared/webrtc/webRTC-shareDevice-64.png)
|
||||
skin/classic/browser/webRTC-shareDevice-64@2x.png (../shared/webrtc/webRTC-shareDevice-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png (../shared/webrtc/webRTC-sharingDevice-16.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16.png
|
||||
skin/classic/browser/webRTC-shareMicrophone-64.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16@2x.png (../shared/webrtc/webRTC-sharingDevice-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16.png (../shared/webrtc/webRTC-shareMicrophone-16.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16@2x.png (../shared/webrtc/webRTC-shareMicrophone-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-64.png (../shared/webrtc/webRTC-shareMicrophone-64.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-64@2x.png (../shared/webrtc/webRTC-shareMicrophone-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingMicrophone-16.png (../shared/webrtc/webRTC-sharingMicrophone-16.png)
|
||||
skin/classic/browser/webRTC-sharingMicrophone-16@2x.png (../shared/webrtc/webRTC-sharingMicrophone-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareScreen-16.png (../shared/webrtc/webRTC-shareScreen-16.png)
|
||||
skin/classic/browser/webRTC-shareScreen-16@2x.png (../shared/webrtc/webRTC-shareScreen-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareScreen-64.png (../shared/webrtc/webRTC-shareScreen-64.png)
|
||||
skin/classic/browser/webRTC-shareScreen-64@2x.png (../shared/webrtc/webRTC-shareScreen-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingScreen-16.png (../shared/webrtc/webRTC-sharingScreen-16.png)
|
||||
skin/classic/browser/webRTC-sharingScreen-16@2x.png (../shared/webrtc/webRTC-sharingScreen-16@2x.png)
|
||||
skin/classic/browser/webRTC-indicator.css (../shared/webrtc/indicator.css)
|
||||
skin/classic/browser/webRTC-camera-white-16.png (../shared/webrtc/camera-white-16.png)
|
||||
skin/classic/browser/webRTC-microphone-white-16.png (../shared/webrtc/microphone-white-16.png)
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.8 KiB |
@ -155,16 +155,16 @@ browser.jar:
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
* skin/classic/browser/readinglist/sidebar.css (readinglist/sidebar.css)
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-16@2x.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/browser/webRTC-shareDevice-64@2x.png
|
||||
skin/classic/browser/webRTC-shareDevice-16.png (../shared/webrtc/webRTC-shareDevice-16.png)
|
||||
skin/classic/browser/webRTC-shareDevice-16@2x.png (../shared/webrtc/webRTC-shareDevice-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareDevice-64.png (../shared/webrtc/webRTC-shareDevice-64.png)
|
||||
skin/classic/browser/webRTC-shareDevice-64@2x.png (../shared/webrtc/webRTC-shareDevice-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png (../shared/webrtc/webRTC-sharingDevice-16.png)
|
||||
skin/classic/browser/webRTC-sharingDevice-16@2x.png (../shared/webrtc/webRTC-sharingDevice-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16.png
|
||||
skin/classic/browser/webRTC-shareMicrophone-16@2x.png
|
||||
skin/classic/browser/webRTC-shareMicrophone-64.png
|
||||
skin/classic/browser/webRTC-shareMicrophone-64@2x.png
|
||||
skin/classic/browser/webRTC-shareMicrophone-16.png (../shared/webrtc/webRTC-shareMicrophone-16.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16@2x.png (../shared/webrtc/webRTC-shareMicrophone-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-64.png (../shared/webrtc/webRTC-shareMicrophone-64.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-64@2x.png (../shared/webrtc/webRTC-shareMicrophone-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingMicrophone-16.png (../shared/webrtc/webRTC-sharingMicrophone-16.png)
|
||||
skin/classic/browser/webRTC-sharingMicrophone-16@2x.png (../shared/webrtc/webRTC-sharingMicrophone-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareScreen-16.png (../shared/webrtc/webRTC-shareScreen-16.png)
|
||||
|
Before Width: | Height: | Size: 224 B |
Before Width: | Height: | Size: 1.1 KiB |
@ -318,6 +318,51 @@
|
||||
border-image: url("chrome://browser/skin/urlbar-arrow@2x.png") 0 16 0 0 fill;
|
||||
}
|
||||
|
||||
.webRTC-shareDevices-notification-icon,
|
||||
#webRTC-shareDevices-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-sharingDevices-notification-icon,
|
||||
#webRTC-sharingDevices-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-shareMicrophone-notification-icon,
|
||||
#webRTC-shareMicrophone-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-sharingMicrophone-notification-icon,
|
||||
#webRTC-sharingMicrophone-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingMicrophone-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-shareScreen-notification-icon,
|
||||
#webRTC-shareScreen-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-sharingScreen-notification-icon,
|
||||
#webRTC-sharingScreen-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingScreen-16@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="webRTC-sharingDevices"],
|
||||
.popup-notification-icon[popupid="webRTC-shareDevices"] {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="webRTC-sharingMicrophone"],
|
||||
.popup-notification-icon[popupid="webRTC-shareMicrophone"] {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-64@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="webRTC-sharingScreen"],
|
||||
.popup-notification-icon[popupid="webRTC-shareScreen"] {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-64@2x.png);
|
||||
}
|
||||
|
||||
%ifdef XP_MACOSX
|
||||
/* OSX only until we have icons for Windows and Linux */
|
||||
.default-notification-icon,
|
||||
@ -381,36 +426,6 @@
|
||||
list-style-image: url(chrome://browser/skin/bad-content-unblocked-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-shareDevices-notification-icon,
|
||||
#webRTC-shareDevices-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-sharingDevices-notification-icon,
|
||||
#webRTC-sharingDevices-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-shareMicrophone-notification-icon,
|
||||
#webRTC-shareMicrophone-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-sharingMicrophone-notification-icon,
|
||||
#webRTC-sharingMicrophone-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingMicrophone-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-shareScreen-notification-icon,
|
||||
#webRTC-shareScreen-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-16@2x.png);
|
||||
}
|
||||
|
||||
.webRTC-sharingScreen-notification-icon,
|
||||
#webRTC-sharingScreen-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingScreen-16@2x.png);
|
||||
}
|
||||
|
||||
.web-notifications-notification-icon,
|
||||
#web-notifications-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-16@2x.png);
|
||||
@ -458,21 +473,6 @@
|
||||
list-style-image: url(chrome://browser/skin/pointerLock-64@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="webRTC-sharingDevices"],
|
||||
.popup-notification-icon[popupid="webRTC-shareDevices"] {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="webRTC-sharingMicrophone"],
|
||||
.popup-notification-icon[popupid="webRTC-shareMicrophone"] {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-64@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="webRTC-sharingScreen"],
|
||||
.popup-notification-icon[popupid="webRTC-shareScreen"] {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-64@2x.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="servicesInstall"] {
|
||||
list-style-image: url(chrome://browser/skin/social/services-64@2x.png);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 224 B After Width: | Height: | Size: 224 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
@ -155,15 +155,24 @@ browser.jar:
|
||||
skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png)
|
||||
skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png)
|
||||
skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png)
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/browser/webRTC-shareDevice-16.png (../shared/webrtc/webRTC-shareDevice-16.png)
|
||||
skin/classic/browser/webRTC-shareDevice-16@2x.png (../shared/webrtc/webRTC-shareDevice-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareDevice-64.png (../shared/webrtc/webRTC-shareDevice-64.png)
|
||||
skin/classic/browser/webRTC-shareDevice-64@2x.png (../shared/webrtc/webRTC-shareDevice-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png (../shared/webrtc/webRTC-sharingDevice-16.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16.png
|
||||
skin/classic/browser/webRTC-shareMicrophone-64.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16@2x.png (../shared/webrtc/webRTC-sharingDevice-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16.png (../shared/webrtc/webRTC-shareMicrophone-16.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-16@2x.png (../shared/webrtc/webRTC-shareMicrophone-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-64.png (../shared/webrtc/webRTC-shareMicrophone-64.png)
|
||||
skin/classic/browser/webRTC-shareMicrophone-64@2x.png (../shared/webrtc/webRTC-shareMicrophone-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingMicrophone-16.png (../shared/webrtc/webRTC-sharingMicrophone-16.png)
|
||||
skin/classic/browser/webRTC-sharingMicrophone-16@2x.png (../shared/webrtc/webRTC-sharingMicrophone-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareScreen-16.png (../shared/webrtc/webRTC-shareScreen-16.png)
|
||||
skin/classic/browser/webRTC-shareScreen-16@2x.png (../shared/webrtc/webRTC-shareScreen-16@2x.png)
|
||||
skin/classic/browser/webRTC-shareScreen-64.png (../shared/webrtc/webRTC-shareScreen-64.png)
|
||||
skin/classic/browser/webRTC-shareScreen-64@2x.png (../shared/webrtc/webRTC-shareScreen-64@2x.png)
|
||||
skin/classic/browser/webRTC-sharingScreen-16.png (../shared/webrtc/webRTC-sharingScreen-16.png)
|
||||
skin/classic/browser/webRTC-sharingScreen-16@2x.png (../shared/webrtc/webRTC-sharingScreen-16@2x.png)
|
||||
skin/classic/browser/webRTC-indicator.css (../shared/webrtc/indicator.css)
|
||||
skin/classic/browser/webRTC-camera-white-16.png (../shared/webrtc/camera-white-16.png)
|
||||
skin/classic/browser/webRTC-microphone-white-16.png (../shared/webrtc/microphone-white-16.png)
|
||||
|
Before Width: | Height: | Size: 233 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 1.6 KiB |
@ -127,19 +127,20 @@ bool isInIgnoredNamespaceForImplicitCtor(const Decl *decl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return name == "std" || // standard C++ lib
|
||||
name == "__gnu_cxx" || // gnu C++ lib
|
||||
name == "boost" || // boost
|
||||
name == "webrtc" || // upstream webrtc
|
||||
name == "icu_52" || // icu
|
||||
name == "google" || // protobuf
|
||||
name == "google_breakpad" || // breakpad
|
||||
name == "soundtouch" || // libsoundtouch
|
||||
name == "stagefright" || // libstagefright
|
||||
name == "MacFileUtilities" || // MacFileUtilities
|
||||
name == "dwarf2reader" || // dwarf2reader
|
||||
name == "arm_ex_to_module" || // arm_ex_to_module
|
||||
name == "testing"; // gtest
|
||||
|
||||
return name == "std" || // standard C++ lib
|
||||
name == "__gnu_cxx" || // gnu C++ lib
|
||||
name == "boost" || // boost
|
||||
name == "webrtc" || // upstream webrtc
|
||||
name.substr(0, 4) == "icu_" || // icu
|
||||
name == "google" || // protobuf
|
||||
name == "google_breakpad" || // breakpad
|
||||
name == "soundtouch" || // libsoundtouch
|
||||
name == "stagefright" || // libstagefright
|
||||
name == "MacFileUtilities" || // MacFileUtilities
|
||||
name == "dwarf2reader" || // dwarf2reader
|
||||
name == "arm_ex_to_module" || // arm_ex_to_module
|
||||
name == "testing"; // gtest
|
||||
}
|
||||
|
||||
bool isInIgnoredNamespaceForImplicitConversion(const Decl *decl) {
|
||||
|
@ -1958,8 +1958,8 @@ MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsr
|
||||
MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion`
|
||||
|
||||
dnl Get version of various core apps from the version files.
|
||||
FIREFOX_VERSION=`cat $_topsrcdir/browser/config/version.txt|head -1`
|
||||
FIREFOX_VERSION_ABOUT=`cat $_topsrcdir/browser/config/version.txt|tail -1`
|
||||
FIREFOX_VERSION=`cat $_topsrcdir/browser/config/version.txt`
|
||||
FIREFOX_VERSION_ABOUT=`cat $_topsrcdir/browser/config/version_about.txt`
|
||||
|
||||
if test -z "$FIREFOX_VERSION"; then
|
||||
AC_MSG_ERROR([FIREFOX_VERSION is unexpectedly blank.])
|
||||
|
@ -203,6 +203,7 @@ this.DOMApplicationRegistry = {
|
||||
dirKey: DIRECTORY_NAME,
|
||||
|
||||
init: function() {
|
||||
// Keep the messages in sync with the lazy-loading in browser.js (bug 1171013).
|
||||
this.messages = ["Webapps:Install",
|
||||
"Webapps:Uninstall",
|
||||
"Webapps:GetSelf",
|
||||
|
@ -531,13 +531,13 @@ File::GetLastModified(ErrorResult& aRv)
|
||||
}
|
||||
|
||||
void
|
||||
File::GetMozFullPath(nsAString& aFilename, ErrorResult& aRv)
|
||||
File::GetMozFullPath(nsAString& aFilename, ErrorResult& aRv) const
|
||||
{
|
||||
mImpl->GetMozFullPath(aFilename, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv)
|
||||
File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
|
||||
{
|
||||
mImpl->GetMozFullPathInternal(aFileName, aRv);
|
||||
}
|
||||
@ -735,7 +735,7 @@ BlobImplBase::GetPath(nsAString& aPath, ErrorResult& aRv)
|
||||
}
|
||||
|
||||
void
|
||||
BlobImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv)
|
||||
BlobImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv) const
|
||||
{
|
||||
NS_ASSERTION(mIsFile, "Should only be called on files");
|
||||
|
||||
@ -759,7 +759,7 @@ BlobImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv)
|
||||
}
|
||||
|
||||
void
|
||||
BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv)
|
||||
BlobImplBase::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
|
||||
{
|
||||
if (!mIsFile) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
@ -950,7 +950,7 @@ BlobImplFile::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
}
|
||||
|
||||
void
|
||||
BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv)
|
||||
BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
|
||||
{
|
||||
NS_ASSERTION(mIsFile, "Should only be called on files");
|
||||
aRv = mFile->GetPath(aFilename);
|
||||
|
@ -261,9 +261,9 @@ public:
|
||||
|
||||
void GetPath(nsAString& aName, ErrorResult& aRv);
|
||||
|
||||
void GetMozFullPath(nsAString& aFilename, ErrorResult& aRv);
|
||||
void GetMozFullPath(nsAString& aFilename, ErrorResult& aRv) const;
|
||||
|
||||
void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv);
|
||||
void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const;
|
||||
|
||||
protected:
|
||||
virtual bool HasFileInterface() const override { return true; }
|
||||
@ -293,9 +293,9 @@ public:
|
||||
|
||||
virtual void SetLastModified(int64_t aLastModified) = 0;
|
||||
|
||||
virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) = 0;
|
||||
virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) const = 0;
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) = 0;
|
||||
virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const = 0;
|
||||
|
||||
virtual uint64_t GetSize(ErrorResult& aRv) = 0;
|
||||
|
||||
@ -434,10 +434,10 @@ public:
|
||||
|
||||
virtual void SetLastModified(int64_t aLastModified) override;
|
||||
|
||||
virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) override;
|
||||
virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) const override;
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFileName,
|
||||
ErrorResult& aRv) override;
|
||||
ErrorResult& aRv) const override;
|
||||
|
||||
virtual uint64_t GetSize(ErrorResult& aRv) override
|
||||
{
|
||||
@ -822,7 +822,7 @@ public:
|
||||
virtual int64_t GetLastModified(ErrorResult& aRv) override;
|
||||
virtual void SetLastModified(int64_t aLastModified) override;
|
||||
virtual void GetMozFullPathInternal(nsAString& aFullPath,
|
||||
ErrorResult& aRv) override;
|
||||
ErrorResult& aRv) const override;
|
||||
virtual void GetInternalStream(nsIInputStream** aInputStream,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
|
@ -240,7 +240,7 @@ MultipartBlobImpl::SetLengthAndModifiedDate()
|
||||
|
||||
void
|
||||
MultipartBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
|
||||
ErrorResult& aRv)
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
if (!mIsFromNsIFile || mBlobImpls.Length() == 0) {
|
||||
BlobImplBase::GetMozFullPathInternal(aFilename, aRv);
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void GetMozFullPathInternal(nsAString& aFullPath,
|
||||
ErrorResult& aRv) override;
|
||||
ErrorResult& aRv) const override;
|
||||
|
||||
virtual nsresult
|
||||
SetMutable(bool aMutable) override;
|
||||
|
@ -313,34 +313,7 @@ AutoJSAPI::~AutoJSAPI()
|
||||
if (mOwnErrorReporting) {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "See corresponding assertion in TakeOwnershipOfErrorReporting()");
|
||||
|
||||
if (HasException()) {
|
||||
|
||||
// AutoJSAPI uses a JSAutoNullableCompartment, and may be in a null
|
||||
// compartment when the destructor is called. However, the JS engine
|
||||
// requires us to be in a compartment when we fetch the pending exception.
|
||||
// In this case, we enter the privileged junk scope and don't dispatch any
|
||||
// error events.
|
||||
JS::Rooted<JSObject*> errorGlobal(cx(), JS::CurrentGlobalOrNull(cx()));
|
||||
if (!errorGlobal)
|
||||
errorGlobal = xpc::PrivilegedJunkScope();
|
||||
JSAutoCompartment ac(cx(), errorGlobal);
|
||||
nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
|
||||
JS::Rooted<JS::Value> exn(cx());
|
||||
js::ErrorReport jsReport(cx());
|
||||
if (StealException(&exn) && jsReport.init(cx(), exn)) {
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
xpcReport->Init(jsReport.report(), jsReport.message(),
|
||||
nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
if (win) {
|
||||
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn);
|
||||
} else {
|
||||
xpcReport->LogToConsole();
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("OOMed while acquiring uncaught exception from JSAPI");
|
||||
}
|
||||
}
|
||||
ReportException();
|
||||
|
||||
// We need to do this _after_ processing the existing exception, because the
|
||||
// JS engine can throw while doing that, and uses this bit to determine what
|
||||
@ -508,6 +481,41 @@ AutoJSAPI::TakeOwnershipOfErrorReporting()
|
||||
JS_SetErrorReporter(rt, WarningOnlyErrorReporter);
|
||||
}
|
||||
|
||||
void
|
||||
AutoJSAPI::ReportException()
|
||||
{
|
||||
MOZ_ASSERT(OwnsErrorReporting(), "This is not our exception to report!");
|
||||
if (!HasException()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// AutoJSAPI uses a JSAutoNullableCompartment, and may be in a null
|
||||
// compartment when the destructor is called. However, the JS engine
|
||||
// requires us to be in a compartment when we fetch the pending exception.
|
||||
// In this case, we enter the privileged junk scope and don't dispatch any
|
||||
// error events.
|
||||
JS::Rooted<JSObject*> errorGlobal(cx(), JS::CurrentGlobalOrNull(cx()));
|
||||
if (!errorGlobal)
|
||||
errorGlobal = xpc::PrivilegedJunkScope();
|
||||
JSAutoCompartment ac(cx(), errorGlobal);
|
||||
nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
|
||||
JS::Rooted<JS::Value> exn(cx());
|
||||
js::ErrorReport jsReport(cx());
|
||||
if (StealException(&exn) && jsReport.init(cx(), exn)) {
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
xpcReport->Init(jsReport.report(), jsReport.message(),
|
||||
nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
if (win) {
|
||||
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn);
|
||||
} else {
|
||||
xpcReport->LogToConsole();
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("OOMed while acquiring uncaught exception from JSAPI");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal)
|
||||
{
|
||||
|
@ -274,6 +274,9 @@ public:
|
||||
// while keeping the old behavior as the default.
|
||||
void TakeOwnershipOfErrorReporting();
|
||||
bool OwnsErrorReporting() { return mOwnErrorReporting; }
|
||||
// If HasException, report it. Otherwise, a no-op. This must be
|
||||
// called only if OwnsErrorReporting().
|
||||
void ReportException();
|
||||
|
||||
bool HasException() const {
|
||||
MOZ_ASSERT(CxPusherIsStackTop());
|
||||
|
@ -68,7 +68,7 @@ nsContentPolicy::~nsContentPolicy()
|
||||
inline nsresult
|
||||
nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
||||
SCPMethod simplePolicyMethod,
|
||||
uint32_t contentType,
|
||||
nsContentPolicyType contentType,
|
||||
nsIURI *contentLocation,
|
||||
nsIURI *requestingLocation,
|
||||
nsISupports *requestingContext,
|
||||
@ -110,6 +110,9 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
||||
}
|
||||
}
|
||||
|
||||
nsContentPolicyType externalType =
|
||||
nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
|
||||
|
||||
/*
|
||||
* Enumerate mPolicies and ask each of them, taking the logical AND of
|
||||
* their permissions.
|
||||
@ -120,7 +123,7 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
||||
int32_t count = entries.Count();
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
/* check the appropriate policy */
|
||||
rv = (entries[i]->*policyMethod)(contentType, contentLocation,
|
||||
rv = (entries[i]->*policyMethod)(externalType, contentLocation,
|
||||
requestingLocation, requestingContext,
|
||||
mimeType, extra, requestPrincipal,
|
||||
decision);
|
||||
@ -166,7 +169,7 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
||||
count = simpleEntries.Count();
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
/* check the appropriate policy */
|
||||
rv = (simpleEntries[i]->*simplePolicyMethod)(contentType, contentLocation,
|
||||
rv = (simpleEntries[i]->*simplePolicyMethod)(externalType, contentLocation,
|
||||
requestingLocation,
|
||||
topFrameElement, isTopLevel,
|
||||
mimeType, extra, requestPrincipal,
|
||||
|
@ -49,7 +49,7 @@ class nsContentPolicy : public nsIContentPolicy
|
||||
//Helper method that applies policyMethod across all policies in mPolicies
|
||||
// with the given parameters
|
||||
nsresult CheckPolicy(CPMethod policyMethod, SCPMethod simplePolicyMethod,
|
||||
uint32_t contentType,
|
||||
nsContentPolicyType contentType,
|
||||
nsIURI *aURI, nsIURI *origURI,
|
||||
nsISupports *requestingContext,
|
||||
const nsACString &mimeGuess, nsISupports *extra,
|
||||
|
@ -92,28 +92,38 @@ inline const char *
|
||||
NS_CP_ContentTypeName(uint32_t contentType)
|
||||
{
|
||||
switch (contentType) {
|
||||
CASE_RETURN( TYPE_OTHER );
|
||||
CASE_RETURN( TYPE_SCRIPT );
|
||||
CASE_RETURN( TYPE_IMAGE );
|
||||
CASE_RETURN( TYPE_STYLESHEET );
|
||||
CASE_RETURN( TYPE_OBJECT );
|
||||
CASE_RETURN( TYPE_DOCUMENT );
|
||||
CASE_RETURN( TYPE_SUBDOCUMENT );
|
||||
CASE_RETURN( TYPE_REFRESH );
|
||||
CASE_RETURN( TYPE_XBL );
|
||||
CASE_RETURN( TYPE_PING );
|
||||
CASE_RETURN( TYPE_XMLHTTPREQUEST );
|
||||
CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
|
||||
CASE_RETURN( TYPE_DTD );
|
||||
CASE_RETURN( TYPE_FONT );
|
||||
CASE_RETURN( TYPE_MEDIA );
|
||||
CASE_RETURN( TYPE_WEBSOCKET );
|
||||
CASE_RETURN( TYPE_CSP_REPORT );
|
||||
CASE_RETURN( TYPE_XSLT );
|
||||
CASE_RETURN( TYPE_BEACON );
|
||||
CASE_RETURN( TYPE_FETCH );
|
||||
CASE_RETURN( TYPE_IMAGESET );
|
||||
CASE_RETURN( TYPE_WEB_MANIFEST );
|
||||
CASE_RETURN( TYPE_OTHER );
|
||||
CASE_RETURN( TYPE_SCRIPT );
|
||||
CASE_RETURN( TYPE_IMAGE );
|
||||
CASE_RETURN( TYPE_STYLESHEET );
|
||||
CASE_RETURN( TYPE_OBJECT );
|
||||
CASE_RETURN( TYPE_DOCUMENT );
|
||||
CASE_RETURN( TYPE_SUBDOCUMENT );
|
||||
CASE_RETURN( TYPE_REFRESH );
|
||||
CASE_RETURN( TYPE_XBL );
|
||||
CASE_RETURN( TYPE_PING );
|
||||
CASE_RETURN( TYPE_XMLHTTPREQUEST );
|
||||
CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
|
||||
CASE_RETURN( TYPE_DTD );
|
||||
CASE_RETURN( TYPE_FONT );
|
||||
CASE_RETURN( TYPE_MEDIA );
|
||||
CASE_RETURN( TYPE_WEBSOCKET );
|
||||
CASE_RETURN( TYPE_CSP_REPORT );
|
||||
CASE_RETURN( TYPE_XSLT );
|
||||
CASE_RETURN( TYPE_BEACON );
|
||||
CASE_RETURN( TYPE_FETCH );
|
||||
CASE_RETURN( TYPE_IMAGESET );
|
||||
CASE_RETURN( TYPE_WEB_MANIFEST );
|
||||
CASE_RETURN( TYPE_INTERNAL_SCRIPT );
|
||||
CASE_RETURN( TYPE_INTERNAL_WORKER );
|
||||
CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER );
|
||||
CASE_RETURN( TYPE_INTERNAL_EMBED );
|
||||
CASE_RETURN( TYPE_INTERNAL_OBJECT );
|
||||
CASE_RETURN( TYPE_INTERNAL_FRAME );
|
||||
CASE_RETURN( TYPE_INTERNAL_IFRAME );
|
||||
CASE_RETURN( TYPE_INTERNAL_AUDIO );
|
||||
CASE_RETURN( TYPE_INTERNAL_VIDEO );
|
||||
CASE_RETURN( TYPE_INTERNAL_TRACK );
|
||||
default:
|
||||
return "<Unknown Type>";
|
||||
}
|
||||
|
@ -7812,3 +7812,31 @@ nsContentUtils::GetWindowRoot(nsIDocument* aDoc)
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsContentPolicyType
|
||||
nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
|
||||
{
|
||||
switch (aType) {
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
|
||||
return nsIContentPolicy::TYPE_SCRIPT;
|
||||
|
||||
case nsIContentPolicy::TYPE_INTERNAL_EMBED:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
|
||||
return nsIContentPolicy::TYPE_OBJECT;
|
||||
|
||||
case nsIContentPolicy::TYPE_INTERNAL_FRAME:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
|
||||
return nsIContentPolicy::TYPE_SUBDOCUMENT;
|
||||
|
||||
case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_TRACK:
|
||||
return nsIContentPolicy::TYPE_MEDIA;
|
||||
|
||||
default:
|
||||
return aType;
|
||||
}
|
||||
}
|
||||
|
@ -916,6 +916,11 @@ public:
|
||||
*/
|
||||
static nsIContentPolicy *GetContentPolicy();
|
||||
|
||||
/**
|
||||
* Map internal content policy types to external ones.
|
||||
*/
|
||||
static nsContentPolicyType InternalContentPolicyTypeToExternal(nsContentPolicyType aType);
|
||||
|
||||
/**
|
||||
* Quick helper to determine whether there are any mutation listeners
|
||||
* of a given type that apply to this content or any of its ancestors.
|
||||
|
@ -43,6 +43,9 @@ nsDataDocumentContentPolicy::ShouldLoad(uint32_t aContentType,
|
||||
nsIPrincipal *aRequestPrincipal,
|
||||
int16_t *aDecision)
|
||||
{
|
||||
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
|
||||
"We should only see external content policy types here.");
|
||||
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
// Look for the document. In most cases, aRequestingContext is a node.
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
@ -12463,6 +12463,7 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
|
||||
// New script entry point required, due to the "Create a script" sub-step of
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
|
||||
AutoEntryScript entryScript(this, reason, true, aScx->GetNativeContext());
|
||||
entryScript.TakeOwnershipOfErrorReporting();
|
||||
JS::CompileOptions options(entryScript.cx());
|
||||
options.setFileAndLine(filename, lineNo)
|
||||
.setVersion(JSVERSION_DEFAULT);
|
||||
|
@ -20,7 +20,7 @@ interface nsIPrincipal;
|
||||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(cb978019-0c5b-4067-abb6-c914461208c1)]
|
||||
[scriptable,uuid(b545899e-42bd-434c-8fec-a0af3448ea15)]
|
||||
interface nsIContentPolicy : nsIContentPolicyBase
|
||||
{
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType;
|
||||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(4f2655e8-6365-4583-8510-732bff2186c5)]
|
||||
[scriptable,uuid(11b8d725-7c2b-429e-b51f-8b5b542d5009)]
|
||||
interface nsIContentPolicyBase : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -57,6 +57,10 @@ interface nsIContentPolicyBase : nsISupports
|
||||
* Implementations of nsIContentPolicy should treat this the same way they
|
||||
* treat unknown types, because existing users of TYPE_OTHER may be converted
|
||||
* to use new content types.
|
||||
*
|
||||
* Note that the TYPE_INTERNAL_* constants are never passed to content
|
||||
* policy implementations. They are mapped to other TYPE_* constants, and
|
||||
* are only intended for internal usage inside Gecko.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_OTHER = 1;
|
||||
|
||||
@ -177,6 +181,82 @@ interface nsIContentPolicyBase : nsISupports
|
||||
*/
|
||||
const nsContentPolicyType TYPE_WEB_MANIFEST = 22;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for scripts loaded through script
|
||||
* elements.
|
||||
*
|
||||
* This will be mapped to TYPE_SCRIPT before being passed to content policy
|
||||
* implementations.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_SCRIPT = 23;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for scripts loaded through a dedicated
|
||||
* worker.
|
||||
*
|
||||
* This will be mapped to TYPE_SCRIPT before being passed to content policy
|
||||
* implementations.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_WORKER = 24;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for scripts loaded through a shared
|
||||
* worker.
|
||||
*
|
||||
* This will be mapped to TYPE_SCRIPT before being passed to content policy
|
||||
* implementations.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_SHARED_WORKER = 25;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from embed elements.
|
||||
*
|
||||
* This will be mapped to TYPE_OBJECT.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_EMBED = 26;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from object elements.
|
||||
*
|
||||
* This will be mapped to TYPE_OBJECT.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_OBJECT = 27;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from frame elements.
|
||||
*
|
||||
* This will be mapped to TYPE_SUBDOCUMENT.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_FRAME = 28;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from iframe elements.
|
||||
*
|
||||
* This will be mapped to TYPE_SUBDOCUMENT.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_IFRAME = 29;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from audio elements.
|
||||
*
|
||||
* This will be mapped to TYPE_MEDIA.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_AUDIO = 30;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from video elements.
|
||||
*
|
||||
* This will be mapped to TYPE_MEDIA.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_VIDEO = 31;
|
||||
|
||||
/**
|
||||
* Indicates an internal constant for content loaded from track elements.
|
||||
*
|
||||
* This will be mapped to TYPE_MEDIA.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_TRACK = 32;
|
||||
|
||||
/* When adding new content types, please update nsContentBlocker,
|
||||
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
|
||||
* implementations, and other things that are not listed here that are
|
||||
|
@ -28,7 +28,7 @@ interface nsIDOMElement;
|
||||
* by launching a dialog to prompt the user for something).
|
||||
*/
|
||||
|
||||
[scriptable,uuid(704b4b8e-2287-498a-9c0a-d1bde547a2d4)]
|
||||
[scriptable,uuid(b181c97c-9d67-4da1-95a0-e0a202e1807c)]
|
||||
interface nsISimpleContentPolicy : nsIContentPolicyBase
|
||||
{
|
||||
/**
|
||||
|
@ -98,41 +98,6 @@ nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext)
|
||||
return innerWindowID;
|
||||
}
|
||||
|
||||
void
|
||||
nsJSUtils::ReportPendingException(JSContext *aContext)
|
||||
{
|
||||
if (JS_IsExceptionPending(aContext)) {
|
||||
bool saved = JS_SaveFrameChain(aContext);
|
||||
{
|
||||
// JS_SaveFrameChain set the compartment of aContext to null, so we need
|
||||
// to enter a compartment. The question is, which one? We don't want to
|
||||
// enter the original compartment of aContext (or the compartment of the
|
||||
// current exception on aContext, for that matter) because when we
|
||||
// JS_ReportPendingException the JS engine can try to duck-type the
|
||||
// exception and produce a JSErrorReport. It will then pass that
|
||||
// JSErrorReport to the error reporter on aContext, which might expose
|
||||
// information from it to script via onerror handlers. So it's very
|
||||
// important that the duck typing happen in the same compartment as the
|
||||
// onerror handler. In practice, that's the compartment of the window (or
|
||||
// otherwise default global) of aContext, so use that here.
|
||||
nsIScriptContext* scx = GetScriptContextFromJSContext(aContext);
|
||||
JS::Rooted<JSObject*> scope(aContext);
|
||||
scope = scx ? scx->GetWindowProxy() : nullptr;
|
||||
if (!scope) {
|
||||
// The SafeJSContext has no default object associated with it.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aContext == nsContentUtils::GetSafeJSContext());
|
||||
scope = xpc::UnprivilegedJunkScope(); // Usage approved by bholley
|
||||
}
|
||||
JSAutoCompartment ac(aContext, scope);
|
||||
JS_ReportPendingException(aContext);
|
||||
}
|
||||
if (saved) {
|
||||
JS_RestoreFrameChain(aContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
|
||||
JS::AutoObjectVector& aScopeChain,
|
||||
@ -199,12 +164,11 @@ nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
PROFILER_LABEL("nsJSUtils", "EvaluateString",
|
||||
js::ProfileEntry::Category::JS);
|
||||
|
||||
MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(),
|
||||
"Caller must own error reporting");
|
||||
MOZ_ASSERT_IF(aCompileOptions.versionSet,
|
||||
aCompileOptions.version != JSVERSION_UNKNOWN);
|
||||
MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, !aCompileOptions.noScriptRval);
|
||||
MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, !aCompileOptions.noScriptRval);
|
||||
// Note that the above assert means that if aCompileOptions.noScriptRval then
|
||||
// also aEvaluateOptions.reportUncaught.
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
MOZ_ASSERT(aSrcBuf.get());
|
||||
MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) ==
|
||||
@ -225,13 +189,6 @@ nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK);
|
||||
|
||||
mozilla::Maybe<AutoDontReportUncaught> dontReport;
|
||||
if (!aEvaluateOptions.reportUncaught) {
|
||||
// We need to prevent AutoLastFrameCheck from reporting and clearing
|
||||
// any pending exceptions.
|
||||
dontReport.emplace(aCx);
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
// Scope the JSAutoCompartment so that we can later wrap the return value
|
||||
// into the caller's cx.
|
||||
@ -275,24 +232,14 @@ nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
if (aEvaluateOptions.reportUncaught) {
|
||||
ReportPendingException(aCx);
|
||||
if (!aCompileOptions.noScriptRval) {
|
||||
aRetValue.setUndefined();
|
||||
}
|
||||
} else {
|
||||
rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE
|
||||
: NS_ERROR_OUT_OF_MEMORY;
|
||||
JS::Rooted<JS::Value> exn(aCx);
|
||||
JS_GetPendingException(aCx, &exn);
|
||||
MOZ_ASSERT(!aCompileOptions.noScriptRval); // we asserted this on entry
|
||||
aRetValue.set(exn);
|
||||
JS_ClearPendingException(aCx);
|
||||
rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW;
|
||||
if (!aCompileOptions.noScriptRval) {
|
||||
aRetValue.setUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap the return value into whatever compartment aCx was in.
|
||||
if (!aCompileOptions.noScriptRval) {
|
||||
if (ok && !aCompileOptions.noScriptRval) {
|
||||
if (!JS_WrapValue(aCx, aRetValue)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -53,13 +53,6 @@ public:
|
||||
*/
|
||||
static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext);
|
||||
|
||||
/**
|
||||
* Report a pending exception on aContext, if any. Note that this
|
||||
* can be called when the context has a JS stack. If that's the
|
||||
* case, the stack will be set aside before reporting the exception.
|
||||
*/
|
||||
static void ReportPendingException(JSContext *aContext);
|
||||
|
||||
static nsresult CompileFunction(mozilla::dom::AutoJSAPI& jsapi,
|
||||
JS::AutoObjectVector& aScopeChain,
|
||||
JS::CompileOptions& aOptions,
|
||||
@ -71,12 +64,10 @@ public:
|
||||
|
||||
struct MOZ_STACK_CLASS EvaluateOptions {
|
||||
bool coerceToString;
|
||||
bool reportUncaught;
|
||||
JS::AutoObjectVector scopeChain;
|
||||
|
||||
explicit EvaluateOptions(JSContext* cx)
|
||||
: coerceToString(false)
|
||||
, reportUncaught(true)
|
||||
, scopeChain(cx)
|
||||
{}
|
||||
|
||||
@ -84,16 +75,13 @@ public:
|
||||
coerceToString = aCoerce;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EvaluateOptions& setReportUncaught(bool aReport) {
|
||||
reportUncaught = aReport;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// aEvaluationGlobal is the global to evaluate in. The return value
|
||||
// will then be wrapped back into the compartment aCx is in when
|
||||
// this function is called.
|
||||
// this function is called. For all the EvaluateString overloads,
|
||||
// the JSContext must come from an AutoJSAPI that has had
|
||||
// TakeOwnershipOfErrorReporting() called on it.
|
||||
static nsresult EvaluateString(JSContext* aCx,
|
||||
const nsAString& aScript,
|
||||
JS::Handle<JSObject*> aEvaluationGlobal,
|
||||
|
@ -1120,6 +1120,7 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
|
||||
AutoEntryScript entryScript(globalObject, "<script> element", true,
|
||||
context->GetNativeContext());
|
||||
entryScript.TakeOwnershipOfErrorReporting();
|
||||
JS::Rooted<JSObject*> global(entryScript.cx(),
|
||||
globalObject->GetGlobalJSObject());
|
||||
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMErrorBinding.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "mozilla/dom/HTMLObjectElement.h"
|
||||
#include "mozilla/dom/HTMLObjectElementBinding.h"
|
||||
@ -284,26 +282,16 @@ ErrorResult::ReportJSExceptionFromJSImplementation(JSContext* aCx)
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
||||
"Why didn't you tell us you planned to handle JS exceptions?");
|
||||
|
||||
dom::DOMException* domException;
|
||||
nsresult rv =
|
||||
UNWRAP_OBJECT(DOMException, &mJSException.toObject(), domException);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Check for a DOMError, since we convert that into an Error in the content
|
||||
// compartment. We can probably remove that now; see bug 1174954.
|
||||
dom::DOMError* domError;
|
||||
nsresult rv = UNWRAP_OBJECT(DOMError, &mJSException.toObject(), domError);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Just report it.
|
||||
ReportJSException(aCx);
|
||||
return;
|
||||
}
|
||||
|
||||
dom::DOMError* domError;
|
||||
rv = UNWRAP_OBJECT(DOMError, &mJSException.toObject(), domError);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Unwrapping really shouldn't fail here: if mExceptionHandling is set to
|
||||
// eRethrowContentExceptions then the CallSetup destructor only stores an
|
||||
// exception if it unwraps to DOMError or DOMException. If we reach this
|
||||
// then either mExceptionHandling wasn't set to eRethrowContentExceptions
|
||||
// and we shouldn't be calling ReportJSExceptionFromJSImplementation or
|
||||
// something went really wrong.
|
||||
NS_RUNTIMEABORT("We stored a non-DOMError exception!");
|
||||
}
|
||||
|
||||
nsString message;
|
||||
domError->GetMessage(message);
|
||||
|
||||
|
@ -6,10 +6,6 @@
|
||||
|
||||
#include "mozilla/dom/CallbackObject.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMErrorBinding.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIXPConnect.h"
|
||||
@ -224,8 +220,7 @@ CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aExcepti
|
||||
MOZ_ASSERT(mCompartment);
|
||||
|
||||
// Now we only want to throw an exception to the caller if the object that was
|
||||
// thrown is a DOMError or DOMException object in the caller compartment
|
||||
// (which we stored in mCompartment).
|
||||
// thrown is in the caller compartment (which we stored in mCompartment).
|
||||
|
||||
if (!aException.isObject()) {
|
||||
return false;
|
||||
@ -233,14 +228,7 @@ CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aExcepti
|
||||
|
||||
JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
|
||||
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
if (js::GetObjectCompartment(obj) != mCompartment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DOMError* domError;
|
||||
DOMException* domException;
|
||||
return NS_SUCCEEDED(UNWRAP_OBJECT(DOMError, obj, domError)) ||
|
||||
NS_SUCCEEDED(UNWRAP_OBJECT(DOMException, obj, domException));
|
||||
return js::GetObjectCompartment(obj) == mCompartment;
|
||||
}
|
||||
|
||||
CallbackObject::CallSetup::~CallSetup()
|
||||
|
@ -142,9 +142,9 @@ ThrowAndReport(nsPIDOMWindow* aWindow, nsresult aRv, const char* aMessage)
|
||||
if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(aWindow))) {
|
||||
return;
|
||||
}
|
||||
jsapi.TakeOwnershipOfErrorReporting();
|
||||
|
||||
Throw(jsapi.cx(), aRv, aMessage);
|
||||
(void) JS_ReportPendingException(jsapi.cx());
|
||||
}
|
||||
|
||||
already_AddRefed<Exception>
|
||||
|
@ -73,6 +73,22 @@ TestInterfaceJS.prototype = {
|
||||
"NotSupportedError");
|
||||
},
|
||||
|
||||
testThrowTypeError: function() {
|
||||
throw new this._win.TypeError("We are a TypeError");
|
||||
},
|
||||
|
||||
testThrowCallbackError: function(callback) {
|
||||
callback();
|
||||
},
|
||||
|
||||
testThrowXraySelfHosted: function() {
|
||||
this._win.Array.indexOf();
|
||||
},
|
||||
|
||||
testThrowSelfHosted: function() {
|
||||
Array.indexOf();
|
||||
},
|
||||
|
||||
testPromiseWithThrowingChromePromiseInit: function() {
|
||||
return new this._win.Promise(function() {
|
||||
noSuchMethodExistsYo1();
|
||||
|
@ -51,9 +51,86 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107592
|
||||
"http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
|
||||
"Should still have the right file name");
|
||||
is(e.lineNumber, 38, "Should still have the right line number");
|
||||
todo_is(e.columnNumber, 7,
|
||||
"No column number support for DOMException yet");
|
||||
todo_isnot(e.columnNumber, 0,
|
||||
"No column number support for DOMException yet");
|
||||
}
|
||||
|
||||
try {
|
||||
t.testThrowTypeError();
|
||||
} catch (e) {
|
||||
ok(e instanceof TypeError, "Should have a TypeError here");
|
||||
ok(!(e instanceof DOMException), "Should not have DOMException here (2)");
|
||||
ok(!("code" in e), "Should not have a 'code' property (2)");
|
||||
is(e.name, "TypeError", "Should be named TypeError");
|
||||
is(e.message, "We are a TypeError",
|
||||
"Should also have the right message (2)");
|
||||
is(e.stack,
|
||||
"doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:59:7\n",
|
||||
"Exception stack for TypeError should only show our code");
|
||||
is(e.fileName,
|
||||
"http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
|
||||
"Should still have the right file name for TypeError");
|
||||
is(e.lineNumber, 59, "Should still have the right line number for TypeError");
|
||||
is(e.columnNumber, 7, "Should have the right column number for TypeError");
|
||||
}
|
||||
|
||||
try {
|
||||
t.testThrowCallbackError(function() { Array.indexOf() });
|
||||
} catch (e) {
|
||||
ok(e instanceof TypeError, "Should have a TypeError here (3)");
|
||||
ok(!(e instanceof DOMException), "Should not have DOMException here (3)");
|
||||
ok(!("code" in e), "Should not have a 'code' property (3)");
|
||||
is(e.name, "TypeError", "Should be named TypeError (3)");
|
||||
is(e.message, "missing argument 0 when calling function Array.indexOf",
|
||||
"Should also have the right message (3)");
|
||||
is(e.stack,
|
||||
"doTest/<@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:78:45\n" +
|
||||
"doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:78:7\n"
|
||||
,
|
||||
"Exception stack for TypeError should only show our code (3)");
|
||||
is(e.fileName,
|
||||
"http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
|
||||
"Should still have the right file name for TypeError (3)");
|
||||
is(e.lineNumber, 78, "Should still have the right line number for TypeError (3)");
|
||||
is(e.columnNumber, 45, "Should have the right column number for TypeError (3)");
|
||||
}
|
||||
|
||||
try {
|
||||
t.testThrowXraySelfHosted();
|
||||
} catch (e) {
|
||||
ok(!(e instanceof Error), "Should have an Exception here (4)");
|
||||
ok(!(e instanceof DOMException), "Should not have DOMException here (4)");
|
||||
ok(!("code" in e), "Should not have a 'code' property (4)");
|
||||
is(e.name, "NS_ERROR_UNEXPECTED", "Name should be sanitized (4)");
|
||||
is(e.message, "", "Message should be sanitized (5)");
|
||||
is(e.stack,
|
||||
"doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:99:7\n",
|
||||
"Exception stack for sanitized exception should only show our code (4)");
|
||||
is(e.filename,
|
||||
"http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
|
||||
"Should still have the right file name for sanitized exception (4)");
|
||||
is(e.lineNumber, 99, "Should still have the right line number for sanitized exception (4)");
|
||||
todo_isnot(e.columnNumber, 0, "Should have the right column number for sanitized exception (4)");
|
||||
}
|
||||
|
||||
try {
|
||||
t.testThrowSelfHosted();
|
||||
} catch (e) {
|
||||
ok(!(e instanceof Error), "Should have an Exception here (5)");
|
||||
ok(!(e instanceof DOMException), "Should not have DOMException here (5)");
|
||||
ok(!("code" in e), "Should not have a 'code' property (5)");
|
||||
is(e.name, "NS_ERROR_UNEXPECTED", "Name should be sanitized (5)");
|
||||
is(e.message, "", "Message should be sanitized (5)");
|
||||
is(e.stack,
|
||||
"doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:117:7\n",
|
||||
"Exception stack for sanitized exception should only show our code (5)");
|
||||
is(e.filename,
|
||||
"http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
|
||||
"Should still have the right file name for sanitized exception (5)");
|
||||
is(e.lineNumber, 117, "Should still have the right line number for sanitized exception (5)");
|
||||
todo_isnot(e.columnNumber, 0, "Should have the right column number for sanitized exception (5)");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
2
dom/cache/CacheTypes.ipdlh
vendored
@ -12,7 +12,6 @@ using HeadersGuardEnum from "mozilla/dom/cache/IPCUtils.h";
|
||||
using RequestCredentials from "mozilla/dom/cache/IPCUtils.h";
|
||||
using RequestMode from "mozilla/dom/cache/IPCUtils.h";
|
||||
using RequestCache from "mozilla/dom/cache/IPCUtils.h";
|
||||
using RequestContext from "mozilla/dom/cache/IPCUtils.h";
|
||||
using ResponseType from "mozilla/dom/cache/IPCUtils.h";
|
||||
using mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
using struct nsID from "nsID.h";
|
||||
@ -63,7 +62,6 @@ struct CacheRequest
|
||||
RequestCredentials credentials;
|
||||
CacheReadStreamOrVoid body;
|
||||
uint32_t contentPolicyType;
|
||||
RequestContext context;
|
||||
RequestCache requestCache;
|
||||
};
|
||||
|
||||
|
58
dom/cache/DBSchema.cpp
vendored
@ -29,11 +29,11 @@ namespace dom {
|
||||
namespace cache {
|
||||
namespace db {
|
||||
|
||||
const int32_t kMaxWipeSchemaVersion = 11;
|
||||
const int32_t kMaxWipeSchemaVersion = 13;
|
||||
|
||||
namespace {
|
||||
|
||||
const int32_t kLatestSchemaVersion = 11;
|
||||
const int32_t kLatestSchemaVersion = 13;
|
||||
const int32_t kMaxEntriesPerStatement = 255;
|
||||
|
||||
const uint32_t kPageSize = 4 * 1024;
|
||||
@ -77,40 +77,6 @@ static_assert(int(RequestCredentials::Omit) == 0 &&
|
||||
int(RequestCredentials::Include) == 2 &&
|
||||
int(RequestCredentials::EndGuard_) == 3,
|
||||
"RequestCredentials values are as expected");
|
||||
static_assert(int(RequestContext::Audio) == 0 &&
|
||||
int(RequestContext::Beacon) == 1 &&
|
||||
int(RequestContext::Cspreport) == 2 &&
|
||||
int(RequestContext::Download) == 3 &&
|
||||
int(RequestContext::Embed) == 4 &&
|
||||
int(RequestContext::Eventsource) == 5 &&
|
||||
int(RequestContext::Favicon) == 6 &&
|
||||
int(RequestContext::Fetch) == 7 &&
|
||||
int(RequestContext::Font) == 8 &&
|
||||
int(RequestContext::Form) == 9 &&
|
||||
int(RequestContext::Frame) == 10 &&
|
||||
int(RequestContext::Hyperlink) == 11 &&
|
||||
int(RequestContext::Iframe) == 12 &&
|
||||
int(RequestContext::Image) == 13 &&
|
||||
int(RequestContext::Imageset) == 14 &&
|
||||
int(RequestContext::Import) == 15 &&
|
||||
int(RequestContext::Internal) == 16 &&
|
||||
int(RequestContext::Location) == 17 &&
|
||||
int(RequestContext::Manifest) == 18 &&
|
||||
int(RequestContext::Object) == 19 &&
|
||||
int(RequestContext::Ping) == 20 &&
|
||||
int(RequestContext::Plugin) == 21 &&
|
||||
int(RequestContext::Prefetch) == 22 &&
|
||||
int(RequestContext::Script) == 23 &&
|
||||
int(RequestContext::Serviceworker) == 24 &&
|
||||
int(RequestContext::Sharedworker) == 25 &&
|
||||
int(RequestContext::Subresource) == 26 &&
|
||||
int(RequestContext::Style) == 27 &&
|
||||
int(RequestContext::Track) == 28 &&
|
||||
int(RequestContext::Video) == 29 &&
|
||||
int(RequestContext::Worker) == 30 &&
|
||||
int(RequestContext::Xmlhttprequest) == 31 &&
|
||||
int(RequestContext::Xslt) == 32,
|
||||
"RequestContext values are as expected");
|
||||
static_assert(int(RequestCache::Default) == 0 &&
|
||||
int(RequestCache::No_store) == 1 &&
|
||||
int(RequestCache::Reload) == 2 &&
|
||||
@ -291,7 +257,6 @@ CreateSchema(mozIStorageConnection* aConn)
|
||||
"request_mode INTEGER NOT NULL, "
|
||||
"request_credentials INTEGER NOT NULL, "
|
||||
"request_contentpolicytype INTEGER NOT NULL, "
|
||||
"request_context INTEGER NOT NULL, "
|
||||
"request_cache INTEGER NOT NULL, "
|
||||
"request_body_id TEXT NULL, "
|
||||
"response_type INTEGER NOT NULL, "
|
||||
@ -1462,7 +1427,6 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
"request_mode, "
|
||||
"request_credentials, "
|
||||
"request_contentpolicytype, "
|
||||
"request_context, "
|
||||
"request_cache, "
|
||||
"request_body_id, "
|
||||
"response_type, "
|
||||
@ -1484,7 +1448,6 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
":request_mode, "
|
||||
":request_credentials, "
|
||||
":request_contentpolicytype, "
|
||||
":request_context, "
|
||||
":request_cache, "
|
||||
":request_body_id, "
|
||||
":response_type, "
|
||||
@ -1533,10 +1496,6 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
static_cast<int32_t>(aRequest.contentPolicyType()));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_context"),
|
||||
static_cast<int32_t>(aRequest.context()));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_cache"),
|
||||
static_cast<int32_t>(aRequest.requestCache()));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
@ -1780,7 +1739,6 @@ ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
|
||||
"request_mode, "
|
||||
"request_credentials, "
|
||||
"request_contentpolicytype, "
|
||||
"request_context, "
|
||||
"request_cache, "
|
||||
"request_body_id "
|
||||
"FROM entries "
|
||||
@ -1830,25 +1788,19 @@ ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
|
||||
aSavedRequestOut->mValue.contentPolicyType() =
|
||||
static_cast<nsContentPolicyType>(requestContentPolicyType);
|
||||
|
||||
int32_t requestContext;
|
||||
rv = state->GetInt32(8, &requestContext);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
aSavedRequestOut->mValue.context() =
|
||||
static_cast<RequestContext>(requestContext);
|
||||
|
||||
int32_t requestCache;
|
||||
rv = state->GetInt32(9, &requestCache);
|
||||
rv = state->GetInt32(8, &requestCache);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
aSavedRequestOut->mValue.requestCache() =
|
||||
static_cast<RequestCache>(requestCache);
|
||||
|
||||
bool nullBody = false;
|
||||
rv = state->GetIsNull(10, &nullBody);
|
||||
rv = state->GetIsNull(9, &nullBody);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
aSavedRequestOut->mHasBodyId = !nullBody;
|
||||
|
||||
if (aSavedRequestOut->mHasBodyId) {
|
||||
rv = ExtractId(state, 10, &aSavedRequestOut->mBodyId);
|
||||
rv = ExtractId(state, 9, &aSavedRequestOut->mBodyId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
}
|
||||
|
||||
|
5
dom/cache/IPCUtils.h
vendored
@ -39,11 +39,6 @@ namespace IPC {
|
||||
mozilla::dom::RequestCache::Default,
|
||||
mozilla::dom::RequestCache::EndGuard_> {};
|
||||
template<>
|
||||
struct ParamTraits<mozilla::dom::RequestContext> :
|
||||
public ContiguousEnumSerializer<mozilla::dom::RequestContext,
|
||||
mozilla::dom::RequestContext::Audio,
|
||||
mozilla::dom::RequestContext::EndGuard_> {};
|
||||
template<>
|
||||
struct ParamTraits<mozilla::dom::ResponseType> :
|
||||
public ContiguousEnumSerializer<mozilla::dom::ResponseType,
|
||||
mozilla::dom::ResponseType::Basic,
|
||||
|
5
dom/cache/TypeUtils.cpp
vendored
@ -177,7 +177,6 @@ TypeUtils::ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
|
||||
aOut.mode() = aIn->Mode();
|
||||
aOut.credentials() = aIn->GetCredentialsMode();
|
||||
aOut.contentPolicyType() = aIn->ContentPolicyType();
|
||||
aOut.context() = aIn->Context();
|
||||
aOut.requestCache() = aIn->GetCacheMode();
|
||||
|
||||
if (aBodyAction == IgnoreBody) {
|
||||
@ -328,10 +327,6 @@ TypeUtils::ToInternalRequest(const CacheRequest& aIn)
|
||||
internalRequest->SetMode(aIn.mode());
|
||||
internalRequest->SetCredentialsMode(aIn.credentials());
|
||||
internalRequest->SetContentPolicyType(aIn.contentPolicyType());
|
||||
DebugOnly<RequestContext> contextAfterSetContentPolicyType = internalRequest->Context();
|
||||
internalRequest->SetContext(aIn.context());
|
||||
MOZ_ASSERT(contextAfterSetContentPolicyType.value == internalRequest->Context(),
|
||||
"The RequestContext and nsContentPolicyType values should not get out of sync");
|
||||
internalRequest->SetCacheMode(aIn.requestCache());
|
||||
|
||||
nsRefPtr<InternalHeaders> internalHeaders =
|
||||
|
@ -894,6 +894,10 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
|
||||
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
|
||||
|
||||
bool disabled = Preferences::GetBool("webgl.disabled", false);
|
||||
|
||||
// TODO: When we have software webgl support we should use that instead.
|
||||
disabled |= gfxPlatform::InSafeMode();
|
||||
|
||||
if (disabled) {
|
||||
GenerateWarning("WebGL creation is disabled, and so disallowed here.");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -492,7 +492,16 @@ WebGLContext::GenerateWarning(const char* fmt, va_list ap)
|
||||
|
||||
// no need to print to stderr, as JS_ReportWarning takes care of this for us.
|
||||
|
||||
AutoJSContext cx;
|
||||
if (!mCanvasElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoJSAPI api;
|
||||
if (!api.Init(mCanvasElement->OwnerDoc()->GetScopeObject())) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSContext* cx = api.cx();
|
||||
JS_ReportWarning(cx, "WebGL: %s", buf);
|
||||
if (!ShouldGenerateWarnings()) {
|
||||
JS_ReportWarning(cx,
|
||||
|
@ -39,7 +39,6 @@ InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult
|
||||
// The default referrer is already about:client.
|
||||
|
||||
copy->mContentPolicyType = nsIContentPolicy::TYPE_FETCH;
|
||||
copy->mContext = RequestContext::Fetch;
|
||||
copy->mMode = mMode;
|
||||
copy->mCredentialsMode = mCredentialsMode;
|
||||
copy->mCacheMode = mCacheMode;
|
||||
@ -76,7 +75,6 @@ InternalRequest::InternalRequest(const InternalRequest& aOther)
|
||||
, mURL(aOther.mURL)
|
||||
, mHeaders(new InternalHeaders(*aOther.mHeaders))
|
||||
, mContentPolicyType(aOther.mContentPolicyType)
|
||||
, mContext(aOther.mContext)
|
||||
, mReferrer(aOther.mReferrer)
|
||||
, mMode(aOther.mMode)
|
||||
, mCredentialsMode(aOther.mCredentialsMode)
|
||||
@ -104,78 +102,85 @@ void
|
||||
InternalRequest::SetContentPolicyType(nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
mContentPolicyType = aContentPolicyType;
|
||||
}
|
||||
|
||||
/* static */
|
||||
RequestContext
|
||||
InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
RequestContext context = RequestContext::Internal;
|
||||
switch (aContentPolicyType) {
|
||||
case nsIContentPolicy::TYPE_OTHER:
|
||||
mContext = RequestContext::Internal;
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_SCRIPT:
|
||||
mContext = RequestContext::Script;
|
||||
context = RequestContext::Script;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_IMAGE:
|
||||
mContext = RequestContext::Image;
|
||||
context = RequestContext::Image;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_STYLESHEET:
|
||||
mContext = RequestContext::Style;
|
||||
context = RequestContext::Style;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_OBJECT:
|
||||
mContext = RequestContext::Object;
|
||||
context = RequestContext::Object;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
mContext = RequestContext::Internal;
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
mContext = RequestContext::Iframe;
|
||||
context = RequestContext::Iframe;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_REFRESH:
|
||||
mContext = RequestContext::Internal;
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_XBL:
|
||||
mContext = RequestContext::Internal;
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_PING:
|
||||
mContext = RequestContext::Ping;
|
||||
context = RequestContext::Ping;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
|
||||
mContext = RequestContext::Xmlhttprequest;
|
||||
context = RequestContext::Xmlhttprequest;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
|
||||
mContext = RequestContext::Plugin;
|
||||
context = RequestContext::Plugin;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_DTD:
|
||||
mContext = RequestContext::Internal;
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_FONT:
|
||||
mContext = RequestContext::Font;
|
||||
context = RequestContext::Font;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_MEDIA:
|
||||
mContext = RequestContext::Audio;
|
||||
context = RequestContext::Audio;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_WEBSOCKET:
|
||||
mContext = RequestContext::Internal;
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_CSP_REPORT:
|
||||
mContext = RequestContext::Cspreport;
|
||||
context = RequestContext::Cspreport;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_XSLT:
|
||||
mContext = RequestContext::Xslt;
|
||||
context = RequestContext::Xslt;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_BEACON:
|
||||
mContext = RequestContext::Beacon;
|
||||
context = RequestContext::Beacon;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_FETCH:
|
||||
mContext = RequestContext::Fetch;
|
||||
context = RequestContext::Fetch;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_IMAGESET:
|
||||
mContext = RequestContext::Imageset;
|
||||
context = RequestContext::Imageset;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_WEB_MANIFEST:
|
||||
mContext = RequestContext::Manifest;
|
||||
context = RequestContext::Manifest;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
|
||||
mContext = RequestContext::Internal;
|
||||
break;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -26,8 +26,7 @@ namespace dom {
|
||||
/*
|
||||
* The mapping of RequestContext and nsContentPolicyType is currently as the
|
||||
* following. Note that this mapping is not perfect yet (see the TODO comments
|
||||
* below for examples), so for now we'll have to keep both an mContext and an
|
||||
* mContentPolicyType, because we cannot have a two way conversion.
|
||||
* below for examples).
|
||||
*
|
||||
* RequestContext | nsContentPolicyType
|
||||
* ------------------+--------------------
|
||||
@ -55,7 +54,6 @@ namespace dom {
|
||||
* plugin | TYPE_OBJECT_SUBREQUEST
|
||||
* prefetch |
|
||||
* script | TYPE_SCRIPT
|
||||
* serviceworker |
|
||||
* sharedworker |
|
||||
* subresource | Not supported by Gecko
|
||||
* style | TYPE_STYLESHEET
|
||||
@ -282,13 +280,7 @@ public:
|
||||
RequestContext
|
||||
Context() const
|
||||
{
|
||||
return mContext;
|
||||
}
|
||||
|
||||
void
|
||||
SetContext(RequestContext aContext)
|
||||
{
|
||||
mContext = aContext;
|
||||
return MapContentPolicyTypeToRequestContext(mContentPolicyType);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -372,13 +364,15 @@ private:
|
||||
|
||||
~InternalRequest();
|
||||
|
||||
static RequestContext
|
||||
MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType);
|
||||
|
||||
nsCString mMethod;
|
||||
nsCString mURL;
|
||||
nsRefPtr<InternalHeaders> mHeaders;
|
||||
nsCOMPtr<nsIInputStream> mBodyStream;
|
||||
|
||||
nsContentPolicyType mContentPolicyType;
|
||||
RequestContext mContext;
|
||||
|
||||
// Empty string: no-referrer
|
||||
// "about:client": client (default)
|
||||
|
@ -79,13 +79,6 @@ public:
|
||||
return mRequest->Context();
|
||||
}
|
||||
|
||||
// [ChromeOnly]
|
||||
void
|
||||
SetContext(RequestContext aContext)
|
||||
{
|
||||
mRequest->SetContext(aContext);
|
||||
}
|
||||
|
||||
void
|
||||
SetContentPolicyType(nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ Directory::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
}
|
||||
|
||||
void
|
||||
Directory::GetName(nsString& aRetval) const
|
||||
Directory::GetName(nsAString& aRetval) const
|
||||
{
|
||||
aRetval.Truncate();
|
||||
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void
|
||||
GetName(nsString& aRetval) const;
|
||||
GetName(nsAString& aRetval) const;
|
||||
|
||||
already_AddRefed<Promise>
|
||||
CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions,
|
||||
|
@ -113,6 +113,7 @@
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsLayoutStylesheetCache.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -146,26 +147,6 @@ static bool ConvertToMidasInternalCommand(const nsAString & inCommandID,
|
||||
// ==================================================================
|
||||
// =
|
||||
// ==================================================================
|
||||
static nsresult
|
||||
RemoveFromAgentSheets(nsCOMArray<nsIStyleSheet> &aAgentSheets, const nsAString& url)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (int32_t i = aAgentSheets.Count() - 1; i >= 0; --i) {
|
||||
nsIStyleSheet* sheet = aAgentSheets[i];
|
||||
nsIURI* sheetURI = sheet->GetSheetURI();
|
||||
|
||||
bool equals = false;
|
||||
uri->Equals(sheetURI, &equals);
|
||||
if (equals) {
|
||||
aAgentSheets.RemoveObjectAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
|
||||
@ -2660,9 +2641,9 @@ nsHTMLDocument::TearingDownEditor(nsIEditor *aEditor)
|
||||
nsCOMArray<nsIStyleSheet> agentSheets;
|
||||
presShell->GetAgentStyleSheets(agentSheets);
|
||||
|
||||
RemoveFromAgentSheets(agentSheets, NS_LITERAL_STRING("resource://gre/res/contenteditable.css"));
|
||||
agentSheets.RemoveObject(nsLayoutStylesheetCache::ContentEditableSheet());
|
||||
if (oldState == eDesignMode)
|
||||
RemoveFromAgentSheets(agentSheets, NS_LITERAL_STRING("resource://gre/res/designmode.css"));
|
||||
agentSheets.RemoveObject(nsLayoutStylesheetCache::DesignModeSheet());
|
||||
|
||||
presShell->SetAgentStyleSheets(agentSheets);
|
||||
|
||||
@ -2800,41 +2781,34 @@ nsHTMLDocument::EditingStateChanged()
|
||||
rv = presShell->GetAgentStyleSheets(agentSheets);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri),
|
||||
NS_LITERAL_STRING("resource://gre/res/contenteditable.css"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
CSSStyleSheet* contentEditableSheet =
|
||||
nsLayoutStylesheetCache::ContentEditableSheet();
|
||||
|
||||
nsRefPtr<CSSStyleSheet> sheet;
|
||||
rv = LoadChromeSheetSync(uri, true, getter_AddRefs(sheet));
|
||||
NS_ENSURE_TRUE(sheet, rv);
|
||||
bool result;
|
||||
|
||||
bool result = agentSheets.AppendObject(sheet);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!agentSheets.Contains(contentEditableSheet)) {
|
||||
bool result = agentSheets.AppendObject(contentEditableSheet);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// Should we update the editable state of all the nodes in the document? We
|
||||
// need to do this when the designMode value changes, as that overrides
|
||||
// specific states on the elements.
|
||||
if (designMode) {
|
||||
// designMode is being turned on (overrides contentEditable).
|
||||
rv = NS_NewURI(getter_AddRefs(uri),
|
||||
NS_LITERAL_STRING("resource://gre/res/designmode.css"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = LoadChromeSheetSync(uri, true, getter_AddRefs(sheet));
|
||||
NS_ENSURE_TRUE(sheet, rv);
|
||||
|
||||
result = agentSheets.AppendObject(sheet);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
CSSStyleSheet* designModeSheet =
|
||||
nsLayoutStylesheetCache::DesignModeSheet();
|
||||
if (!agentSheets.Contains(designModeSheet)) {
|
||||
result = agentSheets.AppendObject(designModeSheet);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
updateState = true;
|
||||
spellRecheckAll = oldState == eContentEditable;
|
||||
}
|
||||
else if (oldState == eDesignMode) {
|
||||
// designMode is being turned off (contentEditable is still on).
|
||||
RemoveFromAgentSheets(agentSheets,
|
||||
NS_LITERAL_STRING("resource://gre/res/designmode.css"));
|
||||
|
||||
agentSheets.RemoveObject(nsLayoutStylesheetCache::DesignModeSheet());
|
||||
updateState = true;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ BlobImplSnapshot::CreateSlice(uint64_t aStart,
|
||||
|
||||
void
|
||||
BlobImplSnapshot::GetMozFullPathInternal(nsAString& aFilename,
|
||||
ErrorResult& aRv)
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
AssertSanity();
|
||||
MOZ_ASSERT(mIsFile);
|
||||
|
@ -74,7 +74,7 @@ private:
|
||||
#endif
|
||||
|
||||
virtual void
|
||||
GetMozFullPathInternal(nsAString& aFullPath, ErrorResult& aRv) override;
|
||||
GetMozFullPathInternal(nsAString& aFullPath, ErrorResult& aRv) const override;
|
||||
|
||||
virtual void
|
||||
GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv) override;
|
||||
|
@ -63,6 +63,18 @@ function testSteps()
|
||||
// This one lives in storage/default/file++++c++
|
||||
{ url: "file:///c:/", dbName: "dbQ", dbVersion: 1 },
|
||||
|
||||
// This one lives in storage/default/file++++Users+joe+c+++index.html
|
||||
{ url: "file:///Users/joe/c++/index.html", dbName: "dbR", dbVersion: 1 },
|
||||
|
||||
// This one lives in storage/default/file++++Users+joe+c+++index.html
|
||||
{ url: "file:///Users/joe/c///index.html", dbName: "dbR", dbVersion: 1 },
|
||||
|
||||
// This one lives in storage/default/file++++++index.html
|
||||
{ url: "file:///+/index.html", dbName: "dbS", dbVersion: 1 },
|
||||
|
||||
// This one lives in storage/default/file++++++index.html
|
||||
{ url: "file://///index.html", dbName: "dbS", dbVersion: 1 },
|
||||
|
||||
// This one lives in storage/temporary/http+++localhost
|
||||
{ url: "http://localhost", dbName: "dbZ",
|
||||
dbOptions: { version: 1, storage: "temporary" } }
|
||||
|
@ -1918,7 +1918,7 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual void
|
||||
GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) override;
|
||||
GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const override;
|
||||
|
||||
virtual already_AddRefed<BlobImpl>
|
||||
CreateSlice(uint64_t aStart,
|
||||
@ -2078,10 +2078,10 @@ public:
|
||||
SetLastModified(int64_t aLastModified) override;
|
||||
|
||||
virtual void
|
||||
GetMozFullPath(nsAString& aName, ErrorResult& aRv) override;
|
||||
GetMozFullPath(nsAString& aName, ErrorResult& aRv) const override;
|
||||
|
||||
virtual void
|
||||
GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) override;
|
||||
GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const override;
|
||||
|
||||
virtual uint64_t
|
||||
GetSize(ErrorResult& aRv) override;
|
||||
@ -2319,7 +2319,7 @@ NS_IMPL_QUERY_INTERFACE_INHERITED(BlobChild::RemoteBlobImpl,
|
||||
void
|
||||
BlobChild::
|
||||
RemoteBlobImpl::GetMozFullPathInternal(nsAString& aFilePath,
|
||||
ErrorResult& aRv)
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
if (!EventTargetIsOnCurrentThread(mActorTarget)) {
|
||||
MOZ_CRASH("Not implemented!");
|
||||
@ -2774,14 +2774,14 @@ RemoteBlobImpl::SetLastModified(int64_t aLastModified)
|
||||
|
||||
void
|
||||
BlobParent::
|
||||
RemoteBlobImpl::GetMozFullPath(nsAString& aName, ErrorResult& aRv)
|
||||
RemoteBlobImpl::GetMozFullPath(nsAString& aName, ErrorResult& aRv) const
|
||||
{
|
||||
mBlobImpl->GetMozFullPath(aName, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
BlobParent::
|
||||
RemoteBlobImpl::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv)
|
||||
RemoteBlobImpl::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
|
||||
{
|
||||
mBlobImpl->GetMozFullPathInternal(aFileName, aRv);
|
||||
}
|
||||
|
@ -423,6 +423,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
|
||||
defaultZoom <= viewportInfo.GetMaxZoom());
|
||||
metrics.SetZoom(CSSToParentLayerScale2D(ConvertScaleForRoot(defaultZoom)));
|
||||
|
||||
metrics.SetPresShellId(presShellId);
|
||||
metrics.SetScrollId(viewId);
|
||||
}
|
||||
|
||||
@ -561,13 +562,9 @@ TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
|
||||
} else {
|
||||
// aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
|
||||
// This requires special handling.
|
||||
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(
|
||||
aFrameMetrics.GetScrollId());
|
||||
if (content) {
|
||||
FrameMetrics newSubFrameMetrics(aFrameMetrics);
|
||||
APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
|
||||
return true;
|
||||
}
|
||||
FrameMetrics newSubFrameMetrics(aFrameMetrics);
|
||||
APZCCallbackHelper::UpdateSubFrame(newSubFrameMetrics);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -580,9 +577,7 @@ TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
}
|
||||
|
||||
FrameMetrics newMetrics = aFrameMetrics;
|
||||
if (nsCOMPtr<nsIPresShell> presShell = GetPresShell()) {
|
||||
APZCCallbackHelper::UpdateRootFrame(presShell, newMetrics);
|
||||
}
|
||||
APZCCallbackHelper::UpdateRootFrame(newMetrics);
|
||||
|
||||
CSSSize cssCompositedSize = newMetrics.CalculateCompositedSizeInCssPixels();
|
||||
// The BrowserElementScrolling helper must know about these updated metrics
|
||||
|
@ -79,7 +79,7 @@ function fetchManifest() {
|
||||
reqInit.credentials = 'include';
|
||||
}
|
||||
const req = new content.Request(manifestURL, reqInit);
|
||||
req.setContext('manifest');
|
||||
req.setContentPolicyType(Ci.nsIContentPolicy.TYPE_WEB_MANIFEST);
|
||||
const response = yield content.fetch(req);
|
||||
const manifest = yield processResponse(response, content);
|
||||
return manifest;
|
||||
|
@ -251,6 +251,10 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#javascript-protocol
|
||||
AutoEntryScript entryScript(innerGlobal, "javascript: URI", true,
|
||||
scriptContext->GetNativeContext());
|
||||
// We want to make sure we report any exceptions that happen before we
|
||||
// return, since whatever happens inside our execution shouldn't affect any
|
||||
// other scripts that might happen to be running.
|
||||
entryScript.TakeOwnershipOfErrorReporting();
|
||||
JSContext* cx = entryScript.cx();
|
||||
JS::Rooted<JSObject*> globalJSObject(cx, innerGlobal->GetGlobalJSObject());
|
||||
NS_ENSURE_TRUE(globalJSObject, NS_ERROR_UNEXPECTED);
|
||||
@ -278,20 +282,13 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
|
||||
rv = nsJSUtils::EvaluateString(cx, NS_ConvertUTF8toUTF16(script),
|
||||
globalJSObject, options, evalOptions, &v);
|
||||
|
||||
// If there's an error on cx as a result of that call, report
|
||||
// it now -- either we're just running under the event loop,
|
||||
// so we shouldn't propagate JS exceptions out of here, or we
|
||||
// can't be sure that our caller is JS (and if it's not we'll
|
||||
// lose the error), or it might be JS that then proceeds to
|
||||
// cause an error of its own (which will also make us lose
|
||||
// this error).
|
||||
::JS_ReportPendingException(cx);
|
||||
|
||||
if (NS_FAILED(rv) || !(v.isString() || v.isUndefined())) {
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
} else if (v.isUndefined()) {
|
||||
return NS_ERROR_DOM_RETVAL_UNDEFINED;
|
||||
} else {
|
||||
MOZ_ASSERT(rv != NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW,
|
||||
"How did we get a non-undefined return value?");
|
||||
nsAutoJSString result;
|
||||
if (!result.init(cx, v)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -104,12 +104,13 @@ void InitPreferredSampleRate()
|
||||
cubeb* GetCubebContextUnlocked()
|
||||
{
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
if (sCubebContext ||
|
||||
cubeb_init(&sCubebContext, "CubebUtils") == CUBEB_OK) {
|
||||
return sCubebContext;
|
||||
if (!sCubebContext) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (cubeb_init(&sCubebContext, "CubebUtils") != CUBEB_OK) {
|
||||
NS_WARNING("cubeb_init failed");
|
||||
}
|
||||
}
|
||||
NS_WARNING("cubeb_init failed");
|
||||
return nullptr;
|
||||
return sCubebContext;
|
||||
}
|
||||
|
||||
uint32_t GetCubebLatency()
|
||||
|
@ -56,10 +56,6 @@
|
||||
#include "RtspOmxDecoder.h"
|
||||
#include "RtspOmxReader.h"
|
||||
#endif
|
||||
#ifdef MOZ_WMF
|
||||
#include "WMFDecoder.h"
|
||||
#include "WMFReader.h"
|
||||
#endif
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
#include "DirectShowDecoder.h"
|
||||
#include "DirectShowReader.h"
|
||||
@ -334,14 +330,6 @@ IsAndroidMediaType(const nsACString& aType)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WMF
|
||||
static bool
|
||||
IsWMFSupportedType(const nsACString& aType)
|
||||
{
|
||||
return WMFDecoder::CanPlayType(aType, NS_LITERAL_STRING(""));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
static bool
|
||||
IsDirectShowSupportedType(const nsACString& aType)
|
||||
@ -481,23 +469,10 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
// Note: DirectShow should come before WMF, so that we prefer DirectShow's
|
||||
// MP3 support over WMF's.
|
||||
if (DirectShowDecoder::GetSupportedCodecs(nsDependentCString(aMIMEType), &codecList)) {
|
||||
result = CANPLAY_MAYBE;
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_WMF
|
||||
if (!Preferences::GetBool("media.fragmented-mp4.exposed", false) &&
|
||||
IsWMFSupportedType(nsDependentCString(aMIMEType))) {
|
||||
if (!aHaveRequestedCodecs) {
|
||||
return CANPLAY_MAYBE;
|
||||
}
|
||||
return WMFDecoder::CanPlayType(nsDependentCString(aMIMEType),
|
||||
aRequestedCodecs)
|
||||
? CANPLAY_YES : CANPLAY_NO;
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
if (IsAppleMediaSupportedType(nsDependentCString(aMIMEType), &codecList)) {
|
||||
result = CANPLAY_MAYBE;
|
||||
@ -637,12 +612,6 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
|
||||
return decoder.forget();
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_WMF
|
||||
if (IsWMFSupportedType(aType)) {
|
||||
decoder = new WMFDecoder();
|
||||
return decoder.forget();
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
if (IsAppleMediaSupportedType(aType)) {
|
||||
decoder = new AppleDecoder();
|
||||
@ -727,17 +696,10 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
|
||||
} else
|
||||
#endif
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
// Note: DirectShowReader is preferred for MP3, but if it's disabled we
|
||||
// fallback to the WMFReader.
|
||||
if (IsDirectShowSupportedType(aType)) {
|
||||
decoderReader = new DirectShowReader(aDecoder);
|
||||
} else
|
||||
#endif
|
||||
#ifdef MOZ_WMF
|
||||
if (IsWMFSupportedType(aType)) {
|
||||
decoderReader = new WMFReader(aDecoder);
|
||||
} else
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
if (IsAppleMediaSupportedType(aType)) {
|
||||
decoderReader = new AppleMP3Reader(aDecoder);
|
||||
@ -781,9 +743,6 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
|
||||
IsMP4SupportedType(aType) ||
|
||||
#endif
|
||||
IsMP3SupportedType(aType) ||
|
||||
#ifdef MOZ_WMF
|
||||
IsWMFSupportedType(aType) ||
|
||||
#endif
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
IsDirectShowSupportedType(aType) ||
|
||||
#endif
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <limits>
|
||||
#include "nsIObserver.h"
|
||||
#include "nsTArray.h"
|
||||
#include "CubebUtils.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
#include "ImageContainer.h"
|
||||
@ -28,10 +29,6 @@
|
||||
#include "mozilla/dom/VideoTrack.h"
|
||||
#include "mozilla/dom/VideoTrackList.h"
|
||||
|
||||
#ifdef MOZ_WMF
|
||||
#include "WMFDecoder.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::media;
|
||||
@ -404,6 +401,11 @@ bool MediaDecoder::Init(MediaDecoderOwner* aOwner)
|
||||
mOwner = aOwner;
|
||||
mVideoFrameContainer = aOwner->GetVideoFrameContainer();
|
||||
MediaShutdownManager::Instance().Register(this);
|
||||
// We don't use the cubeb context yet, but need to ensure it is created on
|
||||
// the main thread.
|
||||
if (!CubebUtils::GetCubebContext()) {
|
||||
NS_WARNING("Audio backend initialization failed.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1509,14 +1511,6 @@ MediaDecoder::IsAndroidMediaEnabled()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WMF
|
||||
bool
|
||||
MediaDecoder::IsWMFEnabled()
|
||||
{
|
||||
return WMFDecoder::IsEnabled();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
bool
|
||||
MediaDecoder::IsAppleMP3Enabled()
|
||||
|
@ -159,10 +159,11 @@ MediaTaskQueue::AwaitShutdownAndIdle()
|
||||
nsRefPtr<ShutdownPromise>
|
||||
MediaTaskQueue::BeginShutdown()
|
||||
{
|
||||
// Make sure there are no tasks for this queue waiting in the caller's tail
|
||||
// dispatcher.
|
||||
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
|
||||
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
|
||||
// Dispatch any tasks for this queue waiting in the caller's tail dispatcher,
|
||||
// since this is the last opportunity to do so.
|
||||
if (AbstractThread* currentThread = AbstractThread::GetCurrent()) {
|
||||
currentThread->TailDispatcher().DispatchTasksFor(this);
|
||||
}
|
||||
|
||||
MonitorAutoLock mon(mQueueMonitor);
|
||||
mIsShutdown = true;
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
already_AddRefed<nsIRunnable> aRunnable,
|
||||
AbstractThread::DispatchFailureHandling aFailureHandling = AbstractThread::AssertDispatchSuccess) = 0;
|
||||
|
||||
virtual void DispatchTasksFor(AbstractThread* aThread) = 0;
|
||||
virtual bool HasTasksFor(AbstractThread* aThread) = 0;
|
||||
virtual void DrainDirectTasks() = 0;
|
||||
};
|
||||
@ -82,14 +83,7 @@ public:
|
||||
MOZ_ASSERT(mDirectTasks.empty());
|
||||
|
||||
for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
|
||||
UniquePtr<PerThreadTaskGroup> group(Move(mTaskGroups[i]));
|
||||
nsRefPtr<AbstractThread> thread = group->mThread;
|
||||
|
||||
AbstractThread::DispatchFailureHandling failureHandling = group->mFailureHandling;
|
||||
AbstractThread::DispatchReason reason = mIsTailDispatcher ? AbstractThread::TailDispatch
|
||||
: AbstractThread::NormalDispatch;
|
||||
nsCOMPtr<nsIRunnable> r = new TaskGroupRunnable(Move(group));
|
||||
thread->Dispatch(r.forget(), failureHandling, reason);
|
||||
DispatchTaskGroup(Move(mTaskGroups[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,6 +126,17 @@ public:
|
||||
return !!GetTaskGroup(aThread) || (aThread == AbstractThread::GetCurrent() && !mDirectTasks.empty());
|
||||
}
|
||||
|
||||
void DispatchTasksFor(AbstractThread* aThread) override
|
||||
{
|
||||
for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
|
||||
if (mTaskGroups[i]->mThread == aThread) {
|
||||
DispatchTaskGroup(Move(mTaskGroups[i]));
|
||||
mTaskGroups.RemoveElementAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct PerThreadTaskGroup
|
||||
@ -215,6 +220,17 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DispatchTaskGroup(UniquePtr<PerThreadTaskGroup> aGroup)
|
||||
{
|
||||
nsRefPtr<AbstractThread> thread = aGroup->mThread;
|
||||
|
||||
AbstractThread::DispatchFailureHandling failureHandling = aGroup->mFailureHandling;
|
||||
AbstractThread::DispatchReason reason = mIsTailDispatcher ? AbstractThread::TailDispatch
|
||||
: AbstractThread::NormalDispatch;
|
||||
nsCOMPtr<nsIRunnable> r = new TaskGroupRunnable(Move(aGroup));
|
||||
thread->Dispatch(r.forget(), failureHandling, reason);
|
||||
}
|
||||
|
||||
// Direct tasks.
|
||||
std::queue<nsCOMPtr<nsIRunnable>> mDirectTasks;
|
||||
|
||||
|
@ -54,9 +54,6 @@ if CONFIG['MOZ_DIRECTSHOW']:
|
||||
if CONFIG['MOZ_ANDROID_OMX']:
|
||||
DIRS += ['android']
|
||||
|
||||
if CONFIG['MOZ_WMF']:
|
||||
DIRS += ['wmf']
|
||||
|
||||
if CONFIG['MOZ_FMP4']:
|
||||
DIRS += ['fmp4']
|
||||
|
||||
|