Merge inbound to m-c. a=merge

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-02-10 16:03:15 -05:00
commit 74f80ff51c
628 changed files with 7368 additions and 6558 deletions

View File

@ -34,7 +34,10 @@ var security = {
var isBroken =
(ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_BROKEN);
var isInsecure =
var isMixed =
(ui.state & (Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT));
var isInsecure =
(ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_INSECURE);
var isEV =
(ui.state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
@ -54,6 +57,7 @@ var security = {
encryptionStrength : undefined,
version: undefined,
isBroken : isBroken,
isMixed : isMixed,
isEV : isEV,
cert : cert,
fullLocation : gWindow.location
@ -92,6 +96,7 @@ var security = {
encryptionStrength : 0,
version: "",
isBroken : isBroken,
isMixed : isMixed,
isEV : isEV,
cert : null,
fullLocation : gWindow.location
@ -253,7 +258,14 @@ function securityOnLoad() {
var msg2;
if (info.isBroken) {
hdr = pkiBundle.getString("pageInfo_MixedContent");
if (info.isMixed) {
hdr = pkiBundle.getString("pageInfo_MixedContent");
} else {
hdr = pkiBundle.getFormattedString("pageInfo_BrokenEncryption",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
}
msg1 = pkiBundle.getString("pageInfo_Privacy_Broken1");
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
}

View File

@ -16,6 +16,12 @@ add_task(function* () {
"rc4.example.com": "security-state-weak",
};
yield new promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [
["security.tls.insecure_fallback_hosts", "rc4.example.com"]
]}, resolve);
});
let [tab, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL);
let { $, EVENTS, NetMonitorView } = monitor.panelWin;
let { RequestsMenu } = NetMonitorView;

View File

@ -40,9 +40,12 @@ add_task(function* () {
let { RequestsMenu, NetworkDetails } = NetMonitorView;
RequestsMenu.lazyUpdate = false;
info("Enabling SSLv3 for the test.");
info("Enabling SSLv3 and RC4 for the test.");
yield new promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [["security.tls.version.min", 0]]}, resolve);
SpecialPowers.pushPrefEnv({"set": [
["security.tls.version.min", 0],
["security.tls.insecure_fallback_hosts", "rc4.example.com,ssl3rc4.example.com"]
]}, resolve);
});
let cipher = $("#security-warning-cipher");

View File

@ -98,7 +98,7 @@ function _imageFromURI(doc, uri, privateMode, callback) {
// favicon).
let defaultURI = faviconSvc.defaultFavicon;
if (!defaultURI.equals(uri))
_imageFromURI(defaultURI, callback);
_imageFromURI(doc, defaultURI, privateMode, callback);
}
});
}

View File

@ -22,8 +22,8 @@ nsChromeRegistryContent::RegisterRemoteChrome(
const nsACString& aLocale,
bool aReset)
{
NS_ABORT_IF_FALSE(aReset || mLocale.IsEmpty(),
"RegisterChrome twice?");
MOZ_ASSERT(aReset || mLocale.IsEmpty(),
"RegisterChrome twice?");
if (aReset) {
mPackagesHash.Clear();

View File

@ -27,7 +27,7 @@ ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
static inline double
StepEnd(uint32_t aSteps, double aPortion)
{
NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range");
uint32_t step = uint32_t(aPortion * aSteps); // floor
return double(step) / double(aSteps);
}
@ -47,7 +47,7 @@ ComputedTimingFunction::GetValue(double aPortion) const
// really meant it.
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
default:
NS_ABORT_IF_FALSE(false, "bad type");
MOZ_ASSERT(false, "bad type");
// fall through
case nsTimingFunction::StepEnd:
return StepEnd(mSteps, aPortion);

View File

@ -831,6 +831,7 @@ WebappsApplicationMgmt.prototype = {
"Webapps:Uninstall:Return:KO",
"Webapps:Install:Return:OK",
"Webapps:GetNotInstalled:Return:OK",
"Webapps:GetIcon:Return",
"Webapps:Import:Return",
"Webapps:ExtractManifest:Return",
"Webapps:SetEnabled:Return"]);
@ -896,6 +897,21 @@ WebappsApplicationMgmt.prototype = {
return request;
},
getIcon: function(aApp, aIconID, aEntryPoint) {
return this.createPromise(function(aResolve, aReject) {
cpmm.sendAsyncMessage("Webapps:GetIcon", {
oid: this._id,
manifestURL: aApp.manifestURL,
iconID: aIconID,
entryPoint: aEntryPoint,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
});
}.bind(this));
},
getNotInstalled: function() {
let request = this.createRequest();
let principal = this._window.document.nodePrincipal;
@ -970,7 +986,8 @@ WebappsApplicationMgmt.prototype = {
let msg = aMessage.data;
let req;
if (["Webapps:Import:Return",
if (["Webapps:GetIcon:Return",
"Webapps:Import:Return",
"Webapps:ExtractManifest:Return"]
.indexOf(aMessage.name) != -1) {
req = this.takePromiseResolver(msg.requestID);
@ -1036,7 +1053,18 @@ WebappsApplicationMgmt.prototype = {
this.__DOM_IMPL__.dispatchEvent(event);
}
break;
case "Webapps:GetIcon:Return":
if (msg.blob) {
req.resolve(Cu.cloneInto(msg.blob, this._window));
} else if (msg.error && msg.error == "NETWORK_ERROR"
&& !this._window.navigator.onLine) {
req.reject(new this._window.DOMError("NETWORK_OFFLINE"));
} else {
req.reject(new this._window.DOMError(msg.error || ""));
}
break;
}
if (aMessage.name !== "Webapps:Uninstall:Broadcast:Return:OK") {
this.removeRequest(msg.requestID);
}

View File

@ -224,6 +224,7 @@ this.DOMApplicationRegistry = {
"Webapps:RegisterBEP",
"Webapps:Export",
"Webapps:Import",
"Webapps:GetIcon",
"Webapps:ExtractManifest",
"Webapps:SetEnabled",
"child-process-shutdown"];
@ -650,7 +651,7 @@ this.DOMApplicationRegistry = {
// c. for all apps in the new core registry, install them if they are not
// yet in the current registry, and run installPermissions()
installSystemApps: function() {
return Task.spawn(function() {
return Task.spawn(function*() {
let file;
try {
file = FileUtils.getFile("coreAppsDir", ["webapps", "webapps.json"], false);
@ -727,7 +728,7 @@ this.DOMApplicationRegistry = {
},
loadAndUpdateApps: function() {
return Task.spawn(function() {
return Task.spawn(function*() {
let runUpdate = AppsUtils.isFirstRun(Services.prefs);
yield this.loadCurrentRegistry();
@ -760,13 +761,16 @@ this.DOMApplicationRegistry = {
if (runUpdate) {
// Run migration before uninstall of core apps happens.
try {
let appMigrator = Components.classes["@mozilla.org/app-migrator;1"].createInstance(Components.interfaces.nsIObserver);
appMigrator.observe(null, "webapps-before-update-merge", null);
} catch(e) {
debug("Exception running app migration: ");
debug(e.name + " " + e.message);
debug("Skipping app migration.");
let appMigrator = Components.classes["@mozilla.org/app-migrator;1"];
if (appMigrator) {
try {
appMigrator = appMigrator.createInstance(Components.interfaces.nsIObserver);
appMigrator.observe(null, "webapps-before-update-merge", null);
} catch(e) {
debug("Exception running app migration: ");
debug(e.name + " " + e.message);
debug("Skipping app migration.");
}
}
#ifdef MOZ_WIDGET_GONK
@ -1425,6 +1429,9 @@ this.DOMApplicationRegistry = {
case "Webapps:RegisterBEP":
this.registerBrowserElementParentForApp(msg, mm);
break;
case "Webapps:GetIcon":
this.getIcon(msg, mm);
break;
case "Webapps:Export":
this.doExport(msg, mm);
break;
@ -2357,7 +2364,6 @@ this.DOMApplicationRegistry = {
});
},
updatePackagedApp: Task.async(function*(aData, aId, aApp, aNewManifest) {
debug("updatePackagedApp");
@ -3035,7 +3041,7 @@ this.DOMApplicationRegistry = {
this.webapps[id].manifestURL, jsonManifest);
}
for each (let prop in ["installState", "downloadAvailable", "downloading",
for (let prop of ["installState", "downloadAvailable", "downloading",
"downloadSize", "readyToApplyDownload"]) {
aData.app[prop] = appObject[prop];
}
@ -3348,7 +3354,6 @@ this.DOMApplicationRegistry = {
oldPackage = oldPackage || (hash == aOldApp.packageHash);
if (oldPackage) {
debug("package's etag or hash unchanged; sending 'applied' event");
// The package's Etag or hash has not changed.
@ -4281,6 +4286,74 @@ this.DOMApplicationRegistry = {
});
},
getIcon: function(aData, aMm) {
function sendError(aError) {
debug("getIcon error: " + aError);
aData.error = aError;
aMm.sendAsyncMessage("Webapps:GetIcon:Return", aData);
}
let app = this.getAppByManifestURL(aData.manifestURL);
if (!app) {
sendError("NO_APP");
return;
}
function loadIcon(aUrl) {
let fallbackMimeType = aUrl.indexOf('.') >= 0 ?
"image/" + aUrl.split(".").reverse()[0] : "";
// Set up an xhr to download a blob.
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
xhr.mozBackgroundRequest = true;
xhr.open("GET", aUrl, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function() {
debug("Got http status=" + xhr.status + " for " + aUrl);
if (xhr.status == 200) {
let blob = xhr.response;
// Reusing aData with sendAsyncMessage() leads to an empty blob in
// the child.
let payload = {
"oid": aData.oid,
"requestID": aData.requestID,
"blob": blob,
"type": xhr.getResponseHeader("Content-Type") || fallbackMimeType
};
aMm.sendAsyncMessage("Webapps:GetIcon:Return", payload);
} else if (xhr.status === 0) {
sendError("NETWORK_ERROR");
} else {
sendError("FETCH_ICON_FAILED");
}
});
xhr.addEventListener("error", function() {
sendError("FETCH_ICON_FAILED");
});
xhr.send();
}
// Get the manifest, to find the icon url in the current locale.
this.getManifestFor(aData.manifestURL, aData.entryPoint)
.then((aManifest) => {
if (!aManifest) {
sendError("FETCH_ICON_FAILED");
return;
}
let manifest = new ManifestHelper(aManifest, app.origin, app.manifestURL);
let url = manifest.iconURLForSize(aData.iconID);
if (!url) {
sendError("NO_ICON");
return;
}
loadIcon(url);
}).catch(() => {
sendError("FETCH_ICON_FAILED");
return;
});
},
getAll: function(aCallback) {
debug("getAll");
let apps = [];
@ -4514,7 +4587,7 @@ this.DOMApplicationRegistry = {
});
},
getManifestFor: function(aManifestURL) {
getManifestFor: function(aManifestURL, aEntryPoint) {
let id = this._appIdForManifestURL(aManifestURL);
let app = this.webapps[id];
if (!id || (app.installState == "pending" && !app.retryingDownload)) {
@ -4522,7 +4595,11 @@ this.DOMApplicationRegistry = {
}
return this._readManifests([{ id: id }]).then((aResult) => {
return aResult[0].manifest;
if (aEntryPoint) {
return aResult[0].manifest.entry_points[aEntryPoint];
} else {
return aResult[0].manifest;
}
});
},

View File

@ -1,13 +1,19 @@
{
"name": "My W3C Web App",
"short_name": "My App",
"icons": [
{
"src": "/favicon.ico",
"sizes": "64x64",
"type": "image/png"
}
],
"icons": {
"15": "/tests/dom/apps/tests/icon15.png",
"48": "/tests/dom/apps/tests/icon48.png"
},
"start_url": "/index.html",
"display": "standalone"
}
"display": "standalone",
"entry_points": {
"ep1": {
"name": "This is an entry point",
"icons": {
"15": "/tests/dom/apps/tests/icon15alternate.png",
"48": "/tests/dom/apps/tests/icon48.png"
}
}
}
}

View File

@ -17,6 +17,26 @@ var gAppName = "appname";
var gDevName = "devname";
var gDevUrl = "http://dev.url";
var gIconData =
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
"\x78\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xD6\xD8\xD4\x4F\x58" +
"\x32\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72" +
"\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61\x67\x65\x52\x65\x61" +
"\x64\x79\x71\xC9\x65\x3C\x00\x00\x00\x39\x50\x4C\x54\x45\xB5\x42" +
"\x42\xCE\x94\x94\xCE\x84\x84\x9C\x21\x21\xAD\x21\x21\xCE\x73\x73" +
"\x9C\x10\x10\xBD\x52\x52\xEF\xD6\xD6\xB5\x63\x63\xA5\x10\x10\xB5" +
"\x00\x00\xE7\xC6\xC6\xE7\xB5\xB5\x9C\x00\x00\x8C\x00\x00\xFF\xFF" +
"\xFF\x7B\x00\x00\xAD\x00\x00\xEC\xAD\x83\x63\x00\x00\x00\x66\x49" +
"\x44\x41\x54\x78\xDA\x6C\x89\x0B\x12\xC2\x40\x08\x43\xB3\xDB\x8F" +
"\x5A\x21\x40\xEF\x7F\x58\xA1\x55\x67\xB6\xD3\xC0\x03\x42\xF0\xDE" +
"\x87\xC2\x3E\xEA\xCE\xF3\x4B\x0D\x30\x27\xAB\xCF\x03\x9C\xFB\xA3" +
"\xEB\xBC\x2D\xBA\xD4\x0F\x84\x97\x9E\x49\x67\xE5\x74\x87\x26\x70" +
"\x21\x0D\x66\xAE\xB6\x26\xB5\x8D\xE5\xE5\xCF\xB4\x9E\x79\x1C\xB9" +
"\x4C\x2E\xB0\x90\x16\x96\x84\xB6\x68\x2F\x84\x45\xF5\x0F\xC4\xA8" +
"\xAB\xFF\x08\x30\x00\x16\x91\x0C\xDD\xAB\xF1\x05\x11\x00\x00\x00" +
"\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
function handleRequest(request, response) {
var query = getQuery(request);
@ -87,6 +107,9 @@ function handleRequest(request, response) {
appName, devName, devUrl);
addZipEntry(zipWriter, app, "index.html");
var iconString = gIconData;
addZipEntry(zipWriter, iconString, "icon.png");
zipWriter.close();
}

View File

@ -12,6 +12,9 @@
"downloads": {}
},
"launch_path": "tests/dom/apps/tests/file_packaged_app.sjs",
"icons": {
"15": "icon.png"
},
"developer": {
"name": "DEVELOPERTOKEN",
"url": "DEVELOPERURLTOKEN"

BIN
dom/apps/tests/icon15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

BIN
dom/apps/tests/icon48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -29,6 +29,9 @@ support-files =
test_packaged_app_common.js
marketplace/*
pkg_install_iframe.html
icon15.png
icon15alternate.png
icon48.png
[test_app_addons.html]
skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app

View File

@ -76,6 +76,28 @@ function checkInstalledApp(aMiniManifestURL,
};
}
var gIconData =
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
"\x78\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xD6\xD8\xD4\x4F\x58" +
"\x32\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72" +
"\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61\x67\x65\x52\x65\x61" +
"\x64\x79\x71\xC9\x65\x3C\x00\x00\x00\x39\x50\x4C\x54\x45\xB5\x42" +
"\x42\xCE\x94\x94\xCE\x84\x84\x9C\x21\x21\xAD\x21\x21\xCE\x73\x73" +
"\x9C\x10\x10\xBD\x52\x52\xEF\xD6\xD6\xB5\x63\x63\xA5\x10\x10\xB5" +
"\x00\x00\xE7\xC6\xC6\xE7\xB5\xB5\x9C\x00\x00\x8C\x00\x00\xFF\xFF" +
"\xFF\x7B\x00\x00\xAD\x00\x00\xEC\xAD\x83\x63\x00\x00\x00\x66\x49" +
"\x44\x41\x54\x78\xDA\x6C\x89\x0B\x12\xC2\x40\x08\x43\xB3\xDB\x8F" +
"\x5A\x21\x40\xEF\x7F\x58\xA1\x55\x67\xB6\xD3\xC0\x03\x42\xF0\xDE" +
"\x87\xC2\x3E\xEA\xCE\xF3\x4B\x0D\x30\x27\xAB\xCF\x03\x9C\xFB\xA3" +
"\xEB\xBC\x2D\xBA\xD4\x0F\x84\x97\x9E\x49\x67\xE5\x74\x87\x26\x70" +
"\x21\x0D\x66\xAE\xB6\x26\xB5\x8D\xE5\xE5\xCF\xB4\x9E\x79\x1C\xB9" +
"\x4C\x2E\xB0\x90\x16\x96\x84\xB6\x68\x2F\x84\x45\xF5\x0F\xC4\xA8" +
"\xAB\xFF\x08\x30\x00\x16\x91\x0C\xDD\xAB\xF1\x05\x11\x00\x00\x00" +
"\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
var gIconSize = 15;
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
@ -195,6 +217,7 @@ var steps = [
info("== TEST == Install packaged app");
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true";
navigator.mozApps.mgmt.oninstall = function(evt) {
info("Got oninstall event");
PackagedTestHelper.gApp = evt.application;
@ -231,6 +254,25 @@ var steps = [
function() {
PackagedTestHelper.setAppVersion(3, PackagedTestHelper.next, false, true);
},
function() {
info("== TEST == Get icon");
var app = PackagedTestHelper.gApp;
navigator.mozApps.mgmt.getIcon(app, gIconSize).then((blob) => {
var reader = new FileReader();
reader.onloadend = function() {
var success = reader.result == gIconData;
ok(success, "== TEST == Icon matches expected icon");
PackagedTestHelper.next();
}
reader.readAsBinaryString(blob);
}, (err) => {
ok(false, "Can't get icon: " + err);
PackagedTestHelper.finish();
});
},
function() {
info("== TEST == Install packaged app with a cancel/resume");
var miniManifestURL = PackagedTestHelper.gSJS +

View File

@ -19,6 +19,43 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={1075716}
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
var gIconData =
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
"\x78\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xD6\xD8\xD4\x4F\x58" +
"\x32\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72" +
"\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61\x67\x65\x52\x65\x61" +
"\x64\x79\x71\xC9\x65\x3C\x00\x00\x00\x39\x50\x4C\x54\x45\xB5\x42" +
"\x42\xCE\x94\x94\xCE\x84\x84\x9C\x21\x21\xAD\x21\x21\xCE\x73\x73" +
"\x9C\x10\x10\xBD\x52\x52\xEF\xD6\xD6\xB5\x63\x63\xA5\x10\x10\xB5" +
"\x00\x00\xE7\xC6\xC6\xE7\xB5\xB5\x9C\x00\x00\x8C\x00\x00\xFF\xFF" +
"\xFF\x7B\x00\x00\xAD\x00\x00\xEC\xAD\x83\x63\x00\x00\x00\x66\x49" +
"\x44\x41\x54\x78\xDA\x6C\x89\x0B\x12\xC2\x40\x08\x43\xB3\xDB\x8F" +
"\x5A\x21\x40\xEF\x7F\x58\xA1\x55\x67\xB6\xD3\xC0\x03\x42\xF0\xDE" +
"\x87\xC2\x3E\xEA\xCE\xF3\x4B\x0D\x30\x27\xAB\xCF\x03\x9C\xFB\xA3" +
"\xEB\xBC\x2D\xBA\xD4\x0F\x84\x97\x9E\x49\x67\xE5\x74\x87\x26\x70" +
"\x21\x0D\x66\xAE\xB6\x26\xB5\x8D\xE5\xE5\xCF\xB4\x9E\x79\x1C\xB9" +
"\x4C\x2E\xB0\x90\x16\x96\x84\xB6\x68\x2F\x84\x45\xF5\x0F\xC4\xA8" +
"\xAB\xFF\x08\x30\x00\x16\x91\x0C\xDD\xAB\xF1\x05\x11\x00\x00\x00" +
"\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
var gAlternateIconData =
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x02\x00\x00\x00\xB4\xB4\x02" +
"\x1D\x00\x00\x00\xA7\x49\x44\x41\x54\x28\x15\x63\x64\x95\x9D\xC0" +
"\x40\x34\x60\x22\x5A\x25\x48\xE1\x50\x55\xCD\x02\xF1\xE5\xAF\x47" +
"\xF9\xC8\xDE\x7D\x79\xE3\x86\xB8\x86\x06\x44\x64\x6F\x67\x9B\xE7" +
"\x54\x6E\x08\x1B\xC5\x97\x0B\x7C\x5C\x6F\xEF\xDC\x06\x94\x00\x2A" +
"\x05\xB2\x81\x08\xC8\x56\x72\x70\x82\x28\x05\x92\x50\xB3\x81\x2C" +
"\xA0\xBA\x5B\xD7\x8F\x3C\xCF\xBF\x54\x79\xE3\x25\x84\x0D\x51\xF4" +
"\xE7\xC3\x3B\xB8\x6A\x84\xD9\x2C\x02\x42\x40\xD1\xCF\xBF\x3F\x01" +
"\x49\x08\x1B\xA2\x08\x85\x0D\xD7\x07\x31\xE3\xC3\xEF\xBF\x40\x11" +
"\x64\xF3\x20\x0A\x80\x1E\xBB\x7F\xF2\x04\xD4\x25\x40\xD6\xB3\xFB" +
"\x0F\x80\x4A\x05\x58\x99\xE1\x6C\xA0\x3A\xA0\x93\x80\xE2\x40\xC6" +
"\xC1\x19\xD3\x1E\x5F\x3C\xCF\x38\x68\xD2\x09\x00\x73\x68\x4B\x47" +
"\x39\xF8\xEA\x1A\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
var gGenerator = runTest();
function go() {
@ -45,6 +82,20 @@ function cbError(aEvent) {
finish();
}
function iconTest(app, iconSize, entryPoint, testFunction) {
navigator.mozApps.mgmt.getIcon(app, iconSize, entryPoint).then((blob) => {
var reader = new FileReader();
reader.onloadend = function() {
testFunction(reader.result);
continueTest();
}
reader.readAsBinaryString(blob);
}, (err) => {
ok(false, "Couldn't get icon.");
finish();
});
}
SimpleTest.waitForExplicitFinish();
/**
@ -77,6 +128,30 @@ function runTest() {
ok(app, "App is non-null");
is(app.manifestURL, manifestURL, "App manifest url is correct.");
info("Fetching 15x15 icon");
iconTest(app, 15, undefined, (iconData) => {
is(iconData, gIconData, "Fetches 15x15 icon successfully.")
});
yield undefined;
info("Fetching 48x48 icon");
iconTest(app, 48, "ep1", (iconData) => {
ok(iconData.length == 4762, "Fetches 48x48 icon successfully.")
});
yield undefined;
info("Fetching 30x30 icon");
iconTest(app, 30, undefined, (iconData) => {
is(iconData, gIconData, "Fetches 15x15 icon as best fit for 30x30.")
});
yield undefined;
info("Fetching entry-point icon");
iconTest(app, 15, "ep1", (iconData) => {
is(iconData, gAlternateIconData, "Entry-point Icon fetched successfully.")
});
yield undefined;
request = navigator.mozApps.mgmt.uninstall(app);
request.onerror = cbError;
request.onsuccess = continueTest;

View File

@ -42,7 +42,7 @@ private: //data
NS_IMETHODIMP
ArchiveRequestEvent::Run()
{
NS_ABORT_IF_FALSE(mRequest, "the request is not longer valid");
MOZ_ASSERT(mRequest, "the request is not longer valid");
mRequest->Run();
return NS_OK;
}

View File

@ -48,9 +48,9 @@ Attr::Attr(nsDOMAttributeMap *aAttrMap,
const nsAString &aValue, bool aNsAware)
: nsIAttribute(aAttrMap, aNodeInfo, aNsAware), mValue(aValue)
{
NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
"Wrong nodeType");
MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
"Wrong nodeType");
// We don't add a reference to our content. It will tell us
// to drop our reference when it goes away.

View File

@ -19,8 +19,8 @@ class Comment MOZ_FINAL : public nsGenericDOMDataNode,
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
"Bad NodeType in aNodeInfo");
}
virtual ~Comment();

View File

@ -56,7 +56,7 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Called on the wrong thread");
MOZ_ASSERT(NS_IsMainThread(), "Called on the wrong thread");
JS::Rooted<JSObject*> view(aCx, aArray.Obj());

View File

@ -27,11 +27,10 @@ class DocumentFragment : public FragmentOrElement,
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() ==
nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
kNameSpaceID_None),
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
kNameSpaceID_None),
"Bad NodeType in aNodeInfo");
}
public:

View File

@ -74,8 +74,8 @@ DocumentType::DocumentType(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
mSystemId(aSystemId),
mInternalSubset(aInternalSubset)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
}
DocumentType::~DocumentType()

View File

@ -204,9 +204,9 @@ Element::NotifyStateChange(EventStates aStates)
void
Element::UpdateLinkState(EventStates aState)
{
NS_ABORT_IF_FALSE(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED)),
"Unexpected link state bits");
MOZ_ASSERT(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED)),
"Unexpected link state bits");
mState =
(mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
aState;

View File

@ -152,8 +152,8 @@ public:
FragmentOrElement(aNodeInfo),
mState(NS_EVENT_STATE_MOZ_READONLY)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
"Bad NodeType in aNodeInfo");
SetIsElement();
}
#endif // MOZILLA_INTERNAL_API

View File

@ -580,9 +580,9 @@ EventSource::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsresult
EventSource::OnRedirectVerifyCallback(nsresult aResult)
{
NS_ABORT_IF_FALSE(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ABORT_IF_FALSE(mNewRedirectChannel,
"mNewRedirectChannel not set in callback");
MOZ_ASSERT(mRedirectCallback, "mRedirectCallback not set in callback");
MOZ_ASSERT(mNewRedirectChannel,
"mNewRedirectChannel not set in callback");
NS_ENSURE_SUCCESS(aResult, aResult);

View File

@ -29,7 +29,7 @@ Link::Link(Element *aElement)
, mNeedsRegistration(false)
, mRegistered(false)
{
NS_ABORT_IF_FALSE(mElement, "Must have an element");
MOZ_ASSERT(mElement, "Must have an element");
}
Link::~Link()
@ -58,9 +58,9 @@ Link::SetLinkState(nsLinkState aState)
// Per IHistory interface documentation, we are no longer registered.
mRegistered = false;
NS_ABORT_IF_FALSE(LinkState() == NS_EVENT_STATE_VISITED ||
LinkState() == NS_EVENT_STATE_UNVISITED,
"Unexpected state obtained from LinkState()!");
MOZ_ASSERT(LinkState() == NS_EVENT_STATE_VISITED ||
LinkState() == NS_EVENT_STATE_UNVISITED,
"Unexpected state obtained from LinkState()!");
// Tell the element to update its visited state
mElement->UpdateState(true);

View File

@ -48,7 +48,7 @@ NodeInfo::NodeInfo(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID,
nsNodeInfoManager *aOwnerManager)
{
CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager");
MOZ_ASSERT(aOwnerManager, "Invalid aOwnerManager");
// Initialize mInner
NS_ADDREF(mInner.mName = aName);
@ -104,8 +104,7 @@ NodeInfo::NodeInfo(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID,
SetDOMStringToNull(mLocalName);
break;
default:
NS_ABORT_IF_FALSE(aNodeType == UINT16_MAX,
"Unknown node type");
MOZ_ASSERT(aNodeType == UINT16_MAX, "Unknown node type");
}
}

View File

@ -75,42 +75,42 @@ inline void
CheckValidNodeInfo(uint16_t aNodeType, nsIAtom *aName, int32_t aNamespaceID,
nsIAtom* aExtraName)
{
NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
aNodeType == nsIDOMNode::TEXT_NODE ||
aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
aNodeType == nsIDOMNode::COMMENT_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
aNodeType == UINT16_MAX,
"Invalid nodeType");
NS_ABORT_IF_FALSE((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
!!aExtraName,
"Supply aExtraName for and only for PIs and doctypes");
NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
aNodeType == UINT16_MAX ||
aNamespaceID == kNameSpaceID_None,
"Only attributes and elements can be in a namespace");
NS_ABORT_IF_FALSE(aName && aName != nsGkAtoms::_empty, "Invalid localName");
NS_ABORT_IF_FALSE(((aNodeType == nsIDOMNode::TEXT_NODE) ==
(aName == nsGkAtoms::textTagName)) &&
((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
(aName == nsGkAtoms::cdataTagName)) &&
((aNodeType == nsIDOMNode::COMMENT_NODE) ==
(aName == nsGkAtoms::commentTagName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
(aName == nsGkAtoms::documentNodeName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
(aName == nsGkAtoms::documentFragmentNodeName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
(aName == nsGkAtoms::documentTypeNodeName)) &&
((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
(aName == nsGkAtoms::processingInstructionTagName)),
"Wrong localName for nodeType");
MOZ_ASSERT(aNodeType == nsIDOMNode::ELEMENT_NODE ||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
aNodeType == nsIDOMNode::TEXT_NODE ||
aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
aNodeType == nsIDOMNode::COMMENT_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
aNodeType == UINT16_MAX,
"Invalid nodeType");
MOZ_ASSERT((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
!!aExtraName,
"Supply aExtraName for and only for PIs and doctypes");
MOZ_ASSERT(aNodeType == nsIDOMNode::ELEMENT_NODE ||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
aNodeType == UINT16_MAX ||
aNamespaceID == kNameSpaceID_None,
"Only attributes and elements can be in a namespace");
MOZ_ASSERT(aName && aName != nsGkAtoms::_empty, "Invalid localName");
MOZ_ASSERT(((aNodeType == nsIDOMNode::TEXT_NODE) ==
(aName == nsGkAtoms::textTagName)) &&
((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
(aName == nsGkAtoms::cdataTagName)) &&
((aNodeType == nsIDOMNode::COMMENT_NODE) ==
(aName == nsGkAtoms::commentTagName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
(aName == nsGkAtoms::documentNodeName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
(aName == nsGkAtoms::documentFragmentNodeName)) &&
((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
(aName == nsGkAtoms::documentTypeNodeName)) &&
((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
(aName == nsGkAtoms::processingInstructionTagName)),
"Wrong localName for nodeType");
}
#endif /* mozilla_dom_NodeInfoInlines_h___ */
#endif /* mozilla_dom_NodeInfoInlines_h___ */

View File

@ -78,9 +78,10 @@ TextInputProcessor::~TextInputProcessor()
}
NS_IMETHODIMP
TextInputProcessor::Init(nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool* aSucceeded)
TextInputProcessor::BeginInputTransaction(
nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool* aSucceeded)
{
MOZ_RELEASE_ASSERT(aSucceeded, "aSucceeded must not be nullptr");
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
@ -88,27 +89,29 @@ TextInputProcessor::Init(nsIDOMWindow* aWindow,
*aSucceeded = false;
return NS_ERROR_INVALID_ARG;
}
return InitInternal(aWindow, aCallback, false, *aSucceeded);
return BeginInputTransactionInternal(aWindow, aCallback, false, *aSucceeded);
}
NS_IMETHODIMP
TextInputProcessor::InitForTests(nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
uint8_t aOptionalArgc,
bool* aSucceeded)
TextInputProcessor::BeginInputTransactionForTests(
nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
uint8_t aOptionalArgc,
bool* aSucceeded)
{
MOZ_RELEASE_ASSERT(aSucceeded, "aSucceeded must not be nullptr");
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsITextInputProcessorCallback* callback =
aOptionalArgc >= 1 ? aCallback : nullptr;
return InitInternal(aWindow, callback, true, *aSucceeded);
return BeginInputTransactionInternal(aWindow, callback, true, *aSucceeded);
}
nsresult
TextInputProcessor::InitInternal(nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool aForTests,
bool& aSucceeded)
TextInputProcessor::BeginInputTransactionInternal(
nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool aForTests,
bool& aSucceeded)
{
aSucceeded = false;
if (NS_WARN_IF(!aWindow)) {
@ -164,9 +167,9 @@ TextInputProcessor::InitInternal(nsIDOMWindow* aWindow,
UnlinkFromTextEventDispatcher();
if (aForTests) {
rv = dispatcher->InitForTests(this);
rv = dispatcher->BeginInputTransactionForTests(this);
} else {
rv = dispatcher->Init(this);
rv = dispatcher->BeginInputTransaction(this);
}
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -190,7 +193,7 @@ TextInputProcessor::UnlinkFromTextEventDispatcher()
mCallback = nullptr;
nsRefPtr<TextInputProcessorNotification> notification =
new TextInputProcessorNotification("notify-detached");
new TextInputProcessorNotification("notify-end-input-transaction");
bool result = false;
callback->OnNotify(this, notification, &result);
}

View File

@ -38,10 +38,11 @@ protected:
virtual ~TextInputProcessor();
private:
nsresult InitInternal(nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool aForTests,
bool& aSucceeded);
nsresult BeginInputTransactionInternal(
nsIDOMWindow* aWindow,
nsITextInputProcessorCallback* aCallback,
bool aForTests,
bool& aSucceeded);
nsresult CommitCompositionInternal(const nsAString* aCommitString = nullptr,
bool* aSucceeded = nullptr);
nsresult CancelCompositionInternal();

View File

@ -1482,7 +1482,7 @@ WebSocketImpl::Init(JSContext* aCx,
void
WebSocketImpl::AsyncOpen(ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
nsCString asciiOrigin;
aRv = nsContentUtils::GetASCIIOrigin(mPrincipal, asciiOrigin);
@ -1527,7 +1527,7 @@ nsresult
WebSocketImpl::InitializeConnection()
{
AssertIsOnMainThread();
NS_ABORT_IF_FALSE(!mChannel, "mChannel should be null");
MOZ_ASSERT(!mChannel, "mChannel should be null");
nsCOMPtr<nsIWebSocketChannel> wsChannel;
nsAutoCloseWS autoClose(this);

View File

@ -1032,8 +1032,7 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
// If that changes then we probably want to add methods to the
// corresponding SVG types to compare their base values.
// As a shortcut, however, we can begin by comparing the pointers.
NS_ABORT_IF_FALSE(false, "Comparing nsAttrValues that point to SVG "
"data");
MOZ_ASSERT(false, "Comparing nsAttrValues that point to SVG data");
return false;
}
NS_NOTREACHED("unknown type stored in MiscContainer");
@ -1754,7 +1753,7 @@ nsAttrValue::ResetMiscAtomOrString()
void
nsAttrValue::SetSVGType(ValueType aType, const void* aValue,
const nsAString* aSerialized) {
NS_ABORT_IF_FALSE(IsSVGType(aType), "Not an SVG type");
MOZ_ASSERT(IsSVGType(aType), "Not an SVG type");
MiscContainer* cont = EnsureEmptyMiscContainer();
// All SVG types are just pointers to classes so just setting any of them

View File

@ -4277,7 +4277,7 @@ nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
// sXMLFragmentSink now owns the sink
}
nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
NS_ABORT_IF_FALSE(contentsink, "Sink doesn't QI to nsIContentSink!");
MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!");
sXMLFragmentParser->SetContentSink(contentsink);
sXMLFragmentSink->SetTargetDocument(aDocument);

View File

@ -1765,7 +1765,7 @@ GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
nsCOMPtr<nsIClassInfo> ci;
if (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
int32_t id = aNameStruct->mDOMClassInfoID;
NS_ABORT_IF_FALSE(id >= 0, "Negative DOM classinfo?!?");
MOZ_ASSERT(id >= 0, "Negative DOM classinfo?!?");
nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;

View File

@ -269,7 +269,7 @@ nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv)
void
nsDOMDataChannel::Send(File& aData, ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
nsCOMPtr<nsIInputStream> msgStream;
nsresult rv = aData.GetInternalStream(getter_AddRefs(msgStream));
@ -296,7 +296,7 @@ nsDOMDataChannel::Send(File& aData, ErrorResult& aRv)
void
nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
aData.ComputeLengthAndData();
@ -312,7 +312,7 @@ nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv)
void
nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
aData.ComputeLengthAndData();

View File

@ -182,7 +182,7 @@ void
nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
const nsTArray<nsString>& aTokens)
{
NS_ABORT_IF_FALSE(aAttr, "Need an attribute");
MOZ_ASSERT(aAttr, "Need an attribute");
nsAutoString input;
aAttr->ToString(input);
@ -204,7 +204,7 @@ nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
if (iter == end) {
// At this point we're sure the last seen token (if any) wasn't to be
// removed. So the trailing spaces will need to be kept.
NS_ABORT_IF_FALSE(!lastTokenRemoved, "How did this happen?");
MOZ_ASSERT(!lastTokenRemoved, "How did this happen?");
output.Append(Substring(copyStart, end));
break;
@ -227,8 +227,8 @@ nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
} else {
if (lastTokenRemoved && !output.IsEmpty()) {
NS_ABORT_IF_FALSE(!nsContentUtils::IsHTMLWhitespace(
output.Last()), "Invalid last output token");
MOZ_ASSERT(!nsContentUtils::IsHTMLWhitespace(output.Last()),
"Invalid last output token");
output.Append(char16_t(' '));
}
lastTokenRemoved = false;

View File

@ -1716,9 +1716,9 @@ CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas)
return nullptr;
}
NS_ABORT_IF_FALSE(node->IsElement(),
"An nsINode that implements nsIDOMHTMLCanvasElement should "
"be an element.");
MOZ_ASSERT(node->IsElement(),
"An nsINode that implements nsIDOMHTMLCanvasElement should "
"be an element.");
nsLayoutUtils::SurfaceFromElementResult result =
nsLayoutUtils::SurfaceFromElement(node->AsElement());
return result.mSourceSurface->GetDataSurface();
@ -2309,7 +2309,7 @@ nsDOMWindowUtils::GetClassName(JS::Handle<JS::Value> aObject, JSContext* aCx,
}
*aName = NS_strdup(JS_GetClass(aObject.toObjectOrNull())->name);
NS_ABORT_IF_FALSE(*aName, "NS_strdup should be infallible.");
MOZ_ASSERT(*aName, "NS_strdup should be infallible.");
return NS_OK;
}
@ -2698,9 +2698,9 @@ nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
property = eCSSProperty_UNKNOWN;
}
NS_ABORT_IF_FALSE(property == eCSSProperty_UNKNOWN ||
!nsCSSProps::IsShorthand(property),
"should not have shorthand");
MOZ_ASSERT(property == eCSSProperty_UNKNOWN ||
!nsCSSProps::IsShorthand(property),
"should not have shorthand");
StyleAnimationValue v1, v2;
if (property == eCSSProperty_UNKNOWN ||

View File

@ -1056,8 +1056,8 @@ void
TransferZoomLevels(nsIDocument* aFromDoc,
nsIDocument* aToDoc)
{
NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
"transferring zoom levels from/to null doc");
MOZ_ASSERT(aFromDoc && aToDoc,
"transferring zoom levels from/to null doc");
nsIPresShell* fromShell = aFromDoc->GetShell();
if (!fromShell)
@ -1083,8 +1083,8 @@ TransferZoomLevels(nsIDocument* aFromDoc,
void
TransferShowingState(nsIDocument* aFromDoc, nsIDocument* aToDoc)
{
NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
"transferring showing state from/to null doc");
MOZ_ASSERT(aFromDoc && aToDoc,
"transferring showing state from/to null doc");
if (aFromDoc->IsShowing()) {
aToDoc->OnPageShow(true, nullptr);
@ -1624,8 +1624,8 @@ ClearAllBoxObjects(nsIContent* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
nsIDocument::~nsIDocument()
{
NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
"must not have media query lists left");
MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
"must not have media query lists left");
if (mNodeInfoManager) {
mNodeInfoManager->DropDocumentReference();
@ -2211,8 +2211,8 @@ nsDocument::Init()
// mNodeInfo keeps NodeInfoManager alive!
mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"Bad NodeType in aNodeInfo");
NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!");
@ -4672,11 +4672,11 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
"Script global object must be an inner window!");
}
#endif
NS_ABORT_IF_FALSE(aScriptGlobalObject || !mAnimationController ||
mAnimationController->IsPausedByType(
nsSMILTimeContainer::PAUSE_PAGEHIDE |
nsSMILTimeContainer::PAUSE_BEGIN),
"Clearing window pointer while animations are unpaused");
MOZ_ASSERT(aScriptGlobalObject || !mAnimationController ||
mAnimationController->IsPausedByType(
nsSMILTimeContainer::PAUSE_PAGEHIDE |
nsSMILTimeContainer::PAUSE_BEGIN),
"Clearing window pointer while animations are unpaused");
if (mScriptGlobalObject && !aScriptGlobalObject) {
// We're detaching from the window. We need to grab a pointer to
@ -10406,8 +10406,8 @@ nsDocument::RemoveImage(imgIRequest* aImage, uint32_t aFlags)
// Get the old count. It should exist and be > 0.
uint32_t count = 0;
DebugOnly<bool> found = mImageTracker.Get(aImage, &count);
NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!");
NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!");
MOZ_ASSERT(found, "Removing image that wasn't in the tracker!");
MOZ_ASSERT(count > 0, "Entry in the cache tracker with count 0!");
// We're removing, so decrement the count.
count--;

View File

@ -90,7 +90,6 @@
#include "jsapi.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/dom/SVGIFrameElement.h"
#include "nsSandboxFlags.h"
#include "mozilla/layers/CompositorChild.h"
@ -211,8 +210,7 @@ nsFrameLoader::LoadFrame()
nsAutoString src;
bool isSrcdoc = (mOwnerContent->IsHTML(nsGkAtoms::iframe) ||
mOwnerContent->IsSVG(nsGkAtoms::iframe)) &&
bool isSrcdoc = mOwnerContent->IsHTML(nsGkAtoms::iframe) &&
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
if (isSrcdoc) {
src.AssignLiteral("about:srcdoc");
@ -415,8 +413,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
nsCOMPtr<nsIURI> referrer;
nsAutoString srcdoc;
bool isSrcdoc = (mOwnerContent->IsHTML(nsGkAtoms::iframe) ||
mOwnerContent->IsSVG(nsGkAtoms::iframe)) &&
bool isSrcdoc = mOwnerContent->IsHTML(nsGkAtoms::iframe) &&
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
srcdoc);
@ -1657,13 +1654,8 @@ nsFrameLoader::MaybeCreateDocShell()
// Apply sandbox flags even if our owner is not an iframe, as this copies
// flags from our owning content's owning document.
uint32_t sandboxFlags = 0;
if (!mOwnerContent->IsSVG(nsGkAtoms::iframe)) {
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
if (iframe) {
sandboxFlags = iframe->GetSandboxFlags();
}
} else {
SVGIFrameElement* iframe = static_cast<SVGIFrameElement*>(mOwnerContent);
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
if (iframe) {
sandboxFlags = iframe->GetSandboxFlags();
}
ApplySandboxFlags(sandboxFlags);
@ -1679,8 +1671,7 @@ nsFrameLoader::MaybeCreateDocShell()
nsAutoString frameName;
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
if ((namespaceID == kNameSpaceID_XHTML || namespaceID == kNameSpaceID_SVG)
&& !mOwnerContent->IsInHTMLDocument()) {
if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
} else {
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);

View File

@ -1,21 +0,0 @@
--- nsFrameLoader.cpp
+++ nsFrameLoader.cpp
@@ -48,17 +48,17 @@
#include "nsIDOMHTMLDocument.h"
#include "nsIXULWindow.h"
#include "nsIEditor.h"
#include "nsIMozBrowserFrame.h"
#include "nsIPermissionManager.h"
#include "nsISHistory.h"
#include "nsNullPrincipal.h"
#include "nsIScriptError.h"
-
+#include "nsGlobalWindow.h"
#include "nsLayoutUtils.h"
#include "nsView.h"
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsGkAtoms.h"

View File

@ -1537,41 +1537,42 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
if (dataStringBuf && dataStringLength > 0) {
AutoSafeJSContext cx;
JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
if (global) {
JSAutoCompartment ac(cx, global);
JS::CompileOptions options(cx);
options.setFileAndLine(url.get(), 1);
options.setNoScriptRval(true);
JS::Rooted<JSScript*> script(cx);
// Compile the script in the compilation scope instead of the current global
// to avoid keeping the current compartment alive.
JS::Rooted<JSObject*> global(cx, xpc::CompilationScope());
if (aRunInGlobalScope) {
if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
return;
}
} else {
// We can't clone compile-and-go scripts.
options.setCompileAndGo(false);
if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
return;
}
JSAutoCompartment ac(cx, global);
JS::CompileOptions options(cx, JSVERSION_LATEST);
options.setFileAndLine(url.get(), 1);
options.setNoScriptRval(true);
JS::Rooted<JSScript*> script(cx);
if (aRunInGlobalScope) {
if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
return;
}
aScriptp.set(script);
nsAutoCString scheme;
uri->GetScheme(scheme);
// We don't cache data: scripts!
if (aShouldCache && !scheme.EqualsLiteral("data")) {
nsFrameScriptObjectExecutorHolder* holder;
// Root the object also for caching.
if (script) {
holder = new nsFrameScriptObjectExecutorHolder(cx, script, aRunInGlobalScope);
}
sCachedScripts->Put(aURL, holder);
} else {
// We can't clone compile-and-go scripts.
options.setCompileAndGo(false);
if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
return;
}
}
aScriptp.set(script);
nsAutoCString scheme;
uri->GetScheme(scheme);
// We don't cache data: scripts!
if (aShouldCache && !scheme.EqualsLiteral("data")) {
nsFrameScriptObjectExecutorHolder* holder;
// Root the object also for caching.
if (script) {
holder = new nsFrameScriptObjectExecutorHolder(cx, script, aRunInGlobalScope);
}
sCachedScripts->Put(aURL, holder);
}
}
}

View File

@ -42,25 +42,23 @@ using namespace mozilla::dom;
nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsIContent(aNodeInfo)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
mNodeInfo->NodeType() ==
nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
}
nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsIContent(aNodeInfo)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
mNodeInfo->NodeType() ==
nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
}
nsGenericDOMDataNode::~nsGenericDOMDataNode()

View File

@ -1524,7 +1524,7 @@ nsGlobalWindow::CleanUp()
}
if (mCleanMessageManager) {
NS_ABORT_IF_FALSE(mIsChrome, "only chrome should have msg manager cleaned");
MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this);
if (asChrome->mMessageManager) {
static_cast<nsFrameMessageManager*>(
@ -8119,10 +8119,10 @@ PopulateMessagePortList(MessagePortBase* aKey, MessagePortBase* aValue, void* aC
NS_IMETHODIMP
PostMessageEvent::Run()
{
NS_ABORT_IF_FALSE(mTargetWindow->IsOuterWindow(),
"should have been passed an outer window!");
NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(),
"should have been passed an outer window!");
MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
"should have been passed an outer window!");
MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
"should have been passed an outer window!");
AutoJSAPI jsapi;
jsapi.Init();
@ -8137,8 +8137,8 @@ PostMessageEvent::Run()
targetWindow->IsClosedOrClosing())
return NS_OK;
NS_ABORT_IF_FALSE(targetWindow->IsInnerWindow(),
"we ordered an inner window!");
MOZ_ASSERT(targetWindow->IsInnerWindow(),
"we ordered an inner window!");
JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor());
// Ensure that any origin which might have been provided is the origin of this
@ -8235,8 +8235,8 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
nsRefPtr<nsGlobalWindow> callerInnerWin = CallerInnerWindow();
nsIPrincipal* callerPrin;
if (callerInnerWin) {
NS_ABORT_IF_FALSE(callerInnerWin->IsInnerWindow(),
"should have gotten an inner window here");
MOZ_ASSERT(callerInnerWin->IsInnerWindow(),
"should have gotten an inner window here");
// Compute the caller's origin either from its principal or, in the case the
// principal doesn't carry a URI (e.g. the system principal), the caller's

View File

@ -1718,8 +1718,8 @@ protected:
~nsGlobalChromeWindow()
{
NS_ABORT_IF_FALSE(mCleanMessageManager,
"chrome windows may always disconnect the msg manager");
MOZ_ASSERT(mCleanMessageManager,
"chrome windows may always disconnect the msg manager");
mGroupMessageManagers.EnumerateRead(DisconnectGroupMessageManager, nullptr);
mGroupMessageManagers.Clear();

View File

@ -94,8 +94,7 @@ nsHostObjectURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
#ifdef DEBUG
nsRefPtr<nsHostObjectURI> uriCheck;
rv = simpleClone->QueryInterface(kHOSTOBJECTURICID, getter_AddRefs(uriCheck));
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
"Unexpected!");
MOZ_ASSERT(NS_SUCCEEDED(rv) && uriCheck);
#endif
nsHostObjectURI* u = static_cast<nsHostObjectURI*>(simpleClone.get());

View File

@ -1062,7 +1062,7 @@ nsINode::IsEqualNode(nsINode* aOther)
break;
}
default:
NS_ABORT_IF_FALSE(false, "Unknown node type");
MOZ_ASSERT(false, "Unknown node type");
}
nsINode* nextNode = node1->GetFirstChild();
@ -1357,7 +1357,7 @@ nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
// return early.
nsIContent* parent = tmp->GetParent();
if (parent && !parent->UnoptimizableCCNode() && parent->IsBlack()) {
NS_ABORT_IF_FALSE(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
MOZ_ASSERT(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
return false;
}
}
@ -2584,7 +2584,7 @@ FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
struct ElementHolder {
ElementHolder() : mElement(nullptr) {}
void AppendElement(Element* aElement) {
NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
MOZ_ASSERT(!mElement, "Should only get one element");
mElement = aElement;
}
void SetCapacity(uint32_t aCapacity) { MOZ_CRASH("Don't call me!"); }

View File

@ -136,7 +136,7 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
// We should definitely have a request here
NS_ABORT_IF_FALSE(aRequest, "no request?");
MOZ_ASSERT(aRequest, "no request?");
NS_PRECONDITION(aRequest == mCurrentRequest || aRequest == mPendingRequest,
"Unknown request");
@ -227,8 +227,8 @@ nsImageLoadingContent::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus)
if (aRequest == mPendingRequest) {
MakePendingRequestCurrent();
}
NS_ABORT_IF_FALSE(aRequest == mCurrentRequest,
"One way or another, we should be current by now");
MOZ_ASSERT(aRequest == mCurrentRequest,
"One way or another, we should be current by now");
// We just loaded all the data we're going to get. If we're visible and
// haven't done an initial paint (*), we want to make sure the image starts
@ -890,9 +890,9 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
// time. It should always be the same as the principal of this node.
#ifdef DEBUG
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
NS_ABORT_IF_FALSE(thisContent &&
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
"Principal mismatch?");
MOZ_ASSERT(thisContent &&
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
"Principal mismatch?");
#endif
// Are we blocked?
@ -1219,7 +1219,7 @@ void
nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
{
// Sanity
NS_ABORT_IF_FALSE(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
MOZ_ASSERT(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
// We do some slightly illogical stuff here to maintain consistency with
// old behavior that people probably depend on. Even in the case where the
@ -1347,8 +1347,8 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason,
mCurrentRequestFlags = 0;
return;
}
NS_ABORT_IF_FALSE(!mCurrentURI,
"Shouldn't have both mCurrentRequest and mCurrentURI!");
MOZ_ASSERT(!mCurrentURI,
"Shouldn't have both mCurrentRequest and mCurrentURI!");
// Deregister this image from the refresh driver so it no longer receives
// notifications.

View File

@ -605,8 +605,8 @@ nsPerformance::PerformanceEntryComparator::Equals(
const PerformanceEntry* aElem1,
const PerformanceEntry* aElem2) const
{
NS_ABORT_IF_FALSE(aElem1 && aElem2,
"Trying to compare null performance entries");
MOZ_ASSERT(aElem1 && aElem2,
"Trying to compare null performance entries");
return aElem1->StartTime() == aElem2->StartTime();
}
@ -615,8 +615,8 @@ nsPerformance::PerformanceEntryComparator::LessThan(
const PerformanceEntry* aElem1,
const PerformanceEntry* aElem2) const
{
NS_ABORT_IF_FALSE(aElem1 && aElem2,
"Trying to compare null performance entries");
MOZ_ASSERT(aElem1 && aElem2,
"Trying to compare null performance entries");
return aElem1->StartTime() < aElem2->StartTime();
}

View File

@ -18,7 +18,7 @@ void
nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
bool aWatch, bool aReferenceImage)
{
NS_ABORT_IF_FALSE(aFromContent, "Reset() expects non-null content pointer");
MOZ_ASSERT(aFromContent, "Reset() expects non-null content pointer");
Unlink();

View File

@ -26,8 +26,8 @@ class nsTextNode : public mozilla::dom::Text,
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE,
"Bad NodeType in aNodeInfo");
}
public:

View File

@ -1103,8 +1103,8 @@ nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
aDocument->NodePrincipal(), 0, false);
NS_ENSURE_SUCCESS(rv, true);
// Mark the sheet as complete.
NS_ABORT_IF_FALSE(!sheet->IsModified(),
"should not get marked modified during parsing");
MOZ_ASSERT(!sheet->IsModified(),
"should not get marked modified during parsing");
sheet->SetComplete();
// Loop through all the rules found in the CSS text
int32_t ruleCount = sheet->StyleRuleCount();

View File

@ -321,7 +321,7 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
Abort();
}
NS_ABORT_IF_FALSE(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
MOZ_ASSERT(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
mResultJSON.setUndefined();
@ -1915,7 +1915,7 @@ nsXMLHttpRequest::OnDataAvailable(nsIRequest *request,
{
NS_ENSURE_ARG_POINTER(inStr);
NS_ABORT_IF_FALSE(mContext.get() == ctxt,"start context different from OnDataAvailable context");
MOZ_ASSERT(mContext.get() == ctxt,"start context different from OnDataAvailable context");
mProgressSinceLastProgressEvent = true;
@ -3236,8 +3236,8 @@ nsXMLHttpRequest::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
void
nsXMLHttpRequest::StartTimeoutTimer()
{
NS_ABORT_IF_FALSE(mRequestSentTime,
"StartTimeoutTimer mustn't be called before the request was sent!");
MOZ_ASSERT(mRequestSentTime,
"StartTimeoutTimer mustn't be called before the request was sent!");
if (mState & XML_HTTP_REQUEST_DONE) {
// do nothing!
return;

View File

@ -64,11 +64,18 @@ function make_object()
let for_json = { "n": 3, "a": array, "s": "hello", o: { "x": 10 } };
let proto = { data: 42 };
let with_proto = Object.create(proto);
let with_null_proto = Object.create(null);
return { "data": o,
"throwing": throwing,
"document": content.document,
"array": array,
"for_json": for_json
"for_json": for_json,
"with_proto": with_proto,
"with_null_proto": with_null_proto
};
}

View File

@ -126,6 +126,14 @@
ok(j2.a[2] === 3, "JSON array index");
ok(j2.s === "hello", "JSON string property");
ok(j2.o.x === 10, "JSON object property");
let with_proto = message.objects.with_proto;
let proto = Object.getPrototypeOf(with_proto);
ok(proto.data == 42, "Object.getPrototypeOf works on CPOW");
let with_null_proto = message.objects.with_null_proto;
proto = Object.getPrototypeOf(with_null_proto);
ok(proto === null, "Object.getPrototypeOf works on CPOW (null proto)");
}
function recvAsyncMessage(message) {

View File

@ -73,9 +73,9 @@ function createTIP()
createInstance(Components.interfaces.nsITextInputProcessor);
}
function runInitMethodTests()
function runBeginInputTransactionMethodTests()
{
var description = "runInitMethodTest: ";
var description = "runBeginInputTransactionMethodTests: ";
input.value = "";
input.focus();
@ -97,19 +97,19 @@ function runInitMethodTests()
isnot(TIP1, TIP2,
description + "TIP instances should be different");
// init() and initForTests() can take ownership if there is no composition.
ok(TIP1.init(window, simpleCallback),
description + "TIP1.init(window) should succeed because there is no composition");
ok(TIP1.initForTests(window),
description + "TIP1.initForTests(window) should succeed because there is no composition");
ok(TIP2.init(window, simpleCallback),
description + "TIP2.init(window) should succeed because there is no composition");
ok(TIP2.initForTests(window),
description + "TIP2.initForTests(window) should succeed because there is no composition");
// beginInputTransaction() and beginInputTransactionForTests() can take ownership if there is no composition.
ok(TIP1.beginInputTransaction(window, simpleCallback),
description + "TIP1.beginInputTransaction(window) should succeed because there is no composition");
ok(TIP1.beginInputTransactionForTests(window),
description + "TIP1.beginInputTransactionForTests(window) should succeed because there is no composition");
ok(TIP2.beginInputTransaction(window, simpleCallback),
description + "TIP2.beginInputTransaction(window) should succeed because there is no composition");
ok(TIP2.beginInputTransactionForTests(window),
description + "TIP2.beginInputTransactionForTests(window) should succeed because there is no composition");
// Start composition with TIP1, then, other TIPs cannot take ownership during a composition.
ok(TIP1.initForTests(window),
description + "TIP1.initForTests() should succeed because there is no composition");
ok(TIP1.beginInputTransactionForTests(window),
description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition");
var composingStr = "foo";
TIP1.setPendingCompositionString(composingStr);
TIP1.appendClauseToPendingComposition(composingStr.length, TIP1.ATTR_RAW_CLAUSE);
@ -120,37 +120,37 @@ function runInitMethodTests()
// Composing nsITextInputProcessor instance shouldn't allow initialize it again.
try {
TIP1.init(window, simpleCallback);
TIP1.beginInputTransaction(window, simpleCallback);
ok(false,
"TIP1.init(window) should cause throwing an exception because it's composing with different purpose");
"TIP1.beginInputTransaction(window) should cause throwing an exception because it's composing with different purpose");
} catch (e) {
ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
description + "TIP1.init(window) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing for tests");
description + "TIP1.beginInputTransaction(window) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing for tests");
}
try {
TIP1.initForTests(otherWindow);
TIP1.beginInputTransactionForTests(otherWindow);
ok(false,
"TIP1.initForTests(otherWindow) should cause throwing an exception because it's composing on different window");
"TIP1.beginInputTransactionForTests(otherWindow) should cause throwing an exception because it's composing on different window");
} catch (e) {
ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
description + "TIP1.init(otherWindow) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing on this window");
description + "TIP1.beginInputTransaction(otherWindow) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing on this window");
}
ok(TIP1.initForTests(window),
description + "TIP1.initForTests(window) should succeed because TextEventDispatcher was initialized with same purpose");
ok(TIP1.initForTests(childWindow),
description + "TIP1.initForTests(childWindow) should succeed because TextEventDispatcher was initialized with same purpose and is shared by window and childWindow");
ok(!TIP2.init(window, simpleCallback),
description + "TIP2.init(window) should not succeed because there is composition synthesized by TIP1");
ok(!TIP2.initForTests(window),
description + "TIP2.initForTests(window) should not succeed because there is composition synthesized by TIP1");
ok(!TIP2.init(childWindow, simpleCallback),
description + "TIP2.init(childWindow) should not succeed because there is composition synthesized by TIP1");
ok(!TIP2.initForTests(childWindow),
description + "TIP2.initForTests(childWindow) should not succeed because there is composition synthesized by TIP1");
ok(TIP2.init(otherWindow, simpleCallback),
description + "TIP2.init(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
ok(TIP2.initForTests(otherWindow),
description + "TIP2.initForTests(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
ok(TIP1.beginInputTransactionForTests(window),
description + "TIP1.beginInputTransactionForTests(window) should succeed because TextEventDispatcher was initialized with same purpose");
ok(TIP1.beginInputTransactionForTests(childWindow),
description + "TIP1.beginInputTransactionForTests(childWindow) should succeed because TextEventDispatcher was initialized with same purpose and is shared by window and childWindow");
ok(!TIP2.beginInputTransaction(window, simpleCallback),
description + "TIP2.beginInputTransaction(window) should not succeed because there is composition synthesized by TIP1");
ok(!TIP2.beginInputTransactionForTests(window),
description + "TIP2.beginInputTransactionForTests(window) should not succeed because there is composition synthesized by TIP1");
ok(!TIP2.beginInputTransaction(childWindow, simpleCallback),
description + "TIP2.beginInputTransaction(childWindow) should not succeed because there is composition synthesized by TIP1");
ok(!TIP2.beginInputTransactionForTests(childWindow),
description + "TIP2.beginInputTransactionForTests(childWindow) should not succeed because there is composition synthesized by TIP1");
ok(TIP2.beginInputTransaction(otherWindow, simpleCallback),
description + "TIP2.beginInputTransaction(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
ok(TIP2.beginInputTransactionForTests(otherWindow),
description + "TIP2.beginInputTransactionForTests(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
// Let's confirm that the composing string is NOT committed by above tests.
ok(TIP1.commitComposition(),
@ -158,12 +158,12 @@ function runInitMethodTests()
is(input.value, composingStr,
description + "TIP1.commitString() without specifying commit string should be committed with the last composing string");
ok(TIP1.init(window, simpleCallback),
description + "TIP1.init() should succeed because there is no composition #2");
ok(TIP1.initForTests(window),
description + "TIP1.initForTests() should succeed because there is no composition #2");
ok(TIP2.initForTests(window),
description + "TIP2.initForTests() should succeed because the composition was already committed #2");
ok(TIP1.beginInputTransaction(window, simpleCallback),
description + "TIP1.beginInputTransaction() should succeed because there is no composition #2");
ok(TIP1.beginInputTransactionForTests(window),
description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition #2");
ok(TIP2.beginInputTransactionForTests(window),
description + "TIP2.beginInputTransactionForTests() should succeed because the composition was already committed #2");
// Let's check if startComposition() throws an exception after ownership is strolen.
input.value = "";
@ -181,10 +181,10 @@ function runInitMethodTests()
}
// Let's check if flushPendingComposition() throws an exception after ownership is stolen.
ok(TIP1.initForTests(window),
description + "TIP1.initForTests() should succeed because there is no composition");
ok(TIP2.initForTests(window),
description + "TIP2.initForTests() should succeed because there is no composition");
ok(TIP1.beginInputTransactionForTests(window),
description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition");
ok(TIP2.beginInputTransactionForTests(window),
description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
input.value = "";
try {
TIP1.setPendingCompositionString(composingStr);
@ -202,10 +202,10 @@ function runInitMethodTests()
}
// Let's check if commitComposition("bar") throws an exception after ownership is stolen.
ok(TIP1.initForTests(window),
description + "TIP1.initForTests() should succeed because there is no composition");
ok(TIP2.initForTests(window),
description + "TIP2.initForTests() should succeed because there is no composition");
ok(TIP1.beginInputTransactionForTests(window),
description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition");
ok(TIP2.beginInputTransactionForTests(window),
description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
input.value = "";
try {
TIP1.commitComposition("bar");
@ -219,34 +219,34 @@ function runInitMethodTests()
description + "The input element should not have commit string");
}
// aCallback of nsITextInputProcessor.init() must not be omitted.
// aCallback of nsITextInputProcessor.beginInputTransaction() must not be omitted.
try {
TIP1.init(window);
TIP1.beginInputTransaction(window);
ok(false,
description + "TIP1.init(window) should be failed since aCallback is omitted");
description + "TIP1.beginInputTransaction(window) should be failed since aCallback is omitted");
} catch (e) {
ok(e.message.contains("Not enough arguments"),
description + "TIP1.init(window) should cause throwing an exception including \"Not enough arguments\" since aCallback is omitted");
description + "TIP1.beginInputTransaction(window) should cause throwing an exception including \"Not enough arguments\" since aCallback is omitted");
}
// aCallback of nsITextInputProcessor.init() must not be undefined.
// aCallback of nsITextInputProcessor.beginInputTransaction() must not be undefined.
try {
TIP1.init(window, undefined);
TIP1.beginInputTransaction(window, undefined);
ok(false,
description + "TIP1.init(window, undefined) should be failed since aCallback is undefined");
description + "TIP1.beginInputTransaction(window, undefined) should be failed since aCallback is undefined");
} catch (e) {
ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
description + "TIP1.init(window, undefined) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is undefined");
description + "TIP1.beginInputTransaction(window, undefined) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is undefined");
}
// aCallback of nsITextInputProcessor.init() must not be null.
// aCallback of nsITextInputProcessor.beginInputTransaction() must not be null.
try {
TIP1.init(window, null);
TIP1.beginInputTransaction(window, null);
ok(false,
description + "TIP1.init(window, null) should be failed since aCallback is null");
description + "TIP1.beginInputTransaction(window, null) should be failed since aCallback is null");
} catch (e) {
ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
description + "TIP1.init(window, null) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is null");
description + "TIP1.beginInputTransaction(window, null) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is null");
}
}
@ -255,8 +255,8 @@ function runReleaseTests()
var description = "runReleaseTests(): ";
var TIP = createTIP();
ok(TIP.initForTests(window),
description + "TIP.initForTests() should succeed");
ok(TIP.beginInputTransactionForTests(window),
description + "TIP.beginInputTransactionForTests() should succeed");
input.value = "";
input.focus();
@ -277,8 +277,8 @@ function runReleaseTests()
description + "the input should be empty because the composition should be canceled");
TIP = createTIP();
ok(TIP.initForTests(window),
description + "TIP.initForTests() should succeed #2");
ok(TIP.beginInputTransactionForTests(window),
description + "TIP.beginInputTransactionForTests() should succeed #2");
}
function runCompositionTests()
@ -286,8 +286,8 @@ function runCompositionTests()
var description = "runCompositionTests(): ";
var TIP = createTIP();
ok(TIP.initForTests(window),
description + "TIP.initForTests() should succeed");
ok(TIP.beginInputTransactionForTests(window),
description + "TIP.beginInputTransactionForTests() should succeed");
var events;
@ -530,8 +530,8 @@ function runErrorTests()
var description = "runErrorTests(): ";
var TIP = createTIP();
ok(TIP.initForTests(window),
description + "TIP.initForTests() should succeed");
ok(TIP.beginInputTransactionForTests(window),
description + "TIP.beginInputTransactionForTests() should succeed");
input.value = "";
input.focus();
@ -674,8 +674,8 @@ function runCommitCompositionTests()
var description = "runCommitCompositionTests(): ";
var TIP = createTIP();
ok(TIP.initForTests(window),
description + "TIP.initForTests() should succeed");
ok(TIP.beginInputTransactionForTests(window),
description + "TIP.beginInputTransactionForTests() should succeed");
input.focus();
@ -815,8 +815,8 @@ function runUnloadTests1(aNextTest)
var description = "runUnloadTests1(): ";
var TIP1 = createTIP();
ok(TIP1.initForTests(childWindow),
description + "TIP1.initForTests() should succeed");
ok(TIP1.beginInputTransactionForTests(childWindow),
description + "TIP1.beginInputTransactionForTests() should succeed");
var oldSrc = iframe.src;
var parentWindow = window;
@ -838,8 +838,8 @@ function runUnloadTests1(aNextTest)
// The composition should be committed internally. So, another TIP should
// be able to steal the rights to using TextEventDispatcher.
var TIP2 = createTIP();
ok(TIP2.initForTests(parentWindow),
description + "TIP2.initForTests() should succeed");
ok(TIP2.beginInputTransactionForTests(parentWindow),
description + "TIP2.beginInputTransactionForTests() should succeed");
input.focus();
input.value = "";
@ -877,8 +877,8 @@ function runUnloadTests2(aNextTest)
var description = "runUnloadTests2(): ";
var TIP = createTIP();
ok(TIP.initForTests(childWindow),
description + "TIP.initForTests() should succeed");
ok(TIP.beginInputTransactionForTests(childWindow),
description + "TIP.beginInputTransactionForTests() should succeed");
var oldSrc = iframe.src;
var parentWindow = window;
@ -967,9 +967,9 @@ function runCallbackTests(aForTests)
}
if (aForTests) {
TIP.initForTests(window, callback);
TIP.beginInputTransactionForTests(window, callback);
} else {
TIP.init(window, callback);
TIP.beginInputTransaction(window, callback);
}
notifications = [];
@ -1003,13 +1003,13 @@ function runCallbackTests(aForTests)
notifications = [];
var TIP2 = createTIP();
if (aForTests) {
TIP2.initForTests(window, callback);
TIP2.beginInputTransactionForTests(window, callback);
} else {
TIP2.init(window, callback);
TIP2.beginInputTransaction(window, callback);
}
is(notifications.length, 1,
description + "Initializing another TIP should cause a notification");
is(notifications[0].type, "notify-detached",
is(notifications[0].type, "notify-end-input-transaction",
description + "Initializing another TIP should cause \"notify-detached\"");
dumpUnexpectedNotifications(1);
}
@ -1018,7 +1018,7 @@ function runTests()
{
textareaInFrame = iframe.contentDocument.getElementById("textarea");
runInitMethodTests();
runBeginInputTransactionMethodTests();
runReleaseTests();
runCompositionTests();
runErrorTests();

View File

@ -638,6 +638,8 @@ BrowserElementChild.prototype = {
// We clear selectionStateChangedTarget if selection carets are invisible.
if (e.visible && !isCollapsed) {
this._selectionStateChangedTarget = e.target;
} else if (canPaste && isCollapsed) {
this._selectionStateChangedTarget = e.target;
} else {
this._selectionStateChangedTarget = null;
}
@ -1167,6 +1169,7 @@ BrowserElementChild.prototype = {
_recvDoCommand: function(data) {
if (this._isCommandEnabled(data.json.command)) {
this._selectionStateChangedTarget = null;
docShell.doCommand(COMMAND_MAP[data.json.command]);
}
},

View File

@ -251,9 +251,8 @@ static uint32_t CountNewlinesInXPLength(nsIContent* aContent,
return 0;
}
// For automated tests, we should abort on debug build.
NS_ABORT_IF_FALSE(
(aXPLength == UINT32_MAX || aXPLength <= text->GetLength()),
"aXPLength is out-of-bounds");
MOZ_ASSERT(aXPLength == UINT32_MAX || aXPLength <= text->GetLength(),
"aXPLength is out-of-bounds");
const uint32_t length = std::min(aXPLength, text->GetLength());
uint32_t newlines = 0;
for (uint32_t i = 0; i < length; ++i) {
@ -283,7 +282,7 @@ static uint32_t CountNewlinesInNativeLength(nsIContent* aContent,
i < xpLength && nativeOffset < aNativeLength;
++i, ++nativeOffset) {
// For automated tests, we should abort on debug build.
NS_ABORT_IF_FALSE(i < text->GetLength(), "i is out-of-bounds");
MOZ_ASSERT(i < text->GetLength(), "i is out-of-bounds");
if (text->CharAt(i) == '\n') {
++newlines;
++nativeOffset;
@ -943,8 +942,13 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
nsPoint ptOffset;
firstFrame->GetPointFromOffset(nodeOffset, &ptOffset);
// minus 1 to avoid creating an empty rect
rect.x += ptOffset.x - 1;
rect.width -= ptOffset.x - 1;
if (firstFrame->GetWritingMode().IsVertical()) {
rect.y += ptOffset.y - 1;
rect.height -= ptOffset.y - 1;
} else {
rect.x += ptOffset.x - 1;
rect.width -= ptOffset.x - 1;
}
// get the ending frame
nodeOffset = range->EndOffset();
@ -985,7 +989,11 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
// get the ending frame rect
lastFrame->GetPointFromOffset(nodeOffset, &ptOffset);
// minus 1 to avoid creating an empty rect
frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1;
if (lastFrame->GetWritingMode().IsVertical()) {
frameRect.height -= lastFrame->GetRect().height - ptOffset.y - 1;
} else {
frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1;
}
if (firstFrame == lastFrame) {
rect.IntersectRect(rect, frameRect);
@ -994,6 +1002,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
}
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
aEvent->mReply.mWritingMode = lastFrame->GetWritingMode();
aEvent->mSucceeded = true;
return NS_OK;
}

View File

@ -401,8 +401,8 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
(aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
aValue && !aValue->IsEmptyString()) {
// add the image to the hashtable as needed
NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom,
"Expected atom value for name/id");
MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
"Expected atom value for name/id");
mForm->AddImageElementToTable(this,
nsDependentAtomString(aValue->GetAtomValue()));
}

View File

@ -275,7 +275,7 @@ public:
: mElement(aElement),
mLoadID(aElement->GetCurrentLoadID())
{
NS_ABORT_IF_FALSE(mElement, "Must pass an element to call back");
MOZ_ASSERT(mElement, "Must pass an element to call back");
}
private:
@ -2083,7 +2083,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mAudioChannelFaded(false),
mPlayingThroughTheAudioChannel(false),
mDisableVideo(false),
mWaitingFor(MediaWaitingFor::None),
mElementInTreeState(ELEMENT_NOT_INTREE)
{
#ifdef PR_LOGGING
@ -4329,12 +4328,6 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
return promise.forget();
}
MediaWaitingFor
HTMLMediaElement::WaitingFor() const
{
return mWaitingFor;
}
EventHandlerNonNull*
HTMLMediaElement::GetOnencrypted()
{

View File

@ -25,13 +25,6 @@
#endif
#include "nsGkAtoms.h"
// Something on Linux #defines None, which is an entry in the
// MediaWaitingFor enum, so undef it here before including the binfing,
// so that the build doesn't fail...
#ifdef None
#undef None
#endif
// X.h on Linux #defines CurrentTime as 0L, so we have to #undef it here.
#ifdef CurrentTime
#undef CurrentTime
@ -552,8 +545,6 @@ public:
already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
ErrorResult& aRv);
MediaWaitingFor WaitingFor() const;
mozilla::dom::EventHandlerNonNull* GetOnencrypted();
void SetOnencrypted(mozilla::dom::EventHandlerNonNull* listener);
@ -1337,8 +1328,6 @@ protected:
nsRefPtr<VideoTrackList> mVideoTrackList;
MediaWaitingFor mWaitingFor;
enum ElementInTreeState {
// The MediaElement is not in the DOM tree now.
ELEMENT_NOT_INTREE,

View File

@ -712,8 +712,8 @@ nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
{
if (aNamespaceID == kNameSpaceID_None) {
if (IsEventAttributeName(aName) && aValue) {
NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
"Expected string value for script body");
MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
"Expected string value for script body");
nsresult rv = SetEventHandler(aName, aValue->GetStringValue());
NS_ENSURE_SUCCESS(rv, rv);
}
@ -2152,8 +2152,8 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
aValue && !aValue->IsEmptyString()) {
NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom,
"Expected atom value for name/id");
MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
"Expected atom value for name/id");
mForm->AddElementToTable(this,
nsDependentAtomString(aValue->GetAtomValue()));
}

View File

@ -1899,8 +1899,8 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
if (NS_FAILED(rv) || !mParser) {
return rv;
}
NS_ABORT_IF_FALSE(!JS_IsExceptionPending(cx),
"Open() succeeded but JS exception is pending");
MOZ_ASSERT(!JS_IsExceptionPending(cx),
"Open() succeeded but JS exception is pending");
}
static NS_NAMED_LITERAL_STRING(new_line, "\n");
@ -2773,7 +2773,7 @@ nsHTMLDocument::EditingStateChanged()
// We might already have an editor if it was set up for mail, let's see
// if this is actually the case.
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(existingEditor);
NS_ABORT_IF_FALSE(htmlEditor, "If we have an editor, it must be an HTML editor");
MOZ_ASSERT(htmlEditor, "If we have an editor, it must be an HTML editor");
uint32_t flags = 0;
existingEditor->GetFlags(&flags);
if (flags & nsIPlaintextEditor::eEditorMailMask) {

View File

@ -2107,7 +2107,7 @@ nsTextEditorState::UpdatePlaceholderVisibility(bool aNotify)
void
nsTextEditorState::HideSelectionIfBlurred()
{
NS_ABORT_IF_FALSE(mSelCon, "Should have a selection controller if we have a frame!");
MOZ_ASSERT(mSelCon, "Should have a selection controller if we have a frame!");
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
if (!nsContentUtils::IsFocusedContent(content)) {
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);

View File

@ -1243,7 +1243,8 @@ let CompositionManager = {
Cc["@mozilla.org/text-input-processor;1"].
createInstance(Ci.nsITextInputProcessor);
}
return this._textInputProcessor.init(aWindow, this._callback);
return this._textInputProcessor.beginInputTransaction(aWindow,
this._callback);
},
setComposition: function cm_setComposition(element, text, cursor, clauses) {

View File

@ -10,11 +10,12 @@ interface nsITextInputProcessorCallback;
/**
* An nsITextInputProcessor instance is associated with a top level widget which
* handles native IME. It's associated by calling init() or initForTests().
* While an instance has composition, nobody can steal the rights to make
* composition on the top level widget. In other words, if another instance is
* composing on a top level widget, either init() or initForTests() returns
* false (i.e., not throws an exception).
* handles native IME. It's associated by calling beginInputTransaction() or
* beginInputTransactionForTests(). While an instance has composition, nobody
* can steal the rights to make composition on the top level widget. In other
* words, if another instance is composing on a top level widget, either
* beginInputTransaction() or beginInputTransactionForTests() returns false
* (i.e., not throws an exception).
*
* NOTE: See nsITextInputProcessorCallback.idl for examples of |callback| in
* following examples,
@ -23,7 +24,7 @@ interface nsITextInputProcessorCallback;
*
* var TIP = Components.classes["@mozilla.org/text-input-processor;1"].
* createInstance(Components.interfaces.nsITextInputProcessor);
* if (!TIP.init(window, callback)) {
* if (!TIP.beginInputTransaction(window, callback)) {
* return; // You failed to get the rights to make composition
* }
* // Set new composition string first
@ -84,14 +85,14 @@ interface nsITextInputProcessorCallback;
*
* Example #6 JS-IME can insert text only with commitComposition():
*
* if (!TIP.init(window, callback)) {
* if (!TIP.beginInputTransaction(window, callback)) {
* return; // You failed to get the rights to make composition
* }
* TIP.commitComposition("Some words");
*
* Example #7 JS-IME can start composition explicitly:
*
* if (!TIP.init(window, callback)) {
* if (!TIP.beginInputTransaction(window, callback)) {
* return; // You failed to get the rights to make composition
* }
* // If JS-IME don't want to show composing string in the focused editor,
@ -104,12 +105,12 @@ interface nsITextInputProcessorCallback;
* TIP.commitComposition("selected-words");
*/
[scriptable, builtinclass, uuid(8c20753c-8339-4e9c-86c5-ae30f1b456c3)]
[scriptable, builtinclass, uuid(512f1efe-9e0f-48a4-b423-3936ef948f34)]
interface nsITextInputProcessor : nsISupports
{
/**
* When you create an instance, you must call init() first except when you
* created the instance for automated tests.
* When you create an instance, you must call beginInputTransaction() first
* except when you created the instance for automated tests.
*
* @param aWindow A DOM window. The instance will look for a top
* level widget from this.
@ -122,18 +123,20 @@ interface nsITextInputProcessor : nsISupports
* when this returns true. If this returns false,
* your TIP should wait next chance.
*/
boolean init(in nsIDOMWindow aWindow,
in nsITextInputProcessorCallback aCallback);
boolean beginInputTransaction(in nsIDOMWindow aWindow,
in nsITextInputProcessorCallback aCallback);
/**
* When you create an instance for automated test, you must call
* initForTest(), first. See init() for more detail of this.
* beginInputTransaction(), first. See beginInputTransaction() for more
* detail of this.
* Note that aCallback can be null. If it's null, nsITextInputProcessor
* implementation will handle them automatically.
*/
[optional_argc] boolean
initForTests(in nsIDOMWindow aWindow,
[optional] in nsITextInputProcessorCallback aCallback);
beginInputTransactionForTests(
in nsIDOMWindow aWindow,
[optional] in nsITextInputProcessorCallback aCallback);
/**
* startComposition() dispatches compositionstart event explicitly.

View File

@ -30,9 +30,11 @@ interface nsITextInputProcessorNotification : nsISupports
* nsITextInputProcessorCallback::onNotify() has to handle this
* notification.
*
* "notify-detached" (optional)
* "notify-end-input-transaction" (optional)
* This is notified when the callback is detached from
* nsITextInputProcessor.
* nsITextInputProcessor. I.e., the TextInputProcessor lost the rights
* to input text and needs to call .beginInputTransaction() before next
* input.
*
* "notify-focus" (optional)
* This is notified when an editable editor gets focus and Gecko starts

View File

@ -1964,8 +1964,8 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission)
services::GetPermissionManager();
nsPermissionManager* permissionManager =
static_cast<nsPermissionManager*>(permissionManagerIface.get());
NS_ABORT_IF_FALSE(permissionManager,
"We have no permissionManager in the Content process !");
MOZ_ASSERT(permissionManager,
"We have no permissionManager in the Content process !");
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));

View File

@ -2425,12 +2425,12 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
services::GetPermissionManager();
nsPermissionManager* permissionManager =
static_cast<nsPermissionManager*>(permissionManagerIface.get());
NS_ABORT_IF_FALSE(permissionManager,
"We have no permissionManager in the Chrome process !");
MOZ_ASSERT(permissionManager,
"We have no permissionManager in the Chrome process !");
nsCOMPtr<nsISimpleEnumerator> enumerator;
DebugOnly<nsresult> rv = permissionManager->GetEnumerator(getter_AddRefs(enumerator));
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Could not get enumerator!");
MOZ_ASSERT(NS_SUCCEEDED(rv), "Could not get enumerator!");
while(1) {
bool hasMore;
enumerator->HasMoreElements(&hasMore);
@ -4425,8 +4425,8 @@ ContentParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
#ifndef MOZ_X11
NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
#else
NS_ABORT_IF_FALSE(0 > mChildXSocketFdDup.get(),
"Already backed up X resources??");
MOZ_ASSERT(0 > mChildXSocketFdDup.get(),
"Already backed up X resources??");
mChildXSocketFdDup.forget();
if (aXSocketFd.IsValid()) {
mChildXSocketFdDup.reset(aXSocketFd.PlatformHandle());

View File

@ -3179,8 +3179,8 @@ TabChild::InitRenderingState(const ScrollingBehavior& aScrolling,
ShadowLayerForwarder* lf =
mWidget->GetLayerManager(shadowManager, mTextureFactoryIdentifier.mParentBackend)
->AsShadowForwarder();
NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
"PuppetWidget should have shadow manager");
MOZ_ASSERT(lf && lf->HasShadowManager(),
"PuppetWidget should have shadow manager");
lf->IdentifyTextureHost(mTextureFactoryIdentifier);
ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);

View File

@ -1927,6 +1927,7 @@ TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
aEvent.mReply.mOffset = aEvent.mInput.mOffset;
aEvent.mReply.mRect =
aEvent.mReply.mRect - LayoutDevicePixel::FromUntyped(GetChildProcessOffset());
aEvent.mReply.mWritingMode = mWritingMode;
aEvent.mSucceeded = true;
}
break;
@ -2182,8 +2183,8 @@ TabParent::RecvGetDPI(float* aValue)
{
TryCacheDPIAndScale();
NS_ABORT_IF_FALSE(mDPI > 0,
"Must not ask for DPI before OwnerElement is received!");
MOZ_ASSERT(mDPI > 0,
"Must not ask for DPI before OwnerElement is received!");
*aValue = mDPI;
return true;
}
@ -2193,8 +2194,8 @@ TabParent::RecvGetDefaultScale(double* aValue)
{
TryCacheDPIAndScale();
NS_ABORT_IF_FALSE(mDefaultScale.scale > 0,
"Must not ask for scale before OwnerElement is received!");
MOZ_ASSERT(mDefaultScale.scale > 0,
"Must not ask for scale before OwnerElement is received!");
*aValue = mDefaultScale.scale;
return true;
}

View File

@ -536,7 +536,7 @@ nsJSONListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
JS::ConstTwoByteChars chars(reinterpret_cast<const char16_t*>(mBufferedChars.Elements()),
mBufferedChars.Length());
bool ok = JS_ParseJSONWithReviver(mCx, chars.get(),
bool ok = JS_ParseJSONWithReviver(mCx, chars.start().get(),
uint32_t(mBufferedChars.Length()),
reviver, &value);
@ -645,7 +645,7 @@ nsJSONListener::ConsumeConverted(const char* aBuffer, uint32_t aByteLength)
rv = mDecoder->Convert(aBuffer, &srcLen, endelems, &unicharLength);
if (NS_FAILED(rv))
return rv;
NS_ABORT_IF_FALSE(preLength >= unicharLength, "GetMaxLength lied");
MOZ_ASSERT(preLength >= unicharLength, "GetMaxLength lied");
if (preLength > unicharLength)
mBufferedChars.TruncateLength(mBufferedChars.Length() - (preLength - unicharLength));
return NS_OK;

View File

@ -371,7 +371,7 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate,
// selected based on the observed behaviour of the existing AudioStream
// implementations.
uint32_t bufferLimit = FramesToBytes(aRate);
NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
MOZ_ASSERT(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
mBuffer.SetCapacity(bufferLimit);
if (aLatencyRequest == LowLatency) {
@ -632,8 +632,8 @@ AudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames, TimeStamp *aTim
while (bytesToCopy > 0) {
uint32_t available = std::min(bytesToCopy, mBuffer.Available());
NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0,
"Must copy complete frames.");
MOZ_ASSERT(available % mBytesPerFrame == 0,
"Must copy complete frames.");
mBuffer.AppendElements(src, available);
src += available;
@ -678,14 +678,14 @@ uint32_t
AudioStream::Available()
{
MonitorAutoLock mon(mMonitor);
NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
MOZ_ASSERT(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
return BytesToFrames(mBuffer.Available());
}
void
AudioStream::SetVolume(double aVolume)
{
NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
MOZ_ASSERT(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
if (cubeb_stream_set_volume(mCubebStream.get(), aVolume * CubebUtils::GetVolumeScale()) != CUBEB_OK) {
NS_WARNING("Could not change volume on cubeb stream.");
@ -1035,7 +1035,7 @@ AudioStream::Reset()
// selected based on the observed behaviour of the existing AudioStream
// implementations.
uint32_t bufferLimit = FramesToBytes(mInRate);
NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
MOZ_ASSERT(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
mBuffer.Reset();
mBuffer.SetCapacity(bufferLimit);
@ -1054,7 +1054,7 @@ AudioStream::DataCallback(void* aBuffer, long aFrames)
MonitorAutoLock mon(mMonitor);
MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown");
uint32_t available = std::min(static_cast<uint32_t>(FramesToBytes(aFrames)), mBuffer.Length());
NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames");
MOZ_ASSERT(available % mBytesPerFrame == 0, "Must copy complete frames");
AudioDataValue* output = reinterpret_cast<AudioDataValue*>(aBuffer);
uint32_t underrunFrames = 0;
uint32_t servicedFrames = 0;
@ -1113,7 +1113,7 @@ AudioStream::DataCallback(void* aBuffer, long aFrames)
servicedFrames = GetTimeStretched(output, aFrames, insertTime);
}
NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
MOZ_ASSERT(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
// Notify any blocked Write() call that more space is available in mBuffer.
mon.NotifyAll();

View File

@ -88,7 +88,7 @@ public:
// Set the capacity of the buffer in bytes. Must be called before any
// call to append or pop elements.
void SetCapacity(uint32_t aCapacity) {
NS_ABORT_IF_FALSE(!mBuffer, "Buffer allocated.");
MOZ_ASSERT(!mBuffer, "Buffer allocated.");
mCapacity = aCapacity;
mBuffer = new uint8_t[mCapacity];
}
@ -108,8 +108,8 @@ public:
// Append aLength bytes from aSrc to the buffer. Caller must check that
// sufficient space is available.
void AppendElements(const uint8_t* aSrc, uint32_t aLength) {
NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
NS_ABORT_IF_FALSE(aLength <= Available(), "Buffer full.");
MOZ_ASSERT(mBuffer && mCapacity, "Buffer not initialized.");
MOZ_ASSERT(aLength <= Available(), "Buffer full.");
uint32_t end = (mStart + mCount) % mCapacity;
@ -124,8 +124,8 @@ public:
// must not specify an aSize larger than Length().
void PopElements(uint32_t aSize, void** aData1, uint32_t* aSize1,
void** aData2, uint32_t* aSize2) {
NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
NS_ABORT_IF_FALSE(aSize <= Length(), "Request too large.");
MOZ_ASSERT(mBuffer && mCapacity, "Buffer not initialized.");
MOZ_ASSERT(aSize <= Length(), "Request too large.");
*aData1 = &mBuffer[mStart];
*aSize1 = std::min(mCapacity - mStart, aSize);
@ -139,7 +139,7 @@ public:
// Throw away all but aSize bytes from the buffer. Returns new size, which
// may be less than aSize
uint32_t ContractTo(uint32_t aSize) {
NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
MOZ_ASSERT(mBuffer && mCapacity, "Buffer not initialized.");
if (aSize >= mCount) {
return mCount;
}

View File

@ -212,8 +212,9 @@ nsresult FileBlockCache::Run()
// mDataMonitor to take mFileMonitor.
int32_t blockIndex = mChangeIndexList.PopFront();
nsRefPtr<BlockChange> change = mBlockChanges[blockIndex];
NS_ABORT_IF_FALSE(change,
"Change index list should only contain entries for blocks with changes");
MOZ_ASSERT(change,
"Change index list should only contain entries for blocks "
"with changes");
{
MonitorAutoUnlock unlock(mDataMonitor);
MonitorAutoLock lock(mFileMonitor);

View File

@ -2264,7 +2264,7 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
int64_t bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - mStreamOffset);
// Clamp bytes until 64-bit file size issues are fixed.
bytes = std::min(bytes, int64_t(INT32_MAX));
NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= aCount, "Bytes out of range.");
MOZ_ASSERT(bytes >= 0 && bytes <= aCount, "Bytes out of range.");
memcpy(aBuffer,
reinterpret_cast<char*>(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
if (mCurrentMode == MODE_METADATA) {
@ -2289,7 +2289,7 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
int32_t bytes;
NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range.");
MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
if (NS_FAILED(rv)) {
if (count == 0)
@ -2361,7 +2361,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
// Clamp bytes until 64-bit file size issues are fixed.
int64_t toCopy = std::min<int64_t>(size, mChannelOffset - streamOffset);
bytes = std::min(toCopy, int64_t(INT32_MAX));
NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= toCopy, "Bytes out of range.");
MOZ_ASSERT(bytes >= 0 && bytes <= toCopy, "Bytes out of range.");
memcpy(aBuffer + count,
reinterpret_cast<char*>(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
} else {
@ -2370,7 +2370,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
return NS_ERROR_FAILURE;
}
int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range.");
MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
if (NS_FAILED(rv)) {
return rv;

View File

@ -350,6 +350,71 @@ MediaDecoder::DecodedStreamGraphListener::NotifyEvent(MediaStreamGraph* aGraph,
}
}
class MediaDecoder::OutputStreamListener : public MediaStreamListener {
public:
OutputStreamListener(MediaDecoder* aDecoder, MediaStream* aStream)
: mDecoder(aDecoder), mStream(aStream) {}
virtual void NotifyEvent(
MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE {
if (event == EVENT_FINISHED) {
nsRefPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &OutputStreamListener::DoNotifyFinished);
aGraph->DispatchToMainThreadAfterStreamStateUpdate(r.forget());
}
}
void Forget() {
MOZ_ASSERT(NS_IsMainThread());
mDecoder = nullptr;
}
private:
void DoNotifyFinished() {
MOZ_ASSERT(NS_IsMainThread());
if (!mDecoder) {
return;
}
// Remove the finished stream so it won't block the decoded stream.
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
auto& streams = mDecoder->OutputStreams();
// Don't read |mDecoder| in the loop since removing the element will lead
// to ~OutputStreamData() which will call Forget() to reset |mDecoder|.
for (int32_t i = streams.Length() - 1; i >= 0; --i) {
auto& os = streams[i];
MediaStream* p = os.mStream.get();
if (p == mStream.get()) {
if (os.mPort) {
os.mPort->Destroy();
os.mPort = nullptr;
}
streams.RemoveElementAt(i);
break;
}
}
}
// Main thread only
MediaDecoder* mDecoder;
nsRefPtr<MediaStream> mStream;
};
void
MediaDecoder::OutputStreamData::Init(MediaDecoder* aDecoder,
ProcessedMediaStream* aStream)
{
mStream = aStream;
mListener = new OutputStreamListener(aDecoder, aStream);
aStream->AddListener(mListener);
}
MediaDecoder::OutputStreamData::~OutputStreamData()
{
mListener->Forget();
}
void MediaDecoder::DestroyDecodedStream()
{
MOZ_ASSERT(NS_IsMainThread());
@ -366,22 +431,20 @@ void MediaDecoder::DestroyDecodedStream()
// need to be explicitly blocked again.
for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
OutputStreamData& os = mOutputStreams[i];
// Explicitly remove all existing ports.
// This is not strictly necessary but it's good form.
MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
os.mPort->Destroy();
os.mPort = nullptr;
// During cycle collection, nsDOMMediaStream can be destroyed and send
// its Destroy message before this decoder is destroyed. So we have to
// be careful not to send any messages after the Destroy().
if (os.mStream->IsDestroyed()) {
// Probably the DOM MediaStream was GCed. Clean up.
MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
os.mPort->Destroy();
mOutputStreams.RemoveElementAt(i);
continue;
} else {
os.mStream->ChangeExplicitBlockerCount(1);
}
os.mStream->ChangeExplicitBlockerCount(1);
// Explicitly remove all existing ports. This is not strictly necessary but it's
// good form.
MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
os.mPort->Destroy();
os.mPort = nullptr;
}
mDecodedStream = nullptr;
@ -429,12 +492,8 @@ void MediaDecoder::RecreateDecodedStream(int64_t aStartTimeUSecs)
// between main-thread stable states take effect atomically.
for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
OutputStreamData& os = mOutputStreams[i];
if (os.mStream->IsDestroyed()) {
// Probably the DOM MediaStream was GCed. Clean up.
// No need to destroy the port; all ports have been destroyed here.
mOutputStreams.RemoveElementAt(i);
continue;
}
MOZ_ASSERT(!os.mStream->IsDestroyed(),
"Should've been removed in DestroyDecodedStream()");
ConnectDecodedStreamToOutputStream(&os);
}
UpdateStreamBlockingForStateMachinePlaying();
@ -462,7 +521,7 @@ void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream,
RecreateDecodedStream(t);
}
OutputStreamData* os = mOutputStreams.AppendElement();
os->Init(aStream, aFinishWhenEnded);
os->Init(this, aStream);
ConnectDecodedStreamToOutputStream(os);
if (aFinishWhenEnded) {
// Ensure that aStream finishes the moment mDecodedStream does.
@ -718,7 +777,7 @@ nsresult MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType)
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
NS_ABORT_IF_FALSE(aTime >= 0.0, "Cannot seek to a negative value.");
MOZ_ASSERT(aTime >= 0.0, "Cannot seek to a negative value.");
int64_t timeUsecs = 0;
nsresult rv = SecondsToUsecs(aTime, timeUsecs);
@ -945,32 +1004,6 @@ void MediaDecoder::PlaybackEnded()
return;
}
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
OutputStreamData& os = mOutputStreams[i];
if (os.mStream->IsDestroyed()) {
// Probably the DOM MediaStream was GCed. Clean up.
MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
os.mPort->Destroy();
mOutputStreams.RemoveElementAt(i);
continue;
}
if (os.mFinishWhenEnded) {
// Shouldn't really be needed since mDecodedStream should already have
// finished, but doesn't hurt.
os.mStream->Finish();
MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
os.mPort->Destroy();
// Not really needed but it keeps the invariant that a stream not
// connected to mDecodedStream is explicity blocked.
os.mStream->ChangeExplicitBlockerCount(1);
mOutputStreams.RemoveElementAt(i);
}
}
}
PlaybackPositionChanged();
ChangeState(PLAY_STATE_ENDED);
InvalidateWithFlags(VideoFrameContainer::INVALIDATE_FORCE);
@ -1551,7 +1584,7 @@ bool MediaDecoder::OnDecodeThread() const {
}
ReentrantMonitor& MediaDecoder::GetReentrantMonitor() {
return mReentrantMonitor.GetReentrantMonitor();
return mReentrantMonitor;
}
ImageContainer* MediaDecoder::GetImageContainer()

View File

@ -346,14 +346,6 @@ public:
// the seek target.
virtual nsresult Seek(double aTime, SeekTarget::Type aSeekType);
// Enables decoders to supply an enclosing byte range for a seek offset.
// E.g. used by ChannelMediaResource to download a whole cluster for
// DASH-WebM.
virtual nsresult GetByteRangeForSeek(int64_t const aOffset,
MediaByteRange &aByteRange) {
return NS_ERROR_NOT_AVAILABLE;
}
// Initialize state machine and schedule it.
nsresult InitializeStateMachine(MediaDecoder* aCloneDonor);
@ -487,17 +479,17 @@ public:
bool mStreamFinishedOnMainThread;
};
class OutputStreamListener;
struct OutputStreamData {
void Init(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
{
mStream = aStream;
mFinishWhenEnded = aFinishWhenEnded;
}
void Init(MediaDecoder* aDecoder, ProcessedMediaStream* aStream);
~OutputStreamData();
nsRefPtr<ProcessedMediaStream> mStream;
// mPort connects mDecodedStream->mStream to our mStream.
nsRefPtr<MediaInputPort> mPort;
bool mFinishWhenEnded;
nsRefPtr<OutputStreamListener> mListener;
};
/**
* Connects mDecodedStream->mStream to aStream->mStream.
*/
@ -1082,40 +1074,11 @@ protected:
// Media data resource.
nsRefPtr<MediaResource> mResource;
private:
// |ReentrantMonitor| for detecting when the video play state changes. A call
// to |Wait| on this monitor will block the thread until the next state
// change.
// Using a wrapper class to restrict direct access to the |ReentrantMonitor|
// object. Subclasses may override |MediaDecoder|::|GetReentrantMonitor|
// e.g. |DASHRepDecoder|::|GetReentrantMonitor| returns the monitor in the
// main |DASHDecoder| object. In this case, directly accessing the
// member variable mReentrantMonitor in |DASHRepDecoder| is wrong.
// The wrapper |RestrictedAccessMonitor| restricts use to the getter
// function rather than the object itself.
private:
class RestrictedAccessMonitor
{
public:
explicit RestrictedAccessMonitor(const char* aName) :
mReentrantMonitor(aName)
{
MOZ_COUNT_CTOR(RestrictedAccessMonitor);
}
~RestrictedAccessMonitor()
{
MOZ_COUNT_DTOR(RestrictedAccessMonitor);
}
// Returns a ref to the reentrant monitor
ReentrantMonitor& GetReentrantMonitor() {
return mReentrantMonitor;
}
private:
ReentrantMonitor mReentrantMonitor;
};
// The |RestrictedAccessMonitor| member object.
RestrictedAccessMonitor mReentrantMonitor;
// change. Explicitly private for force access via GetReentrantMonitor.
ReentrantMonitor mReentrantMonitor;
#ifdef MOZ_EME
nsRefPtr<CDMProxy> mProxy;

View File

@ -228,8 +228,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
mIsAudioPrerolling(false),
mIsVideoPrerolling(false),
mAudioRequestStatus(RequestStatus::Idle),
mVideoRequestStatus(RequestStatus::Idle),
mAudioCaptured(false),
mPositionChangeQueued(false),
mAudioCompleted(false),
@ -707,7 +705,7 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
nsRefPtr<AudioData> audio(aAudioSample);
MOZ_ASSERT(audio);
mAudioRequestStatus = RequestStatus::Idle;
mAudioDataRequest.Complete();
mDecodedAudioEndTime = audio->GetEndTime();
SAMPLE_LOG("OnAudioDecoded [%lld,%lld] disc=%d",
@ -824,13 +822,17 @@ void
MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason)
{
MOZ_ASSERT(OnDecodeThread());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
SAMPLE_LOG("OnNotDecoded (aType=%u, aReason=%u)", aType, aReason);
bool isAudio = aType == MediaData::AUDIO_DATA;
MOZ_ASSERT_IF(!isAudio, aType == MediaData::VIDEO_DATA);
// This callback means that the pending request is dead.
RequestStatusRef(aType) = RequestStatus::Idle;
if (isAudio) {
mAudioDataRequest.Complete();
} else {
mVideoDataRequest.Complete();
}
// If this is a decode error, delegate to the generic error path.
if (aReason == MediaDecoderReader::DECODE_ERROR) {
@ -843,10 +845,10 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
RequestStatusRef(aType) = RequestStatus::Waiting;
mReader->WaitForData(aType)->Then(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnWaitForDataResolved,
&MediaDecoderStateMachine::OnWaitForDataRejected);
WaitRequestRef(aType).Begin(mReader->WaitForData(aType)
->RefableThen(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnWaitForDataResolved,
&MediaDecoderStateMachine::OnWaitForDataRejected));
return;
}
@ -940,7 +942,7 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
MOZ_ASSERT(OnDecodeThread());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
nsRefPtr<VideoData> video(aVideoSample);
mVideoRequestStatus = RequestStatus::Idle;
mVideoDataRequest.Complete();
mDecodedVideoEndTime = video ? video->GetEndTime() : mDecodedVideoEndTime;
SAMPLE_LOG("OnVideoDecoded [%lld,%lld] disc=%d",
@ -1863,9 +1865,9 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
!needToDecodeVideo &&
!IsPlaying();
SAMPLE_LOG("DispatchDecodeTasksIfNeeded needAudio=%d audioStatus=%d needVideo=%d videoStatus=%d needIdle=%d",
needToDecodeAudio, mAudioRequestStatus,
needToDecodeVideo, mVideoRequestStatus,
SAMPLE_LOG("DispatchDecodeTasksIfNeeded needAudio=%d audioStatus=%s needVideo=%d videoStatus=%s needIdle=%d",
needToDecodeAudio, AudioRequestStatus(),
needToDecodeVideo, VideoRequestStatus(),
needIdle);
if (needToDecodeAudio) {
@ -1924,8 +1926,8 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
"Should be on state machine or decode thread.");
SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%d",
IsAudioDecoding(), mAudioRequestStatus);
SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%s",
IsAudioDecoding(), AudioRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
@ -1934,18 +1936,19 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
return NS_OK;
}
if (!IsAudioDecoding() || mAudioRequestStatus != RequestStatus::Idle || mWaitingForDecoderSeek) {
if (!IsAudioDecoding() || mAudioDataRequest.Exists() ||
mAudioWaitRequest.Exists() || mWaitingForDecoderSeek) {
return NS_OK;
}
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
mAudioRequestStatus = RequestStatus::Pending;
ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, &MediaDecoderReader::RequestAudioData)
->Then(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded);
mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
__func__, &MediaDecoderReader::RequestAudioData)
->RefableThen(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded));
return NS_OK;
}
@ -1969,8 +1972,8 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
{
AssertCurrentThreadInMonitor();
SAMPLE_LOG("EnsureVideoDecodeTaskQueued isDecoding=%d status=%d",
IsVideoDecoding(), mVideoRequestStatus);
SAMPLE_LOG("EnsureVideoDecodeTaskQueued isDecoding=%d status=%s",
IsVideoDecoding(), VideoRequestStatus());
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
"Should be on state machine or decode thread.");
@ -1982,7 +1985,8 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
return NS_OK;
}
if (!IsVideoDecoding() || mVideoRequestStatus != RequestStatus::Idle || mWaitingForDecoderSeek) {
if (!IsVideoDecoding() || mVideoDataRequest.Exists() ||
mVideoWaitRequest.Exists() || mWaitingForDecoderSeek) {
return NS_OK;
}
@ -1998,13 +2002,12 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
currentTime);
mVideoRequestStatus = RequestStatus::Pending;
ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::RequestVideoData, skipToNextKeyFrame, currentTime)
->Then(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded);
mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::RequestVideoData,
skipToNextKeyFrame, currentTime)
->RefableThen(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded));
return NS_OK;
}
@ -2287,21 +2290,22 @@ MediaDecoderStateMachine::DecodeFirstFrame()
nsresult res = FinishDecodeFirstFrame();
NS_ENSURE_SUCCESS(res, res);
} else {
// NB: We're already on the decode thread, but we proxy these anyway so that
// we don't need to worry about dropping locks.
if (HasAudio()) {
mAudioRequestStatus = RequestStatus::Pending;
ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
mReader->RequestAudioData()->Then(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded);
mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
__func__, &MediaDecoderReader::RequestAudioData)
->RefableThen(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded));
}
if (HasVideo()) {
mVideoDecodeStartTime = TimeStamp::Now();
mVideoRequestStatus = RequestStatus::Pending;
ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
mReader->RequestVideoData(false, 0)
->Then(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded);
mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
__func__, &MediaDecoderReader::RequestVideoData, false, int64_t(0))
->RefableThen(DecodeTaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded));
}
}
@ -2758,8 +2762,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
DebugOnly<nsresult> rv = DecodeTaskQueue()->Dispatch(
NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources));
MOZ_ASSERT(NS_SUCCEEDED(rv));
mAudioRequestStatus = RequestStatus::Idle;
mVideoRequestStatus = RequestStatus::Idle;
return NS_OK;
}
@ -2827,12 +2829,12 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Don't yet have a strategy for non-heuristic + non-WaitForData");
DispatchDecodeTasksIfNeeded();
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mAudioRequestStatus != RequestStatus::Idle);
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mVideoRequestStatus != RequestStatus::Idle);
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mAudioDataRequest.Exists() || mAudioWaitRequest.Exists());
MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mVideoDataRequest.Exists() || mVideoWaitRequest.Exists());
DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
"mAudioStatus: %d, outOfVideo: %d, mVideoStatus: %d",
OutOfDecodedAudio(), mAudioRequestStatus,
OutOfDecodedVideo(), mVideoRequestStatus);
"mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
OutOfDecodedAudio(), AudioRequestStatus(),
OutOfDecodedVideo(), VideoRequestStatus());
return NS_OK;
}
@ -3096,8 +3098,8 @@ void MediaDecoderStateMachine::AdvanceFrame()
(JustExitedQuickBuffering() || HasLowUndecodedData());
} else {
MOZ_ASSERT(mReader->IsWaitForDataSupported());
shouldBuffer = (OutOfDecodedAudio() && mAudioRequestStatus == RequestStatus::Waiting) ||
(OutOfDecodedVideo() && mVideoRequestStatus == RequestStatus::Waiting);
shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) ||
(OutOfDecodedVideo() && mVideoWaitRequest.Exists());
}
if (shouldBuffer) {
if (currentFrame) {

View File

@ -399,12 +399,10 @@ public:
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
void OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
MOZ_ASSERT(OnDecodeThread());
OnNotDecoded(MediaData::AUDIO_DATA, aReason);
}
void OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
MOZ_ASSERT(OnDecodeThread());
OnNotDecoded(MediaData::VIDEO_DATA, aReason);
}
@ -414,17 +412,14 @@ public:
void OnWaitForDataResolved(MediaData::Type aType)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (RequestStatusRef(aType) == RequestStatus::Waiting) {
RequestStatusRef(aType) = RequestStatus::Idle;
DispatchDecodeTasksIfNeeded();
}
WaitRequestRef(aType).Complete();
DispatchDecodeTasksIfNeeded();
}
void OnWaitForDataRejected(WaitForDataRejectValue aRejection)
{
if (RequestStatusRef(aRejection.mType) == RequestStatus::Waiting) {
RequestStatusRef(aRejection.mType) = RequestStatus::Idle;
}
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
WaitRequestRef(aRejection.mType).Complete();
}
private:
@ -1019,21 +1014,38 @@ protected:
bool mIsAudioPrerolling;
bool mIsVideoPrerolling;
enum class RequestStatus {
Idle,
Pending,
Waiting
};
// Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
// should exist at any given moment.
// True when we have dispatched a task to the decode task queue to request
// decoded audio/video, and/or we are waiting for the requested sample to be
// returned by callback from the Reader.
RequestStatus mAudioRequestStatus;
RequestStatus mVideoRequestStatus;
RequestStatus& RequestStatusRef(MediaData::Type aType)
MediaPromiseConsumerHolder<MediaDecoderReader::AudioDataPromise> mAudioDataRequest;
MediaPromiseConsumerHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
const char* AudioRequestStatus()
{
return aType == MediaData::AUDIO_DATA ? mAudioRequestStatus : mVideoRequestStatus;
if (mAudioDataRequest.Exists()) {
MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
return "pending";
} else if (mAudioWaitRequest.Exists()) {
return "waiting";
}
return "idle";
}
MediaPromiseConsumerHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
MediaPromiseConsumerHolder<MediaDecoderReader::VideoDataPromise> mVideoDataRequest;
const char* VideoRequestStatus()
{
if (mVideoDataRequest.Exists()) {
MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
return "pending";
} else if (mVideoWaitRequest.Exists()) {
return "waiting";
}
return "idle";
}
MediaPromiseConsumerHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
{
return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
}
// True if we shouldn't play our audio (but still write it to any capturing

View File

@ -37,27 +37,28 @@ struct TrackInfo {
// Stores info relevant to presenting media frames.
class VideoInfo {
private:
VideoInfo(int32_t aWidth, int32_t aHeight, bool aHasVideo)
: mDisplay(aWidth, aHeight)
, mStereoMode(StereoMode::MONO)
, mHasVideo(aHasVideo)
, mIsHardwareAccelerated(false)
void Init(int32_t aWidth, int32_t aHeight, bool aHasVideo)
{
mDisplay = nsIntSize(aWidth, aHeight);
mStereoMode = StereoMode::MONO;
mHasVideo = aHasVideo;
mIsHardwareAccelerated = false;
// TODO: TrackInfo should be initialized by its specific codec decoder.
// This following call should be removed once we have that implemented.
mTrackInfo.Init(NS_LITERAL_STRING("2"), NS_LITERAL_STRING("main"),
EmptyString(), EmptyString(), true);
}
public:
VideoInfo()
: VideoInfo(0, 0, false)
{
// TODO: TrackInfo should be initialized by its specific codec decoder.
// This following call should be removed once we have that implemented.
mTrackInfo.Init(NS_LITERAL_STRING("2"), NS_LITERAL_STRING("main"),
EmptyString(), EmptyString(), true);
Init(0, 0, false);
}
VideoInfo(int32_t aWidth, int32_t aHeight)
: VideoInfo(aWidth, aHeight, true)
{
Init(aWidth, aHeight, true);
}
// Size in pixels at which the video is rendered. This is after it has

View File

@ -240,8 +240,7 @@ protected:
}
#ifdef DEBUG
// Can't mark MOZ_OVERRIDE due to bug in clang builders we use for osx b2g desktop. :-(
virtual void AssertOnDispatchThread()
virtual void AssertOnDispatchThread() MOZ_OVERRIDE
{
detail::AssertOnThread(mResponseTarget);
}

View File

@ -979,7 +979,7 @@ MediaRecorder::Constructor(const GlobalObject& aGlobal,
nsresult
MediaRecorder::CreateAndDispatchBlobEvent(already_AddRefed<nsIDOMBlob>&& aBlob)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
if (!CheckPrincipal()) {
// Media is not same-origin, don't allow the data out.
nsRefPtr<nsIDOMBlob> blob = aBlob;
@ -1003,7 +1003,7 @@ MediaRecorder::CreateAndDispatchBlobEvent(already_AddRefed<nsIDOMBlob>&& aBlob)
void
MediaRecorder::DispatchSimpleEvent(const nsAString & aStr)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
nsresult rv = CheckInnerWindowCorrectness();
if (NS_FAILED(rv)) {
return;
@ -1034,7 +1034,7 @@ MediaRecorder::DispatchSimpleEvent(const nsAString & aStr)
void
MediaRecorder::NotifyError(nsresult aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
nsresult rv = CheckInnerWindowCorrectness();
if (NS_FAILED(rv)) {
return;
@ -1070,7 +1070,7 @@ MediaRecorder::NotifyError(nsresult aRv)
bool MediaRecorder::CheckPrincipal()
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
if (!mDOMStream && !mAudioNode) {
return false;
}

View File

@ -35,10 +35,10 @@ EMEVideoDecoder::GetNodeId()
return mProxy->GetNodeId();
}
GMPUniquePtr<GMPVideoEncodedFrame>
GMPUnique<GMPVideoEncodedFrame>::Ptr
EMEVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
{
GMPUniquePtr<GMPVideoEncodedFrame> frame = GMPVideoDecoder::CreateFrame(aSample);
GMPUnique<GMPVideoEncodedFrame>::Ptr frame = GMPVideoDecoder::CreateFrame(aSample);
if (frame && aSample->crypto.valid) {
static_cast<gmp::GMPVideoEncodedFrameImpl*>(frame.get())->InitCrypto(aSample->crypto);
}

View File

@ -44,7 +44,7 @@ public:
private:
virtual void InitTags(nsTArray<nsCString>& aTags) MOZ_OVERRIDE;
virtual nsCString GetNodeId() MOZ_OVERRIDE;
virtual GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
nsRefPtr<CDMProxy> mProxy;
};

View File

@ -17,7 +17,7 @@ static bool IsOnGMPThread();
void
VideoCallbackAdapter::Decoded(GMPVideoi420Frame* aDecodedFrame)
{
GMPUniquePtr<GMPVideoi420Frame> decodedFrame(aDecodedFrame);
GMPUnique<GMPVideoi420Frame>::Ptr decodedFrame(aDecodedFrame);
MOZ_ASSERT(IsOnGMPThread());
@ -113,7 +113,7 @@ GMPVideoDecoder::GetNodeId()
return NS_LITERAL_CSTRING("");
}
GMPUniquePtr<GMPVideoEncodedFrame>
GMPUnique<GMPVideoEncodedFrame>::Ptr
GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
{
GMPVideoFrame* ftmp = nullptr;
@ -123,7 +123,7 @@ GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
return nullptr;
}
GMPUniquePtr<GMPVideoEncodedFrame> frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
GMPUnique<GMPVideoEncodedFrame>::Ptr frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
err = frame->CreateEmptyFrame(aSample->size);
if (GMP_FAILED(err)) {
mCallback->Error();
@ -193,7 +193,7 @@ GMPVideoDecoder::Input(mp4_demuxer::MP4Sample* aSample)
mAdapter->SetLastStreamOffset(sample->byte_offset);
GMPUniquePtr<GMPVideoEncodedFrame> frame = CreateFrame(sample);
GMPUnique<GMPVideoEncodedFrame>::Ptr frame = CreateFrame(sample);
nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
nsresult rv = mGMP->Decode(Move(frame), false, info, 0);
if (NS_FAILED(rv)) {

View File

@ -88,7 +88,7 @@ public:
protected:
virtual void InitTags(nsTArray<nsCString>& aTags);
virtual nsCString GetNodeId();
virtual GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(mp4_demuxer::MP4Sample* aSample);
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample);
private:
const mp4_demuxer::VideoDecoderConfig& mConfig;

View File

@ -36,12 +36,12 @@ GMPProcessChild::Init()
// (after the binary name) here is indeed the plugin module path.
// Keep in sync with dom/plugins/PluginModuleParent.
std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
NS_ABORT_IF_FALSE(values.size() >= 3, "not enough args");
MOZ_ASSERT(values.size() >= 3, "not enough args");
pluginFilename = values[1];
voucherFilename = values[2];
#elif defined(OS_WIN)
std::vector<std::wstring> values = CommandLine::ForCurrentProcess()->GetLooseValues();
NS_ABORT_IF_FALSE(values.size() >= 2, "not enough loose args");
MOZ_ASSERT(values.size() >= 2, "not enough loose args");
pluginFilename = WideToUTF8(values[0]);
voucherFilename = WideToUTF8(values[1]);
#else

View File

@ -18,8 +18,11 @@ struct DestroyPolicy
}
};
// Ideally, this would be a template alias, but GCC 4.6 doesn't support them. See bug 1124021.
template<typename T>
using GMPUniquePtr = mozilla::UniquePtr<T, DestroyPolicy<T>>;
struct GMPUnique {
typedef mozilla::UniquePtr<T, DestroyPolicy<T>> Ptr;
};
} // namespace mozilla

View File

@ -109,7 +109,7 @@ GMPVideoDecoderParent::InitDecode(const GMPVideoCodec& aCodecSettings,
}
nsresult
GMPVideoDecoderParent::Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
GMPVideoDecoderParent::Decode(GMPUnique<GMPVideoEncodedFrame>::Ptr aInputFrame,
bool aMissingFrames,
const nsTArray<uint8_t>& aCodecSpecificInfo,
int64_t aRenderTimeMs)
@ -121,7 +121,7 @@ GMPVideoDecoderParent::Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
GMPUniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl(
GMPUnique<GMPVideoEncodedFrameImpl>::Ptr inputFrameImpl(
static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame.release()));
// Very rough kill-switch if the plugin stops processing. If it's merely

View File

@ -38,7 +38,7 @@ public:
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoDecoderCallbackProxy* aCallback,
int32_t aCoreCount) MOZ_OVERRIDE;
virtual nsresult Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
virtual nsresult Decode(GMPUnique<GMPVideoEncodedFrame>::Ptr aInputFrame,
bool aMissingFrames,
const nsTArray<uint8_t>& aCodecSpecificInfo,
int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;

View File

@ -38,7 +38,7 @@ public:
const nsTArray<uint8_t>& aCodecSpecific,
GMPVideoDecoderCallbackProxy* aCallback,
int32_t aCoreCount) = 0;
virtual nsresult Decode(mozilla::GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
virtual nsresult Decode(mozilla::GMPUnique<GMPVideoEncodedFrame>::Ptr aInputFrame,
bool aMissingFrames,
const nsTArray<uint8_t>& aCodecSpecificInfo,
int64_t aRenderTimeMs = -1) = 0;

View File

@ -126,7 +126,7 @@ GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings,
}
GMPErr
GMPVideoEncoderParent::Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
GMPVideoEncoderParent::Encode(GMPUnique<GMPVideoi420Frame>::Ptr aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes)
{
@ -137,7 +137,7 @@ GMPVideoEncoderParent::Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
GMPUniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
GMPUnique<GMPVideoi420FrameImpl>::Ptr inputFrameImpl(
static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release()));
// Very rough kill-switch if the plugin stops processing. If it's merely

View File

@ -39,7 +39,7 @@ public:
GMPVideoEncoderCallbackProxy* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
virtual GMPErr Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
virtual GMPErr Encode(GMPUnique<GMPVideoi420Frame>::Ptr aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;

View File

@ -40,7 +40,7 @@ public:
GMPVideoEncoderCallbackProxy* aCallback,
int32_t aNumberOfCores,
uint32_t aMaxPayloadSize) = 0;
virtual GMPErr Encode(mozilla::GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
virtual GMPErr Encode(mozilla::GMPUnique<GMPVideoi420Frame>::Ptr aInputFrame,
const nsTArray<uint8_t>& aCodecSpecificInfo,
const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0;
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;

View File

@ -39,5 +39,7 @@ skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac"))
[test_SetModeThrows.html]
[test_SplitAppendDelay.html]
[test_SplitAppend.html]
[test_TimestampOffset_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_WaitingOnMissingData.html]
skip-if = android_version == '10' # bug 1115148 - frequent failures on Android 2.3

View File

@ -0,0 +1,83 @@
<!DOCTYPE HTML>
<html>
<head>
<title>MSE: basic functionality</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function range(start, end) {
var rv = [];
for (var i = start; i < end; ++i) {
rv.push(i);
}
return rv;
}
var eps = 0.01;
runWithMSE(function(ms, el) {
once(ms, 'sourceopen').then(function() {
ok(true, "Receive a sourceopen event");
var audiosb = ms.addSourceBuffer("audio/mp4");
var videosb = ms.addSourceBuffer("video/mp4");
// We divide the video into 3 chunks:
// chunk 0: segments 1-4
// chunk 1: segments 5-8
// chunk 2: segments 9-13
// We then fill the timeline so that it seamlessly plays the chunks in order 0, 2, 1.
var vchunks = [ {start: 0, end: 3.2033}, { start: 3.2033, end: 6.4066}, { start: 6.4066, end: 10.01} ];
var firstvoffset = vchunks[2].end - vchunks[2].start; // Duration of chunk 2
var secondvoffset = -(vchunks[1].end - vchunks[1].start); // -(Duration of chunk 1)
fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
.then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 5), '.m4s'))
.then(function() {
is(videosb.buffered.length, 1, "No discontinuity");
isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "Chunk start");
isfuzzy(videosb.buffered.end(0), vchunks[0].end, eps, "Chunk end");
videosb.timestampOffset = firstvoffset;
return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 9), '.m4s');
})
.then(function(data) {
is(videosb.buffered.length, 2, "One discontinuity");
isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "First Chunk start");
isfuzzy(videosb.buffered.end(0), vchunks[0].end, eps, "First chunk end");
isfuzzy(videosb.buffered.start(1), vchunks[1].start + firstvoffset, eps, "Second chunk start");
isfuzzy(videosb.buffered.end(1), vchunks[1].end + firstvoffset, eps, "Second chunk end");
videosb.timestampOffset = secondvoffset;
return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(9, 14), '.m4s');
})
.then(function() {
is(videosb.buffered.length, 1, "No discontinuity (end)");
isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "Chunk start");
isfuzzy(videosb.buffered.end(0), vchunks[2].end, eps, "Chunk end");
audiosb.timestampOffset = 3;
}).then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4'))
.then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(1, 12), '.m4s'))
.then(function() {
is(audiosb.buffered.length, 1, "No audio discontinuity");
isfuzzy(audiosb.buffered.start(0), 3, eps, "Audio starts at 3");
// Trim the rest of the audio.
ms.duration = videosb.buffered.end(0);
return Promise.all([audiosb.updating ? once(audiosb, 'updateend') : Promise.resolve(),
videosb.updating ? once(videosb, 'updateend') : Promise.resolve()]);
}).then(function() {
ms.endOfStream();
once(el, 'ended').then(SimpleTest.finish.bind(SimpleTest));
el.play();
});
});
});
</script>
</pre>
</body>
</html>

View File

@ -73,7 +73,7 @@ function Log(token, msg) {
info(TimeStamp(token) + " " + msg);
}
function UpdateSessionFunc(test, token, sessionType) {
function UpdateSessionFunc(test, token, sessionType, resolve, reject) {
return function(ev) {
var msgStr = ArrayBufferToString(ev.message);
var msg = JSON.parse(msgStr);
@ -110,7 +110,11 @@ function UpdateSessionFunc(test, token, sessionType) {
ev.target.update(StringToArrayBuffer(update)).then(function() {
Log(token, "MediaKeySession update ok!");
}, bail(token + " MediaKeySession update failed"));
resolve(ev.target);
}).catch(function(reason) {
bail(token + " MediaKeySession update failed")(reason);
reject();
});
}
}
@ -223,31 +227,57 @@ function SetupEME(test, token, params)
videoType: test.type,
}
];
navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE, options)
.then(function(keySystemAccess) {
return keySystemAccess.createMediaKeys();
}, bail(token + " Failed to request key system access."))
.then(function(mediaKeys) {
Log(token, "created MediaKeys object ok");
mediaKeys.sessions = [];
return v.setMediaKeys(mediaKeys);
}, bail("failed to create MediaKeys object"))
function chain(promise, onReject) {
return promise.then(function(value) {
return Promise.resolve(value);
}).catch(function(reason) {
onReject(reason);
return Promise.reject();
})
}
.then(function() {
Log(token, "set MediaKeys on <video> element ok");
var sessionType = (params && params.sessionType) ? params.sessionType : "temporary";
var session = v.mediaKeys.createSession(sessionType);
if (params && params.onsessioncreated) {
params.onsessioncreated(session);
}
session.addEventListener("message", UpdateSessionFunc(test, token, sessionType));
return session.generateRequest(ev.initDataType, ev.initData);
}, onSetKeysFail)
var p = navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE, options);
var r = bail(token + " Failed to request key system access.");
chain(p, r)
.then(function(keySystemAccess) {
var p = keySystemAccess.createMediaKeys();
var r = bail(token + " Failed to create MediaKeys object");
return chain(p, r);
})
.then(function() {
Log(token, "generated request");
}, bail(token + " Failed to request key system access2."));
.then(function(mediaKeys) {
Log(token, "created MediaKeys object ok");
mediaKeys.sessions = [];
var p = v.setMediaKeys(mediaKeys);
return chain(p, onSetKeysFail);
})
.then(function() {
Log(token, "set MediaKeys on <video> element ok");
var sessionType = (params && params.sessionType) ? params.sessionType : "temporary";
var session = v.mediaKeys.createSession(sessionType);
if (params && params.onsessioncreated) {
params.onsessioncreated(session);
}
return new Promise(function (resolve, reject) {
session.addEventListener("message", UpdateSessionFunc(test, token, sessionType, resolve, reject));
session.generateRequest(ev.initDataType, ev.initData).catch(function(reason) {
// Reject the promise if generateRequest() failed. Otherwise it will
// be resolve in UpdateSessionFunc().
bail(token + ": session.generateRequest failed")(reason);
reject();
});
});
})
.then(function(session) {
Log(token, ": session.generateRequest succeeded");
if (params && params.onsessionupdated) {
params.onsessionupdated(session);
}
});
});
return v;
}

View File

@ -30,7 +30,7 @@ function UsableKeyIdsMatch(usableKeyIds, expectedKeyIds) {
function AwaitAllKeysUsable(session, keys, token) {
return new Promise(function(resolve, reject) {
function listener(event) {
function check() {
var map = session.keyStatuses;
var usableKeyIds = [];
for (var [key, val] of map.entries()) {
@ -38,25 +38,26 @@ function AwaitAllKeysUsable(session, keys, token) {
usableKeyIds.push(key);
}
if (UsableKeyIdsMatch(usableKeyIds, keys)) {
Log(token, "resolving AwaitAllKeysUsable promise");
session.removeEventListener("keystatuseschange", listener);
session.removeEventListener("keystatuseschange", check);
resolve();
}
}
session.addEventListener("keystatuseschange", listener);
session.addEventListener("keystatuseschange", check);
check(); // in case all keys are already usable
});
}
function AwaitAllKeysNotUsable(session, token) {
return new Promise(function(resolve, reject) {
function listener(event) {
function check() {
var map = session.keyStatuses;
if (map.size == 0) {
session.removeEventListener("keystatuseschange", listener);
session.removeEventListener("keystatuseschange", check);
resolve();
}
}
session.addEventListener("keystatuseschange", listener);
session.addEventListener("keystatuseschange", check);
check(); // in case all keys are already removed
});
}
@ -70,59 +71,76 @@ function startTest(test, token)
var v = SetupEME(test, token,
{
onsessioncreated: function(session) {
onsessionupdated: function(session) {
Log(token, "Session created");
var sessionId;
initialSession = session;
// Once the session has loaded and has all its keys usable, close
// all sessions without calling remove() on them.
AwaitAllKeysUsable(session, test.keys, token).then(
function() {
sessionId = session.sessionId;
Log(token, "Closing session with id=" + sessionId);
session.close();
}
);
AwaitAllKeysUsable(session, test.keys, token)
.then(function() {
sessionId = session.sessionId;
Log(token, "Closing session with id=" + sessionId);
return session.close();
})
// Once the session is closed, reload the MediaKeys and reload the session
session.closed.then(function() {
return navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE)
}, bail("close promise rejected"))
.then(function() {
return navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE);
})
.then(function(requestedKeySystemAccess) {
keySystemAccess = requestedKeySystemAccess;
return keySystemAccess.createMediaKeys();
}, bail(token + " Failed to request key system access."))
})
.then(function(mediaKeys) {
Log(token, "re-created MediaKeys object ok");
recreatedSession = mediaKeys.createSession("persistent");
Log(token, "Created recreatedSession, loading sessionId=" + sessionId);
return Promise.all([AwaitAllKeysUsable(recreatedSession, test.keys, token), recreatedSession.load(sessionId)]);
}, bail(token + " failed to create mediaKeys"))
return recreatedSession.load(sessionId);
})
.then(function(suceeded) {
if (suceeded) {
return Promise.resolve();
} else {
return Promise.reject("Fail to load recreatedSession, sessionId=" + sessionId);
}
})
.then(function() {
return AwaitAllKeysUsable(recreatedSession, test.keys, token);
})
.then(function() {
Log(token, "re-loaded persistent session, all keys still usable");
return Promise.all([AwaitAllKeysNotUsable(recreatedSession, token), recreatedSession.remove()]);
}, bail(token + " failed to get reload session or keys"))
})
.then(function() {
Log(token, "removed session, all keys unusable.");
// Attempt to recreate the session, the attempt should fail.
return keySystemAccess.createMediaKeys();
}, bail(token + " failed to remove session"))
})
.then(function(mediaKeys) {
Log(token, "re-re-created MediaKeys object ok");
// Trying to load the removed persistent session should fail.
return mediaKeys.createSession("persistent").load(sessionId);
}, bail(token + " failed to create mediaKeys"))
})
.then(function(suceeded) {
is(suceeded, false, token + " we expect the third session creation to fail, as the session should have been removed.");
manager.finished(token);
}, bail(token + " failure to load session."));
})
.catch(function(reason) {
// Catch rejections if any.
ok(false, token + " rejected, reason=" + reason);
manager.finished(token);
});
},
sessionType: "persistent",

View File

@ -88,7 +88,13 @@ function startTest(test, token)
manager.finished(token);
});
LoadTest(test, v, token).then(function(){v.play();}, bail(token + " failed to load"));
LoadTest(test, v, token)
.then(function() {
v.play();
}).catch(function() {
ok(false, token + " failed to load");
manager.finished(token);
});
}
function beginTest() {

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