mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-11 01:57:00 +00:00
Merge inbound to central, a=merge
This commit is contained in:
commit
d8fffe1765
@ -927,8 +927,6 @@ pref("general.useragent.updates.retry", 86400); // 1 day
|
||||
// Device ID can be composed of letter, numbers, hyphen ("-") and dot (".")
|
||||
pref("general.useragent.device_id", "");
|
||||
|
||||
// Make <audio> and <video> talk to the AudioChannelService.
|
||||
pref("media.useAudioChannelService", true);
|
||||
// Add Mozilla AudioChannel APIs.
|
||||
pref("media.useAudioChannelAPI", true);
|
||||
|
||||
|
@ -447,7 +447,7 @@ let gFxAccounts = {
|
||||
this.openPreferences();
|
||||
break;
|
||||
default:
|
||||
this.openAccountsPage(null, { entryPoint: "menupanel" });
|
||||
this.openAccountsPage(null, { entrypoint: "menupanel" });
|
||||
break;
|
||||
}
|
||||
|
||||
@ -459,12 +459,12 @@ let gFxAccounts = {
|
||||
},
|
||||
|
||||
openAccountsPage: function (action, urlParams={}) {
|
||||
// An entryPoint param is used for server-side metrics. If the current tab
|
||||
// An entrypoint param is used for server-side metrics. If the current tab
|
||||
// is UITour, assume that it initiated the call to this method and override
|
||||
// the entryPoint accordingly.
|
||||
// the entrypoint accordingly.
|
||||
if (UITour.tourBrowsersByWindow.get(window) &&
|
||||
UITour.tourBrowsersByWindow.get(window).has(gBrowser.selectedBrowser)) {
|
||||
urlParams.entryPoint = "uitour";
|
||||
urlParams.entrypoint = "uitour";
|
||||
}
|
||||
let params = new URLSearchParams();
|
||||
if (action) {
|
||||
@ -482,7 +482,7 @@ let gFxAccounts = {
|
||||
},
|
||||
|
||||
openSignInAgainPage: function (entryPoint) {
|
||||
this.openAccountsPage("reauth", { entryPoint: entryPoint });
|
||||
this.openAccountsPage("reauth", { entrypoint: entryPoint });
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -363,7 +363,6 @@ function* test_on_browser(browser) {
|
||||
add_task(function*() {
|
||||
yield new Promise((resolve) => {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["media.useAudioChannelService", true],
|
||||
["browser.tabs.showAudioPlayingIcon", true],
|
||||
]}, resolve);
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ add_task(function* test_nouser() {
|
||||
Assert.ok(!panelUIFooter.hasAttribute("fxastatus"), "no fxsstatus when signed out");
|
||||
Assert.ok(!panelUIFooter.hasAttribute("fxaprofileimage"), "no fxaprofileimage when signed out");
|
||||
|
||||
let promiseOpen = promiseTabOpen("about:accounts?entryPoint=menupanel");
|
||||
let promiseOpen = promiseTabOpen("about:accounts?entrypoint=menupanel");
|
||||
panelUIStatus.click();
|
||||
yield promiseOpen;
|
||||
});
|
||||
|
@ -211,10 +211,6 @@
|
||||
- in a "receive" state. -->
|
||||
<!ENTITY netmonitorUI.timings.receive "Receiving:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.security.warning.protocol): A tooltip
|
||||
- for warning icon that indicates a connection uses insecure protocol. -->
|
||||
<!ENTITY netmonitorUI.security.warning.sslv3 "The protocol SSL 3.0 is deprecated and insecure.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.security.warning.cipher): A tooltip
|
||||
- for warning icon that indicates a connection uses insecure cipher suite. -->
|
||||
<!ENTITY netmonitorUI.security.warning.cipher "The cipher used for encryption is deprecated and insecure.">
|
||||
|
@ -64,7 +64,7 @@ case "$target" in
|
||||
|
||||
kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
|
||||
|
||||
for version in $android_gnu_compiler_version 4.9 4.8 4.7 4.6 4.4.3; do
|
||||
for version in $android_gnu_compiler_version 4.9 4.8 4.7; do
|
||||
case "$target_cpu" in
|
||||
arm)
|
||||
target_name=arm-linux-androideabi-$version
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/dom/URLSearchParams.h"
|
||||
|
||||
@ -34,6 +35,13 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
UniquePtr<URLParams> params(new URLParams());
|
||||
nsAutoString value;
|
||||
|
||||
//
|
||||
// Important: While serializing any string-valued attributes, perform a
|
||||
// release-mode assertion to make sure that they don't contain characters that
|
||||
// will break the quota manager when it uses the serialization for file
|
||||
// naming (see addonId below).
|
||||
//
|
||||
|
||||
if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
value.AppendInt(mAppId);
|
||||
params->Set(NS_LITERAL_STRING("appId"), value);
|
||||
@ -44,6 +52,7 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
}
|
||||
|
||||
if (!mAddonId.IsEmpty()) {
|
||||
MOZ_RELEASE_ASSERT(mAddonId.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
|
||||
params->Set(NS_LITERAL_STRING("addonId"), mAddonId);
|
||||
}
|
||||
|
||||
@ -60,6 +69,13 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
aStr.AppendLiteral("^");
|
||||
aStr.Append(NS_ConvertUTF16toUTF8(value));
|
||||
}
|
||||
|
||||
// In debug builds, check the whole string for illegal characters too (just in case).
|
||||
#ifdef DEBUG
|
||||
nsAutoCString str;
|
||||
str.Assign(aStr);
|
||||
MOZ_ASSERT(str.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "prenv.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIViewSourceChannel.h"
|
||||
#include "nsIWebBrowserChrome.h"
|
||||
#include "nsPoint.h"
|
||||
#include "nsIObserverService.h"
|
||||
@ -10395,20 +10396,18 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
}
|
||||
|
||||
if (!isSrcdoc) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||
new LoadInfo(requestingNode ? requestingNode->NodePrincipal() :
|
||||
triggeringPrincipal.get(),
|
||||
triggeringPrincipal,
|
||||
requestingNode,
|
||||
securityFlags,
|
||||
aContentPolicyType,
|
||||
aBaseURI);
|
||||
rv = NS_NewChannelInternal(getter_AddRefs(channel),
|
||||
aURI,
|
||||
loadInfo,
|
||||
nullptr, // loadGroup
|
||||
static_cast<nsIInterfaceRequestor*>(this),
|
||||
loadFlags);
|
||||
requestingNode,
|
||||
requestingNode
|
||||
? requestingNode->NodePrincipal()
|
||||
: triggeringPrincipal.get(),
|
||||
triggeringPrincipal,
|
||||
securityFlags,
|
||||
aContentPolicyType,
|
||||
nullptr, // loadGroup
|
||||
static_cast<nsIInterfaceRequestor*>(this),
|
||||
loadFlags);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
|
||||
@ -10425,6 +10424,12 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
if (aBaseURI) {
|
||||
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
|
||||
if (vsc) {
|
||||
vsc->SetBaseURI(aBaseURI);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nsAutoCString scheme;
|
||||
rv = aURI->GetScheme(scheme);
|
||||
@ -10436,17 +10441,15 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
|
||||
NS_ENSURE_TRUE(vsh, NS_ERROR_FAILURE);
|
||||
|
||||
rv = vsh->NewSrcdocChannel(aURI, aSrcdoc, getter_AddRefs(channel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||
new LoadInfo(requestingNode ? requestingNode->NodePrincipal() :
|
||||
triggeringPrincipal.get(),
|
||||
triggeringPrincipal,
|
||||
requestingNode,
|
||||
securityFlags,
|
||||
aContentPolicyType,
|
||||
aBaseURI);
|
||||
channel->SetLoadInfo(loadInfo);
|
||||
rv = vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc,
|
||||
requestingNode,
|
||||
requestingNode
|
||||
? requestingNode->NodePrincipal()
|
||||
: triggeringPrincipal.get(),
|
||||
triggeringPrincipal,
|
||||
securityFlags,
|
||||
aContentPolicyType,
|
||||
getter_AddRefs(channel));
|
||||
} else {
|
||||
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
|
||||
aURI,
|
||||
@ -10459,9 +10462,11 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
triggeringPrincipal,
|
||||
securityFlags,
|
||||
aContentPolicyType,
|
||||
true,
|
||||
aBaseURI);
|
||||
true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
|
||||
MOZ_ASSERT(isc);
|
||||
isc->SetBaseURI(aBaseURI);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11735,7 +11740,7 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
loadInfo->GetBaseURI(getter_AddRefs(baseURI));
|
||||
inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
|
||||
entry->SetBaseURI(baseURI);
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ WebappsRegistry.prototype = {
|
||||
}
|
||||
|
||||
this.addMessageListeners(["Webapps:GetLocalizationResource:Return"]);
|
||||
return this.createPromise((aResolve, aReject) => {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:GetLocalizationResource", {
|
||||
manifestURL: manifestURL,
|
||||
lang: aLanguage,
|
||||
@ -325,10 +325,7 @@ WebappsRegistry.prototype = {
|
||||
dataType: aType,
|
||||
oid: this._id,
|
||||
topId: this._topId,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
requestID: aResolverId
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -609,7 +606,7 @@ WebappsApplication.prototype = {
|
||||
connect: function(aKeyword, aRules) {
|
||||
this.addMessageListeners(["Webapps:Connect:Return:OK",
|
||||
"Webapps:Connect:Return:KO"]);
|
||||
return this.createPromise(function (aResolve, aReject) {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
let from = this._window.location.origin + this._window.location.pathname;
|
||||
cpmm.sendAsyncMessage("Webapps:Connect", {
|
||||
keyword: aKeyword,
|
||||
@ -618,27 +615,21 @@ WebappsApplication.prototype = {
|
||||
pubPageURL: from,
|
||||
outerWindowID: this._id,
|
||||
topWindowID: this._topId,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
requestID: aResolverId
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
getConnections: function() {
|
||||
this.addMessageListeners("Webapps:GetConnections:Return:OK");
|
||||
return this.createPromise(function (aResolve, aReject) {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:GetConnections", {
|
||||
manifestURL: this.manifestURL,
|
||||
outerWindowID: this._id,
|
||||
topWindowID: this._topId,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
requestID: aResolverId
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
addReceipt: function(receipt) {
|
||||
@ -689,22 +680,19 @@ WebappsApplication.prototype = {
|
||||
|
||||
export: function() {
|
||||
this.addMessageListeners(["Webapps:Export:Return"]);
|
||||
return this.createPromise((aResolve, aReject) => {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:Export",
|
||||
{ manifestURL: this.manifestURL,
|
||||
oid: this._id,
|
||||
topId: this._topId,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
requestID: aResolverId
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getLocalizedValue: function(aProperty, aLang, aEntryPoint) {
|
||||
this.addMessageListeners(["Webapps:GetLocalizedValue:Return"]);
|
||||
return this.createPromise((aResolve, aReject) => {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:GetLocalizedValue",
|
||||
{ manifestURL: this.manifestURL,
|
||||
oid: this._id,
|
||||
@ -712,10 +700,7 @@ WebappsApplication.prototype = {
|
||||
property: aProperty,
|
||||
lang: aLang,
|
||||
entryPoint: aEntryPoint,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
requestID: aResolverId
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -958,19 +943,16 @@ WebappsApplicationMgmt.prototype = {
|
||||
},
|
||||
|
||||
getIcon: function(aApp, aIconID, aEntryPoint) {
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:GetIcon", {
|
||||
oid: this._id,
|
||||
topId: this._topId,
|
||||
manifestURL: aApp.manifestURL,
|
||||
iconID: aIconID,
|
||||
entryPoint: aEntryPoint,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})
|
||||
requestID: aResolverId
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
getNotInstalled: function() {
|
||||
@ -988,29 +970,25 @@ WebappsApplicationMgmt.prototype = {
|
||||
|
||||
import: function(aBlob) {
|
||||
let principal = this._window.document.nodePrincipal;
|
||||
return this.createPromise((aResolve, aReject) => {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:Import",
|
||||
{ blob: aBlob,
|
||||
oid: this._id,
|
||||
topId: this._topId,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})}, null, principal);
|
||||
requestID: aResolverId
|
||||
}, null, principal);
|
||||
});
|
||||
},
|
||||
|
||||
extractManifest: function(aBlob) {
|
||||
let principal = this._window.document.nodePrincipal;
|
||||
return this.createPromise((aResolve, aReject) => {
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
cpmm.sendAsyncMessage("Webapps:ExtractManifest",
|
||||
{ blob: aBlob,
|
||||
oid: this._id,
|
||||
topId: this._topId,
|
||||
requestID: this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
})}, null, principal);
|
||||
requestID: aResolverId
|
||||
}, null, principal);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -298,6 +298,17 @@ DOMRequestIpcHelper.prototype = {
|
||||
return new this._window.Promise(aPromiseInit);
|
||||
},
|
||||
|
||||
/**
|
||||
* createPromiseWithId() creates a new Promise, accepting a callback
|
||||
* which is immediately called with the generated resolverId.
|
||||
*/
|
||||
createPromiseWithId: function(aCallback) {
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
let resolverId = this.getPromiseResolverId({ resolve: aResolve, reject: aReject });
|
||||
aCallback(resolverId);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
forEachRequest: function(aCallback) {
|
||||
if (!this._requests) {
|
||||
return;
|
||||
|
@ -85,12 +85,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsContentSink)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
@ -30,10 +30,6 @@ var audio = new Audio();
|
||||
audio.src = "audio.ogg";
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
|
@ -31,10 +31,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
var tests = [
|
||||
function() {
|
||||
iframe = document.querySelector("iframe");
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
runTest();
|
||||
|
@ -99,7 +99,7 @@ function runTest() {
|
||||
iframe.src = "data:text/html,page";
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({ "set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
onload = runTest;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
@ -14,30 +14,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=913761
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=913761">Mozilla Bug 913761</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
var transportChannel = new MessageChannel();
|
||||
transportChannel.port1.onmessage = function (event) {
|
||||
ok(true, 'Port Returned.');
|
||||
var portToService = event.data.port;
|
||||
portToService.onmessage = function (event) {
|
||||
ok(true, "message received");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
portToService.postMessage('READY?');
|
||||
}
|
||||
|
||||
var serviceChannel = new MessageChannel();
|
||||
serviceChannel.port1.onmessage = function (event) {
|
||||
if (event.data == 'READY?') {
|
||||
this.postMessage('READY!');
|
||||
}
|
||||
}
|
||||
|
||||
transportChannel.port2.postMessage({ port: serviceChannel.port2}, [serviceChannel.port2]);
|
||||
var transportChannel = new MessageChannel();
|
||||
transportChannel.port1.onmessage = function (event) {
|
||||
ok(true, 'Port Returned.');
|
||||
var portToService = event.data.port;
|
||||
portToService.onmessage = function (event) {
|
||||
ok(true, "message received");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
portToService.postMessage('READY?');
|
||||
}
|
||||
|
||||
var serviceChannel = new MessageChannel();
|
||||
serviceChannel.port1.onmessage = function (event) {
|
||||
if (event.data == 'READY?') {
|
||||
this.postMessage('READY!');
|
||||
}
|
||||
}
|
||||
|
||||
transportChannel.port2.postMessage({ port: serviceChannel.port2}, [serviceChannel.port2]);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -408,6 +408,18 @@
|
||||
ok(promise instanceof Promise, "Returned a Promise");
|
||||
promise.then(next);
|
||||
},
|
||||
function() {
|
||||
info("== Test createPromiseWithId()");
|
||||
var _resolverId;
|
||||
var promise = dummy.createPromiseWithId(function(resolverId) {
|
||||
_resolverId = resolverId;
|
||||
});
|
||||
var resolver = dummy.getPromiseResolver(_resolverId);
|
||||
ok(promise instanceof Promise, "Returned a Promise");
|
||||
ok(typeof _resolverId === "string", "resolverId is a string");
|
||||
ok(resolver != null, "resolverId is a valid id");
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
info("== Test getResolver()");
|
||||
var id;
|
||||
|
@ -107,7 +107,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=912456
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -38,10 +38,6 @@ video.onplay = video.onpause = function() {
|
||||
};
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
|
@ -34,10 +34,6 @@ var audio = new Audio();
|
||||
audio.loop = true;
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
|
@ -34,10 +34,6 @@ var audio = new Audio();
|
||||
audio.loop = true;
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
|
@ -34,10 +34,6 @@ var audio = new Audio();
|
||||
audio.loop = true;
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
|
@ -26,10 +26,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
var ac;
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
|
@ -64,10 +64,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
var tests = [
|
||||
function() {
|
||||
iframe = document.querySelector("iframe");
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
runTest();
|
||||
|
@ -385,7 +385,7 @@ function next() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, next);
|
||||
next();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -31,10 +31,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
var tests = [
|
||||
function() {
|
||||
iframe = document.querySelector("iframe");
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
runTest();
|
||||
|
@ -31,10 +31,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
var tests = [
|
||||
function() {
|
||||
iframe = document.querySelector("iframe");
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
runTest();
|
||||
|
@ -9,8 +9,6 @@ SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
SpecialPowers.setBoolPref("media.useAudioChannelService", true);
|
||||
|
||||
function noaudio() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
|
@ -68,8 +68,4 @@ function runTest() {
|
||||
iframe.src = browserElementTestHelpers.emptyPage1;
|
||||
}
|
||||
|
||||
addEventListener('testready', () => {
|
||||
// Audio channel service is needed for events
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]},
|
||||
runTest);
|
||||
});
|
||||
addEventListener('testready', runTest);
|
||||
|
@ -47,12 +47,7 @@ function runTest() {
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
// This test relies on <audio> elements interacting with the audio channel
|
||||
// service. This is controled by the media.useAudioChannelService pref.
|
||||
addEventListener('testready', function() {
|
||||
SpecialPowers.pushPrefEnv({set: [['media.useAudioChannelService', true]]},
|
||||
runTest);
|
||||
});
|
||||
addEventListener('testready', runTest);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -1014,7 +1014,7 @@ CanvasRenderingContext2D::ParseColor(const nsAString& aString,
|
||||
*aColor = value.GetColorValue();
|
||||
} else {
|
||||
// otherwise resolve it
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
nsRefPtr<nsStyleContext> parentContext;
|
||||
if (mCanvasElement && mCanvasElement->IsInDoc()) {
|
||||
// Inherit from the canvas element.
|
||||
@ -2151,9 +2151,15 @@ GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
|
||||
ErrorResult& error)
|
||||
{
|
||||
if (aElement && aElement->IsInDoc()) {
|
||||
// inherit from the canvas element
|
||||
return nsComputedDOMStyle::GetStyleContextForElement(aElement, nullptr,
|
||||
presShell);
|
||||
// Inherit from the canvas element.
|
||||
nsRefPtr<nsStyleContext> result =
|
||||
nsComputedDOMStyle::GetStyleContextForElement(aElement, nullptr,
|
||||
presShell);
|
||||
if (!result) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
// otherwise inherit from default (10px sans-serif)
|
||||
@ -2168,7 +2174,14 @@ GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
|
||||
|
||||
nsTArray<nsCOMPtr<nsIStyleRule>> parentRules;
|
||||
parentRules.AppendElement(parentRule);
|
||||
return presShell->StyleSet()->ResolveStyleForRules(nullptr, parentRules);
|
||||
nsRefPtr<nsStyleContext> result =
|
||||
presShell->StyleSet()->ResolveStyleForRules(nullptr, parentRules);
|
||||
|
||||
if (!result) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -2222,6 +2235,12 @@ GetFontStyleContext(Element* aElement, const nsAString& aFont,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(parentContext,
|
||||
"GetFontParentStyleContext should have returned an error if it couldn't get a parent context.");
|
||||
|
||||
MOZ_ASSERT(!presShell->IsDestroying(),
|
||||
"GetFontParentStyleContext should have returned an error if the presshell is being destroyed.");
|
||||
|
||||
nsTArray<nsCOMPtr<nsIStyleRule>> rules;
|
||||
rules.AppendElement(rule);
|
||||
// add a rule to prevent text zoom from affecting the style
|
||||
@ -2299,7 +2318,7 @@ CanvasRenderingContext2D::ParseFilter(const nsAString& aString,
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (!presShell) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return false;
|
||||
@ -3034,6 +3053,13 @@ CanvasRenderingContext2D::TransformWillUpdate()
|
||||
void
|
||||
CanvasRenderingContext2D::SetFont(const nsAString& font,
|
||||
ErrorResult& error)
|
||||
{
|
||||
SetFontInternal(font, error);
|
||||
}
|
||||
|
||||
bool
|
||||
CanvasRenderingContext2D::SetFontInternal(const nsAString& font,
|
||||
ErrorResult& error)
|
||||
{
|
||||
/*
|
||||
* If font is defined with relative units (e.g. ems) and the parent
|
||||
@ -3046,20 +3072,20 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
||||
if (!mCanvasElement && !mDocShell) {
|
||||
NS_WARNING("Canvas element must be non-null or a docshell must be provided");
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (!presShell) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
nsString usedFont;
|
||||
nsRefPtr<nsStyleContext> sc =
|
||||
GetFontStyleContext(mCanvasElement, font, presShell, usedFont, error);
|
||||
if (!sc) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsStyleFont* fontStyle = sc->StyleFont();
|
||||
@ -3099,6 +3125,8 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
||||
CurrentState().fontFont.size = fontStyle->mSize;
|
||||
CurrentState().fontLanguage = fontStyle->mLanguage;
|
||||
CurrentState().fontExplicitLanguage = fontStyle->mExplicitLanguage;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -3693,7 +3721,12 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
||||
}
|
||||
|
||||
gfxFontGroup* currentFontStyle = GetCurrentFontStyle();
|
||||
NS_ASSERTION(currentFontStyle, "font group is null");
|
||||
if (!currentFontStyle) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!presShell->IsDestroying(),
|
||||
"GetCurrentFontStyle() should have returned null if the presshell is being destroyed");
|
||||
|
||||
// ensure user font set is up to date
|
||||
currentFontStyle->
|
||||
@ -3891,8 +3924,9 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
|
||||
ErrorResult err;
|
||||
NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
|
||||
static float kDefaultFontSize = 10.0;
|
||||
SetFont(kDefaultFontStyle, err);
|
||||
if (err.Failed()) {
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
bool fontUpdated = SetFontInternal(kDefaultFontStyle, err);
|
||||
if (err.Failed() || !fontUpdated) {
|
||||
gfxFontStyle style;
|
||||
style.size = kDefaultFontSize;
|
||||
CurrentState().fontGroup =
|
||||
@ -3901,9 +3935,7 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
|
||||
nullptr);
|
||||
if (CurrentState().fontGroup) {
|
||||
CurrentState().font = kDefaultFontStyle;
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
if (presShell && !presShell->IsDestroying()) {
|
||||
CurrentState().fontGroup->SetTextPerfMetrics(
|
||||
presShell->GetPresContext()->GetTextPerfMetrics());
|
||||
}
|
||||
@ -3911,7 +3943,6 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
|
||||
NS_ERROR("Default canvas font is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return CurrentState().fontGroup;
|
||||
|
@ -597,6 +597,10 @@ protected:
|
||||
nsTArray<nsStyleFilter>& aFilterChain,
|
||||
ErrorResult& error);
|
||||
|
||||
// Returns whether the font was successfully updated.
|
||||
bool SetFontInternal(const nsAString& font, mozilla::ErrorResult& error);
|
||||
|
||||
|
||||
/**
|
||||
* Creates the error target, if it doesn't exist
|
||||
*/
|
||||
@ -631,7 +635,7 @@ protected:
|
||||
*/
|
||||
RenderingMode EnsureTarget(RenderingMode aRenderMode = RenderingMode::DefaultBackendMode);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Disposes an old target and prepares to lazily create a new target.
|
||||
*/
|
||||
void ClearTarget();
|
||||
@ -867,10 +871,10 @@ protected:
|
||||
protected:
|
||||
gfxFontGroup *GetCurrentFontStyle();
|
||||
|
||||
/*
|
||||
* Implementation of the fillText, strokeText, and measure functions with
|
||||
* the operation abstracted to a flag.
|
||||
*/
|
||||
/**
|
||||
* Implementation of the fillText, strokeText, and measure functions with
|
||||
* the operation abstracted to a flag.
|
||||
*/
|
||||
nsresult DrawOrMeasureText(const nsAString& text,
|
||||
float x,
|
||||
float y,
|
||||
|
@ -95,7 +95,7 @@ WebGLContext::ClearDepth(GLclampf v)
|
||||
|
||||
MakeContextCurrent();
|
||||
mDepthClearValue = GLClampFloat(v);
|
||||
gl->fClearDepth(v);
|
||||
gl->fClearDepth(mDepthClearValue);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -159,4 +159,4 @@ pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidV
|
||||
# Check that captureStream() displays in a local video element
|
||||
pref(canvas.capturestream.enabled,true) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
|
||||
|
||||
fuzzy-if(Android,3,40) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
|
||||
fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
|
||||
|
@ -52,36 +52,30 @@ EngineeringModeAPI.prototype = {
|
||||
// This returns a Promise<DOMString>
|
||||
getValue: function getValue(aName) {
|
||||
debug("getValue " + aName);
|
||||
let promiseInit = function(resolve, reject) {
|
||||
debug("promise init called for getValue " + aName);
|
||||
let resolverId = this.getPromiseResolverId({resolve: resolve,
|
||||
reject: reject });
|
||||
debug("promise init " + resolverId);
|
||||
let promiseInit = function(aResolverId) {
|
||||
debug("promise init called for getValue " + aName + " has resolverId " + aResolverId);
|
||||
cpmm.sendAsyncMessage("EngineeringMode:GetValue", {
|
||||
requestId: resolverId,
|
||||
requestId: aResolverId,
|
||||
name: aName
|
||||
});
|
||||
}.bind(this);
|
||||
|
||||
return this.createPromise(promiseInit);
|
||||
return this.createPromiseWithId(promiseInit);
|
||||
},
|
||||
|
||||
// This returns a Promise<void>
|
||||
setValue: function setValue(aName, aValue) {
|
||||
debug("setValue " + aName + ' as ' + aValue );
|
||||
let promiseInit = function(resolve, reject) {
|
||||
debug("promise init called for setValue " + aName);
|
||||
let resolverId = this.getPromiseResolverId({resolve: resolve,
|
||||
reject: reject });
|
||||
debug("promise init " + resolverId);
|
||||
let promiseInit = function(aResolverId) {
|
||||
debug("promise init called for getValue " + aName + " has resolverId " + aResolverId);
|
||||
cpmm.sendAsyncMessage("EngineeringMode:SetValue", {
|
||||
requestId: resolverId,
|
||||
requestId: aResolverId,
|
||||
name: aName,
|
||||
value: aValue
|
||||
});
|
||||
}.bind(this);
|
||||
|
||||
return this.createPromise(promiseInit);
|
||||
return this.createPromiseWithId(promiseInit);
|
||||
},
|
||||
|
||||
set onmessage(aHandler) {
|
||||
|
@ -60,7 +60,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=848294
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -135,10 +135,6 @@ FMRadio::Init(nsPIDOMWindow *aWindow)
|
||||
RegisterSwitchObserver(SWITCH_HEADPHONES, this);
|
||||
}
|
||||
|
||||
// All of the codes below are for AudioChannel. We can directly return here
|
||||
// if preferences doesn't enable AudioChannelService.
|
||||
NS_ENSURE_TRUE_VOID(Preferences::GetBool("media.useAudioChannelService"));
|
||||
|
||||
nsCOMPtr<nsIAudioChannelAgent> audioChannelAgent =
|
||||
do_CreateInstance("@mozilla.org/audiochannelagent;1");
|
||||
NS_ENSURE_TRUE_VOID(audioChannelAgent);
|
||||
|
@ -878,19 +878,21 @@ HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewConte
|
||||
|
||||
nsIntSize sz = GetWidthHeight();
|
||||
|
||||
nsresult rv = mCurrentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
|
||||
nsCOMPtr<nsICanvasRenderingContextInternal> currentContext = mCurrentContext;
|
||||
|
||||
nsresult rv = currentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentContext = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCurrentContext->SetContextOptions(aCx, aNewContextOptions);
|
||||
rv = currentContext->SetContextOptions(aCx, aNewContextOptions);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentContext = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCurrentContext->SetDimensions(sz.width, sz.height);
|
||||
rv = currentContext->SetDimensions(sz.width, sz.height);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentContext = nullptr;
|
||||
return rv;
|
||||
|
@ -1097,11 +1097,6 @@ static bool IsAutoplayEnabled()
|
||||
return Preferences::GetBool("media.autoplay.enabled");
|
||||
}
|
||||
|
||||
static bool UseAudioChannelService()
|
||||
{
|
||||
return Preferences::GetBool("media.useAudioChannelService");
|
||||
}
|
||||
|
||||
static bool UseAudioChannelAPI()
|
||||
{
|
||||
return Preferences::GetBool("media.useAudioChannelAPI");
|
||||
@ -2411,10 +2406,6 @@ bool HTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
|
||||
|
||||
bool HTMLMediaElement::CheckAudioChannelPermissions(const nsAString& aString)
|
||||
{
|
||||
if (!UseAudioChannelService()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only normal channel doesn't need permission.
|
||||
if (aString.EqualsASCII("normal")) {
|
||||
return true;
|
||||
@ -4457,10 +4448,6 @@ ImageContainer* HTMLMediaElement::GetImageContainer()
|
||||
|
||||
nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
|
||||
{
|
||||
if (!UseAudioChannelService()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mAudioChannelVolume != aVolume) {
|
||||
mAudioChannelVolume = aVolume;
|
||||
SetVolumeInternal();
|
||||
@ -4487,10 +4474,6 @@ nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
|
||||
|
||||
void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
||||
{
|
||||
if (!UseAudioChannelService()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool playingThroughTheAudioChannel =
|
||||
(!mPaused &&
|
||||
!Muted() &&
|
||||
|
@ -394,7 +394,7 @@ MozInputMethod.prototype = {
|
||||
},
|
||||
|
||||
removeInput: function(inputId) {
|
||||
return this._sendPromise(function(resolverId) {
|
||||
return this.createPromiseWithId(function(resolverId) {
|
||||
let appId = this._window.document.nodePrincipal.appId;
|
||||
|
||||
cpmm.sendAsyncMessage('InputRegistry:Remove', {
|
||||
@ -435,14 +435,6 @@ MozInputMethod.prototype = {
|
||||
if (!this._isSystem) {
|
||||
throw new this._window.Error("Should have 'input-manage' permssion.");
|
||||
}
|
||||
},
|
||||
|
||||
_sendPromise: function(callback) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
callback(resolverId);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -786,14 +778,13 @@ MozInputContext.prototype = {
|
||||
|
||||
_sendPromise: function(callback) {
|
||||
let self = this;
|
||||
return this._ipcHelper.createPromise(function(resolve, reject) {
|
||||
let resolverId = self._ipcHelper.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._ipcHelper.createPromiseWithId(function(aResolverId) {
|
||||
if (!WindowMap.isActive(self._window)) {
|
||||
self._ipcHelper.removePromiseResolver(resolverId);
|
||||
self._ipcHelper.removePromiseResolver(aResolverId);
|
||||
reject('Input method is not active.');
|
||||
return;
|
||||
}
|
||||
callback(resolverId);
|
||||
callback(aResolverId);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -68,7 +68,5 @@ UnsupportedHashAlg=Unsupported hash algorithm in the integrity attribute: "%1$S"
|
||||
# LOCALIZATION NOTE: Do not translate "integrity"
|
||||
NoValidMetadata=The integrity attribute does not contain any valid metadata.
|
||||
|
||||
# LOCALIZATION NOTE: Do not translate "SSL 3.0".
|
||||
WeakProtocolVersionWarning=This site uses the protocol SSL 3.0 for encryption, which is deprecated and insecure.
|
||||
# LOCALIZATION NOTE: Do not translate "RC4".
|
||||
WeakCipherSuiteWarning=This site uses the cipher RC4 for encryption, which is deprecated and insecure.
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
const nsACString& aContentType) :
|
||||
mBuffer(aBuffer),
|
||||
mLength(aLength),
|
||||
mOffset(0),
|
||||
mPrincipal(aPrincipal),
|
||||
mContentType(aContentType)
|
||||
{
|
||||
|
@ -105,7 +105,8 @@ UpdateStreamBlocking(MediaStream* aStream, bool aBlocking)
|
||||
*/
|
||||
class DecodedStreamData {
|
||||
public:
|
||||
DecodedStreamData(SourceMediaStream* aStream, bool aPlaying);
|
||||
DecodedStreamData(SourceMediaStream* aStream, bool aPlaying,
|
||||
MozPromiseHolder<GenericPromise>&& aPromise);
|
||||
~DecodedStreamData();
|
||||
bool IsFinished() const;
|
||||
int64_t GetPosition() const;
|
||||
@ -139,11 +140,10 @@ public:
|
||||
// True if we need to send a compensation video frame to ensure the
|
||||
// StreamTime going forward.
|
||||
bool mEOSVideoCompensation;
|
||||
// This promise will be resolved when the SourceMediaStream is finished.
|
||||
nsRefPtr<GenericPromise> mFinishPromise;
|
||||
};
|
||||
|
||||
DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying)
|
||||
DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying,
|
||||
MozPromiseHolder<GenericPromise>&& aPromise)
|
||||
: mAudioFramesWritten(0)
|
||||
, mNextVideoTime(-1)
|
||||
, mNextAudioTime(-1)
|
||||
@ -155,10 +155,8 @@ DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying)
|
||||
, mPlaying(aPlaying)
|
||||
, mEOSVideoCompensation(false)
|
||||
{
|
||||
MozPromiseHolder<GenericPromise> promise;
|
||||
mFinishPromise = promise.Ensure(__func__);
|
||||
// DecodedStreamGraphListener will resolve this promise.
|
||||
mListener = new DecodedStreamGraphListener(mStream, Move(promise));
|
||||
mListener = new DecodedStreamGraphListener(mStream, Move(aPromise));
|
||||
mStream->AddListener(mListener);
|
||||
|
||||
// Block the stream if we are not playing.
|
||||
@ -293,10 +291,19 @@ OutputStreamData::Remove()
|
||||
mOwner->Remove(mStream);
|
||||
}
|
||||
|
||||
MediaStreamGraph*
|
||||
OutputStreamData::Graph() const
|
||||
{
|
||||
return mStream->Graph();
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// All streams must belong to the same graph.
|
||||
MOZ_ASSERT(!Graph() || Graph() == aStream->Graph());
|
||||
|
||||
// Ensure that aStream finishes the moment mDecodedStream does.
|
||||
if (aFinishWhenEnded) {
|
||||
aStream->SetAutofinish(true);
|
||||
@ -359,6 +366,7 @@ DecodedStream::DecodedStream(MediaQueue<MediaData>& aAudioQueue,
|
||||
|
||||
DecodedStream::~DecodedStream()
|
||||
{
|
||||
MOZ_ASSERT(mStartTime.isNothing(), "playback should've ended.");
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise>
|
||||
@ -366,65 +374,82 @@ DecodedStream::StartPlayback(int64_t aStartTime, const MediaInfo& aInfo)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT(mStartTime.isNothing(), "playback already started.");
|
||||
|
||||
mStartTime.emplace(aStartTime);
|
||||
mInfo = aInfo;
|
||||
|
||||
// TODO: Unfortunately, current call flow of MDSM guarantees mData is non-null
|
||||
// when StartPlayback() is called which imposes an obscure dependency on MDSM.
|
||||
// We will align the life cycle of mData with {Start,Stop}Playback so that
|
||||
// DecodedStream doesn't need to make assumptions about mData's life cycle.
|
||||
return mData->mFinishPromise;
|
||||
class R : public nsRunnable {
|
||||
typedef MozPromiseHolder<GenericPromise> Promise;
|
||||
typedef void(DecodedStream::*Method)(Promise&&);
|
||||
public:
|
||||
R(DecodedStream* aThis, Method aMethod, Promise&& aPromise)
|
||||
: mThis(aThis), mMethod(aMethod)
|
||||
{
|
||||
mPromise = Move(aPromise);
|
||||
}
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
(mThis->*mMethod)(Move(mPromise));
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<DecodedStream> mThis;
|
||||
Method mMethod;
|
||||
Promise mPromise;
|
||||
};
|
||||
|
||||
MozPromiseHolder<GenericPromise> promise;
|
||||
nsRefPtr<GenericPromise> rv = promise.Ensure(__func__);
|
||||
nsCOMPtr<nsIRunnable> r = new R(this, &DecodedStream::CreateData, Move(promise));
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
|
||||
return rv.forget();
|
||||
}
|
||||
|
||||
void DecodedStream::StopPlayback()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
// Playback didn't even start at all.
|
||||
if (mStartTime.isNothing()) {
|
||||
return;
|
||||
}
|
||||
mStartTime.reset();
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::DestroyData()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
// Avoid the redundant blocking to output stream.
|
||||
if (!mData) {
|
||||
// Clear mData immediately when this playback session ends so we won't
|
||||
// send data to the wrong stream in SendData() in next playback session.
|
||||
DecodedStreamData* data = mData.release();
|
||||
// mData is not yet created on the main thread.
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
mOutputStreamManager.Disconnect();
|
||||
mData = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::RecreateData()
|
||||
{
|
||||
nsRefPtr<DecodedStream> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void {
|
||||
self->RecreateData(nullptr);
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
|
||||
self->mOutputStreamManager.Disconnect();
|
||||
delete data;
|
||||
});
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::RecreateData(MediaStreamGraph* aGraph)
|
||||
DecodedStream::CreateData(MozPromiseHolder<GenericPromise>&& aPromise)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT((aGraph && !mData && !HasConsumers()) || // first time
|
||||
(!aGraph && mData)); // 2nd time and later
|
||||
MOZ_ASSERT(!mData, "Already created.");
|
||||
|
||||
if (!aGraph) {
|
||||
aGraph = mData->mStream->Graph();
|
||||
// No need to create a source stream when there are no output streams. This
|
||||
// happens when RemoveOutput() is called immediately after StartPlayback().
|
||||
// We also bail out when the playback session has ended. This happens when
|
||||
// StopPlayback() is called immediately after StartPlayback().
|
||||
if (!mOutputStreamManager.Graph() || mStartTime.isNothing()) {
|
||||
// Resolve the promise to indicate the end of playback.
|
||||
aPromise.Resolve(true, __func__);
|
||||
return;
|
||||
}
|
||||
auto source = aGraph->CreateSourceStream(nullptr);
|
||||
DestroyData();
|
||||
mData.reset(new DecodedStreamData(source, mPlaying));
|
||||
|
||||
// Note that the delay between removing ports in DestroyData
|
||||
// and adding new ones won't cause a glitch since all graph operations
|
||||
// between main-thread stable states take effect atomically.
|
||||
auto source = mOutputStreamManager.Graph()->CreateSourceStream(nullptr);
|
||||
mData.reset(new DecodedStreamData(source, mPlaying, Move(aPromise)));
|
||||
mOutputStreamManager.Connect(mData->mStream);
|
||||
}
|
||||
|
||||
@ -441,20 +466,13 @@ DecodedStream::GetReentrantMonitor() const
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
DecodedStream::AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
if (!mData) {
|
||||
RecreateData(aStream->Graph());
|
||||
}
|
||||
|
||||
mOutputStreamManager.Add(aStream, aFinishWhenEnded);
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::Remove(MediaStream* aStream)
|
||||
DecodedStream::RemoveOutput(MediaStream* aStream)
|
||||
{
|
||||
mOutputStreamManager.Remove(aStream);
|
||||
}
|
||||
@ -736,6 +754,11 @@ DecodedStream::SendData()
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT(mStartTime.isSome(), "Must be called after StartPlayback()");
|
||||
|
||||
// Not yet created on the main thread. MDSM will try again later.
|
||||
if (!mData) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing to do when the stream is finished.
|
||||
if (mData->mHaveSentFinish) {
|
||||
return;
|
||||
@ -759,7 +782,7 @@ int64_t
|
||||
DecodedStream::AudioEndTime() const
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mStartTime.isSome() && mInfo.HasAudio()) {
|
||||
if (mStartTime.isSome() && mInfo.HasAudio() && mData) {
|
||||
CheckedInt64 t = mStartTime.ref() +
|
||||
FramesToUsecs(mData->mAudioFramesWritten, mInfo.mAudio.mRate);
|
||||
if (t.isValid()) {
|
||||
@ -776,14 +799,14 @@ DecodedStream::GetPosition() const
|
||||
// This is only called after MDSM starts playback. So mStartTime is
|
||||
// guaranteed to be something.
|
||||
MOZ_ASSERT(mStartTime.isSome());
|
||||
return mStartTime.ref() + mData->GetPosition();
|
||||
return mStartTime.ref() + (mData ? mData->GetPosition() : 0);
|
||||
}
|
||||
|
||||
bool
|
||||
DecodedStream::IsFinished() const
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
return mData->IsFinished();
|
||||
return mData && mData->IsFinished();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
{
|
||||
return mStream == aStream;
|
||||
}
|
||||
// Return the graph mStream belongs to.
|
||||
MediaStreamGraph* Graph() const;
|
||||
|
||||
private:
|
||||
OutputStreamManager* mOwner;
|
||||
@ -81,6 +83,12 @@ public:
|
||||
void Connect(MediaStream* aStream);
|
||||
// Disconnect all output streams from the input stream.
|
||||
void Disconnect();
|
||||
// Return the graph these streams belong to or null if empty.
|
||||
MediaStreamGraph* Graph() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return !IsEmpty() ? mStreams[0].Graph() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Keep the input stream so we can connect the output streams that
|
||||
@ -105,10 +113,8 @@ public:
|
||||
// Mimic MDSM::StopAudioThread.
|
||||
void StopPlayback();
|
||||
|
||||
void DestroyData();
|
||||
void RecreateData();
|
||||
void Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
void Remove(MediaStream* aStream);
|
||||
void AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
void RemoveOutput(MediaStream* aStream);
|
||||
|
||||
void SetPlaying(bool aPlaying);
|
||||
void SetVolume(double aVolume);
|
||||
@ -126,7 +132,7 @@ protected:
|
||||
|
||||
private:
|
||||
ReentrantMonitor& GetReentrantMonitor() const;
|
||||
void RecreateData(MediaStreamGraph* aGraph);
|
||||
void CreateData(MozPromiseHolder<GenericPromise>&& aPromise);
|
||||
void InitTracks();
|
||||
void AdvanceTracks();
|
||||
void SendAudio(double aVolume, bool aIsSameOrigin);
|
||||
|
@ -386,7 +386,9 @@ void MediaDecoderStateMachine::SendStreamData()
|
||||
// keep decoding audio samples till the end and consume a lot of memory.
|
||||
// Therefore we only discard those behind the stream clock to throttle
|
||||
// the decoding speed.
|
||||
if (a && a->mTime <= clockTime) {
|
||||
// Note we don't discard a sample when |a->mTime == clockTime| because that
|
||||
// will discard the 1st sample when clockTime is still 0.
|
||||
if (a && a->mTime < clockTime) {
|
||||
nsRefPtr<MediaData> releaseMe = AudioQueue().PopFront();
|
||||
continue;
|
||||
}
|
||||
@ -1552,10 +1554,6 @@ MediaDecoderStateMachine::InitiateSeek()
|
||||
"Can only seek in range [0,duration]");
|
||||
mCurrentSeek.mTarget.mTime = seekTime;
|
||||
|
||||
if (mAudioCaptured) {
|
||||
mDecodedStream->RecreateData();
|
||||
}
|
||||
|
||||
mDropAudioUntilNextDiscontinuity = HasAudio();
|
||||
mDropVideoUntilNextDiscontinuity = HasVideo();
|
||||
mCurrentTimeBeforeSeek = GetMediaTime();
|
||||
@ -3173,7 +3171,7 @@ void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
|
||||
mDecodedStream->Connect(aStream, aFinishWhenEnded);
|
||||
mDecodedStream->AddOutput(aStream, aFinishWhenEnded);
|
||||
DispatchAudioCaptured();
|
||||
}
|
||||
|
||||
@ -3181,7 +3179,7 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DECODER_LOG("RemoveOutputStream=%p!", aStream);
|
||||
mDecodedStream->Remove(aStream);
|
||||
mDecodedStream->RemoveOutput(aStream);
|
||||
if (!mDecodedStream->HasConsumers()) {
|
||||
DispatchAudioUncaptured();
|
||||
}
|
||||
|
@ -319,7 +319,6 @@ public:
|
||||
if (mReader) {
|
||||
mReader->BreakCycles();
|
||||
}
|
||||
mDecodedStream->DestroyData();
|
||||
mResource = nullptr;
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
@ -683,26 +683,22 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
|
||||
tags=msg capturestream
|
||||
[test_mediarecorder_record_no_timeslice.html]
|
||||
tags=msg capturestream
|
||||
skip-if = toolkit == 'gonk' && debug
|
||||
[test_mediarecorder_record_nosrc.html]
|
||||
tags=msg capturestream
|
||||
[test_mediarecorder_record_session.html]
|
||||
tags=msg capturestream
|
||||
[test_mediarecorder_record_startstopstart.html]
|
||||
tags=msg
|
||||
skip-if = toolkit == 'gonk' && debug
|
||||
[test_mediarecorder_record_stopms.html]
|
||||
tags=msg
|
||||
[test_mediarecorder_record_timeslice.html]
|
||||
tags=msg capturestream
|
||||
skip-if = toolkit == 'gonk' && debug
|
||||
[test_mediarecorder_reload_crash.html]
|
||||
tags=msg capturestream
|
||||
[test_mediarecorder_unsupported_src.html]
|
||||
tags=msg
|
||||
[test_mediarecorder_record_getdata_afterstart.html]
|
||||
tags=msg capturestream
|
||||
skip-if = toolkit == 'gonk' && debug
|
||||
[test_mediatrack_consuming_mediaresource.html]
|
||||
[test_mediatrack_consuming_mediastream.html]
|
||||
tags=msg
|
||||
|
@ -235,7 +235,6 @@ function setupEnvironment() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
'set': [
|
||||
['canvas.capturestream.enabled', true],
|
||||
['dom.messageChannel.enabled', true],
|
||||
['media.peerconnection.enabled', true],
|
||||
['media.peerconnection.identity.enabled', true],
|
||||
['media.peerconnection.identity.timeout', 120000],
|
||||
@ -246,7 +245,6 @@ function setupEnvironment() {
|
||||
['media.getusermedia.screensharing.enabled', true],
|
||||
['media.getusermedia.screensharing.allowed_domains', "mochi.test"],
|
||||
['media.getusermedia.audiocapture.enabled', true],
|
||||
['media.useAudioChannelService', true],
|
||||
['media.recorder.audio_node.enabled', true]
|
||||
]
|
||||
}, setTestOptions);
|
||||
|
@ -105,8 +105,7 @@ function testMultipleFingerprints() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [ [ 'dom.messageChannel.enabled', true ],
|
||||
[ 'media.peerconnection.identity.enabled', true ] ]
|
||||
set: [ [ 'media.peerconnection.identity.enabled', true ] ]
|
||||
}, testMultipleFingerprints);
|
||||
</script>
|
||||
</body>
|
||||
|
@ -162,9 +162,7 @@ function run_all_tests() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [ [ 'dom.messageChannel.enabled', true ] ]
|
||||
}, run_all_tests);
|
||||
run_all_tests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -305,11 +305,6 @@ private:
|
||||
bool mSuspended;
|
||||
};
|
||||
|
||||
static bool UseAudioChannelService()
|
||||
{
|
||||
return Preferences::GetBool("media.useAudioChannelService");
|
||||
}
|
||||
|
||||
static bool UseAudioChannelAPI()
|
||||
{
|
||||
return Preferences::GetBool("media.useAudioChannelAPI");
|
||||
@ -597,10 +592,6 @@ AudioDestinationNode::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& a
|
||||
bool
|
||||
AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
|
||||
{
|
||||
if (!UseAudioChannelService()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only normal channel doesn't need permission.
|
||||
if (aValue == AudioChannel::Normal) {
|
||||
return true;
|
||||
@ -636,7 +627,7 @@ AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
|
||||
void
|
||||
AudioDestinationNode::CreateAudioChannelAgent()
|
||||
{
|
||||
if (mIsOffline || !UseAudioChannelService()) {
|
||||
if (mIsOffline) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -141,8 +141,7 @@ function runTest() {
|
||||
test();
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true ],
|
||||
["media.useAudioChannelService", true ]]}, runTest);
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true ]]}, runTest);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(5);
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "MessageChannel.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/MessageChannelBinding.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/Navigator.h"
|
||||
@ -30,149 +29,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
namespace {
|
||||
bool gPrefInitialized = false;
|
||||
bool gPrefEnabled = false;
|
||||
|
||||
bool
|
||||
CheckPermission(nsIPrincipal* aPrincipal, bool aCallerChrome)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!gPrefInitialized) {
|
||||
Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled");
|
||||
gPrefInitialized = true;
|
||||
}
|
||||
|
||||
// Enabled by pref
|
||||
if (gPrefEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Chrome callers are allowed.
|
||||
if (aCallerChrome) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_FAILED(aPrincipal->GetURI(getter_AddRefs(uri))) || !uri) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isResource = false;
|
||||
if (NS_FAILED(uri->SchemeIs("resource", &isResource))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isResource;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
GetPrincipalFromWorkerPrivate(workers::WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsIPrincipal* principal = aWorkerPrivate->GetPrincipal();
|
||||
if (principal) {
|
||||
return principal;
|
||||
}
|
||||
|
||||
// Walk up to our containing page
|
||||
workers::WorkerPrivate* wp = aWorkerPrivate;
|
||||
while (wp->GetParent()) {
|
||||
wp = wp->GetParent();
|
||||
}
|
||||
|
||||
nsPIDOMWindow* window = wp->GetWindow();
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return doc->NodePrincipal();
|
||||
}
|
||||
|
||||
// A WorkerMainThreadRunnable to synchronously dispatch the call of
|
||||
// CheckPermission() from the worker thread to the main thread.
|
||||
class CheckPermissionRunnable final : public workers::WorkerMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
bool mResult;
|
||||
bool mCallerChrome;
|
||||
|
||||
explicit CheckPermissionRunnable(workers::WorkerPrivate* aWorkerPrivate)
|
||||
: workers::WorkerMainThreadRunnable(aWorkerPrivate)
|
||||
, mResult(false)
|
||||
, mCallerChrome(false)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
mCallerChrome = aWorkerPrivate->UsesSystemPrincipal();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate);
|
||||
if (!principal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isNullPrincipal;
|
||||
nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(isNullPrincipal)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mResult = CheckPermission(principal, mCallerChrome);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/* static */ bool
|
||||
MessageChannel::Enabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
JS::Rooted<JSObject*> global(aCx, aGlobal);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = Navigator::GetWindowFromGlobal(global);
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIDocument* doc = win->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CheckPermission(doc->NodePrincipal(),
|
||||
nsContentUtils::IsCallerChrome());
|
||||
}
|
||||
|
||||
workers::WorkerPrivate* workerPrivate =
|
||||
workers::GetWorkerPrivateFromContext(aCx);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<CheckPermissionRunnable> runnable =
|
||||
new CheckPermissionRunnable(workerPrivate);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return runnable->mResult;
|
||||
}
|
||||
|
||||
MessageChannel::MessageChannel(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
{
|
||||
|
@ -28,9 +28,6 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
|
||||
|
||||
static bool Enabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
public:
|
||||
nsPIDOMWindow*
|
||||
GetParentObject() const
|
||||
{
|
||||
|
@ -14,7 +14,6 @@ support-files =
|
||||
[test_messageChannel_cloning.html]
|
||||
[test_messageChannel_pingpong.html]
|
||||
[test_messageChannel_post.html]
|
||||
[test_messageChannel_pref.html]
|
||||
[test_messageChannel_start.html]
|
||||
[test_messageChannel_transferable.html]
|
||||
[test_messageChannel_unshipped.html]
|
||||
|
@ -21,29 +21,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
/** Test for Bug 677638 **/
|
||||
var a = new MessageChannel();
|
||||
ok(a, "MessageChannel created");
|
||||
/** Test for Bug 677638 **/
|
||||
var a = new MessageChannel();
|
||||
ok(a, "MessageChannel created");
|
||||
|
||||
var port1 = a.port1;
|
||||
ok(port1, "MessageChannel.port1 exists");
|
||||
is(port1, a.port1, "MessageChannel.port1 is port1");
|
||||
var port1 = a.port1;
|
||||
ok(port1, "MessageChannel.port1 exists");
|
||||
is(port1, a.port1, "MessageChannel.port1 is port1");
|
||||
|
||||
var port2 = a.port2;
|
||||
ok(port2, "MessageChannel.port1 exists");
|
||||
is(port2, a.port2, "MessageChannel.port2 is port2");
|
||||
var port2 = a.port2;
|
||||
ok(port2, "MessageChannel.port1 exists");
|
||||
is(port2, a.port2, "MessageChannel.port2 is port2");
|
||||
|
||||
[ 'postMessage', 'start', 'close' ].forEach(function(e) {
|
||||
ok(e in port1, "MessagePort1." + e + " exists");
|
||||
ok(e in port2, "MessagePort2." + e + " exists");
|
||||
});
|
||||
[ 'postMessage', 'start', 'close' ].forEach(function(e) {
|
||||
ok(e in port1, "MessagePort1." + e + " exists");
|
||||
ok(e in port2, "MessagePort2." + e + " exists");
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -109,7 +109,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -32,7 +32,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1178076
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -64,7 +64,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -16,21 +16,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1176034
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTests() {
|
||||
var mc = new MessageChannel();
|
||||
var mc = new MessageChannel();
|
||||
|
||||
try {
|
||||
postMessage(42, "*", [ mc.port1, window ]);
|
||||
ok(false, "Something went wrong.");
|
||||
} catch(e) {
|
||||
ok(true, "PostMessage should fail and we should not leak.");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
try {
|
||||
postMessage(42, "*", [ mc.port1, window ]);
|
||||
ok(false, "Something went wrong.");
|
||||
} catch(e) {
|
||||
ok(true, "PostMessage should fail and we should not leak.");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -71,7 +71,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -70,7 +70,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, start);
|
||||
start();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,42 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 677638 - pref</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||
<div id="content"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTest(what) {
|
||||
var status;
|
||||
try {
|
||||
status = MessageChannel;
|
||||
ok(what, "Should MessageChannel exist?");
|
||||
} catch(e) {
|
||||
ok(!what, "Should MessageChannel exist?");
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", false]]},
|
||||
function() {
|
||||
runTest(false);
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]},
|
||||
function() {
|
||||
runTest(true);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -16,7 +16,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
var a = new MessageChannel();
|
||||
|
||||
var status = false;
|
||||
@ -27,11 +26,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
ok(status, "Transfering the same port should throw");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -20,19 +20,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
var a = new SharedWorker('sharedWorker_messageChannel.js');
|
||||
a.port.onmessage = function(evt) {
|
||||
is(evt.ports.length, 1, "We received a port.");
|
||||
evt.ports[0].onmessage = function(e) {
|
||||
is(e.data, 42, "Message reiceved back!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
evt.ports[0].postMessage(42);
|
||||
var a = new SharedWorker('sharedWorker_messageChannel.js');
|
||||
a.port.onmessage = function(evt) {
|
||||
is(evt.ports.length, 1, "We received a port.");
|
||||
evt.ports[0].onmessage = function(e) {
|
||||
is(e.data, 42, "Message reiceved back!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
evt.ports[0].postMessage(42);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
|
@ -15,22 +15,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('src', "iframe_messageChannel_sharedWorker2.html");
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('src', "iframe_messageChannel_sharedWorker2.html");
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
|
||||
var a = new SharedWorker('sharedWorker2_messageChannel.js');
|
||||
a.port.onmessage = function(evt) {
|
||||
is(evt.ports.length, 1, "We received a port.");
|
||||
evt.ports[0].onmessage = function(e) {
|
||||
is(e.data, "Hello from the iframe!", "Message reiceved from the iframe!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
var a = new SharedWorker('sharedWorker2_messageChannel.js');
|
||||
a.port.onmessage = function(evt) {
|
||||
is(evt.ports.length, 1, "We received a port.");
|
||||
evt.ports[0].onmessage = function(e) {
|
||||
is(e.data, "Hello from the iframe!", "Message reiceved from the iframe!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
|
@ -229,7 +229,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -105,7 +105,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -117,7 +117,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -54,7 +54,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -37,11 +37,8 @@ NfcCallback.prototype = {
|
||||
_requestId: null,
|
||||
|
||||
_createPromise: function _createPromise() {
|
||||
this.promise = this.createPromise((aResolve, aReject) => {
|
||||
this._requestId = btoa(this.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
}));
|
||||
this.promise = this.createPromiseWithId((aResolverId) => {
|
||||
this._requestId = btoa(aResolverId);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -104,10 +104,9 @@ PresentationDeviceInfoManager.prototype = {
|
||||
getAll: function() {
|
||||
log("getAll");
|
||||
let self = this;
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: aResolve, reject: aReject });
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
cpmm.sendAsyncMessage("PresentationDeviceInfoManager:GetAll", {
|
||||
requestId: resolverId,
|
||||
requestId: aResolverId,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -92,6 +92,12 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
namespace quota {
|
||||
|
||||
// We want profiles to be platform-independent so we always need to replace
|
||||
// the same characters on every platform. Windows has the most extensive set
|
||||
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
|
||||
// FILE_PATH_SEPARATOR.
|
||||
const char QuotaManager::kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\";
|
||||
|
||||
namespace {
|
||||
|
||||
/*******************************************************************************
|
||||
@ -1075,19 +1081,14 @@ public:
|
||||
void
|
||||
SanitizeOriginString(nsCString& aOrigin)
|
||||
{
|
||||
// We want profiles to be platform-independent so we always need to replace
|
||||
// the same characters on every platform. Windows has the most extensive set
|
||||
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
|
||||
// FILE_PATH_SEPARATOR.
|
||||
static const char kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\";
|
||||
|
||||
#ifdef XP_WIN
|
||||
NS_ASSERTION(!strcmp(kReplaceChars,
|
||||
NS_ASSERTION(!strcmp(QuotaManager::kReplaceChars,
|
||||
FILE_ILLEGAL_CHARACTERS FILE_PATH_SEPARATOR),
|
||||
"Illegal file characters have changed!");
|
||||
#endif
|
||||
|
||||
aOrigin.ReplaceChar(kReplaceChars, '+');
|
||||
aOrigin.ReplaceChar(QuotaManager::kReplaceChars, '+');
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -124,6 +124,8 @@ public:
|
||||
NS_DECL_NSIQUOTAMANAGER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static const char kReplaceChars[];
|
||||
|
||||
// Returns a non-owning reference.
|
||||
static QuotaManager*
|
||||
GetOrCreate();
|
||||
|
@ -46,9 +46,8 @@ RequestSyncManager.prototype = {
|
||||
|
||||
sendMessage: function(aMsg, aObj) {
|
||||
let self = this;
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
aObj.requestID =
|
||||
self.getPromiseResolverId({ resolve: aResolve, reject: aReject });
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
aObj.requestID = aResolverId;
|
||||
cpmm.sendAsyncMessage(aMsg, aObj, null,
|
||||
self._window.document.nodePrincipal);
|
||||
});
|
||||
|
@ -68,9 +68,8 @@ RequestSyncScheduler.prototype = {
|
||||
|
||||
sendMessage: function(aMsg, aObj) {
|
||||
let self = this;
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
aObj.requestID =
|
||||
self.getPromiseResolverId({ resolve: aResolve, reject: aReject });
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
aObj.requestID = aResolverId;
|
||||
cpmm.sendAsyncMessage(aMsg, aObj, null,
|
||||
self._window.document.nodePrincipal);
|
||||
});
|
||||
|
@ -146,18 +146,6 @@ function ResourceStatsManager() {
|
||||
ResourceStatsManager.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
_getPromise: function(aCallback) {
|
||||
let self = this;
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
let resolverId = self.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
});
|
||||
|
||||
aCallback(resolverId);
|
||||
});
|
||||
},
|
||||
|
||||
// Check time range.
|
||||
_checkTimeRange: function(aStart, aEnd) {
|
||||
if (DEBUG) {
|
||||
@ -180,7 +168,7 @@ ResourceStatsManager.prototype = {
|
||||
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:GetStats", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -198,7 +186,7 @@ ResourceStatsManager.prototype = {
|
||||
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:ClearStats", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -213,7 +201,7 @@ ResourceStatsManager.prototype = {
|
||||
clearAllStats: function() {
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:ClearAllStats", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -239,7 +227,7 @@ ResourceStatsManager.prototype = {
|
||||
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:AddAlarm", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -255,7 +243,7 @@ ResourceStatsManager.prototype = {
|
||||
getAlarms: function(aStatsOptions) {
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:GetAlarms", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -268,7 +256,7 @@ ResourceStatsManager.prototype = {
|
||||
removeAlarm: function(aAlarmId) {
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:RemoveAlarm", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -281,7 +269,7 @@ ResourceStatsManager.prototype = {
|
||||
removeAllAlarms: function() {
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:RemoveAllAlarms", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
@ -293,7 +281,7 @@ ResourceStatsManager.prototype = {
|
||||
getAvailableComponents: function() {
|
||||
// Create Promise.
|
||||
let self = this;
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.cpmm.sendAsyncMessage("ResourceStats:GetComponents", {
|
||||
resolverId: aResolverId,
|
||||
type: self.type,
|
||||
|
@ -62,12 +62,8 @@ PromiseHelpersSubclass.prototype = {
|
||||
callback(resolverId);
|
||||
};
|
||||
|
||||
return this.createPromise((resolve, reject) => {
|
||||
let resolverId = this.getPromiseResolverId({
|
||||
resolve: resolve,
|
||||
reject: reject
|
||||
});
|
||||
ctxCallback(resolverId);
|
||||
return this.createPromiseWithId((aResolverId) => {
|
||||
ctxCallback(aResolverId);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -225,7 +225,7 @@ SystemUpdateManager.prototype = {
|
||||
},
|
||||
|
||||
getProviders: function() {
|
||||
return this._sendPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
cpmm.sendAsyncMessage("SystemUpdate:GetProviders", {
|
||||
requestId: aResolverId,
|
||||
});
|
||||
@ -233,7 +233,7 @@ SystemUpdateManager.prototype = {
|
||||
},
|
||||
|
||||
getActiveProvider: function() {
|
||||
return this._sendPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
cpmm.sendAsyncMessage("SystemUpdate:GetActiveProvider", {
|
||||
requestId: aResolverId,
|
||||
});
|
||||
@ -241,21 +241,12 @@ SystemUpdateManager.prototype = {
|
||||
},
|
||||
|
||||
setActiveProvider: function(aUuid) {
|
||||
return this._sendPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
cpmm.sendAsyncMessage("SystemUpdate:SetActiveProvider", {
|
||||
requestId: aResolverId,
|
||||
uuid: aUuid
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_sendPromise: function(aCallback) {
|
||||
let self = this;
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
let resolverId = self.getPromiseResolverId({resolve: aResolve,
|
||||
reject: aReject});
|
||||
aCallback(resolverId);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -40,19 +40,6 @@ TetheringManager.prototype = {
|
||||
this.initDOMRequestHelper(aWindow, messages);
|
||||
},
|
||||
|
||||
_getPromise: function(aCallback) {
|
||||
let self = this;
|
||||
|
||||
return this.createPromise(function(aResolve, aReject) {
|
||||
let resolverId = self.getPromiseResolverId({
|
||||
resolve: aResolve,
|
||||
reject: aReject
|
||||
});
|
||||
|
||||
aCallback(resolverId);
|
||||
});
|
||||
},
|
||||
|
||||
// TODO : aMessage format may be different after supporting bt/usb.
|
||||
// for now, use wifi format first.
|
||||
receiveMessage: function(aMessage) {
|
||||
@ -77,7 +64,7 @@ TetheringManager.prototype = {
|
||||
let self = this;
|
||||
switch (aType) {
|
||||
case TETHERING_TYPE_WIFI:
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
let data = { resolverId: aResolverId, enabled: aEnabled, config: aConfig };
|
||||
cpmm.sendAsyncMessage("WifiManager:setWifiTethering", { data: data});
|
||||
});
|
||||
@ -85,7 +72,7 @@ TetheringManager.prototype = {
|
||||
case TETHERING_TYPE_USB:
|
||||
default:
|
||||
debug("tethering type(" + aType + ") doesn't support");
|
||||
return this._getPromise(function(aResolverId) {
|
||||
return this.createPromiseWithId(function(aResolverId) {
|
||||
self.takePromiseResolver(aResolverId).reject();
|
||||
});
|
||||
}
|
||||
|
@ -7,8 +7,7 @@
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
|
||||
*/
|
||||
|
||||
[Constructor, Func="MessageChannel::Enabled",
|
||||
Exposed=(Window,Worker)]
|
||||
[Constructor, Exposed=(Window,Worker)]
|
||||
interface MessageChannel {
|
||||
readonly attribute MessagePort port1;
|
||||
readonly attribute MessagePort port2;
|
||||
|
@ -202,7 +202,6 @@
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.interception.enabled", true],
|
||||
["dom.messageChannel.enabled", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.caches.testing.enabled", true],
|
||||
|
@ -1,9 +1,9 @@
|
||||
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == empty-1.xul empty-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != empty-2.xul empty-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
# There is no way to simulate an autocomplete textbox in windows XP/Vista/7 default theme using CSS.
|
||||
# There is no way to simulate an autocomplete textbox in windows XP/Vista/7/8/10 default theme using CSS.
|
||||
# Therefore, the equlity tests below should be marked as failing.
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == autocomplete-1.xul autocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == autocomplete-1.xul autocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != emptymultiline-1.xul emptymultiline-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptytextbox-1.xul emptytextbox-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
@ -15,10 +15,10 @@ fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptytextbox-5.
|
||||
# Therefore, the equlity tests below should be marked as failing.
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != number-1.xul number-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != number-2.xul number-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-3.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-3.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != number-4.xul number-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-5.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-5.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == passwd-1.xul passwd-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == passwd-2.xul passwd-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != passwd-3.xul passwd-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
@ -26,4 +26,4 @@ fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == plain-1.xul pla
|
||||
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == textbox-1.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if((B2G&&browserIsRemote)||Mulet) != textbox-disabled.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
# Read-only textboxes look like normal textboxes in windows Vista/7 default theme
|
||||
fails-if(windowsDefaultTheme&&/^Windows\x20NT\x206\.[012]/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) != textbox-readonly.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) != textbox-readonly.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
|
@ -2083,9 +2083,9 @@ UpdatePluginWindowState(uint64_t aId)
|
||||
bool shouldComposePlugin = !!lts.mRoot &&
|
||||
!!lts.mRoot->GetParent();
|
||||
|
||||
bool shouldHidePlugin = (!lts.mRoot ||
|
||||
!lts.mRoot->GetParent()) &&
|
||||
!lts.mUpdatedPluginDataAvailable;
|
||||
bool shouldHidePlugin = !lts.mRoot ||
|
||||
!lts.mRoot->GetParent();
|
||||
|
||||
if (shouldComposePlugin) {
|
||||
if (!lts.mPluginData.Length()) {
|
||||
// We will pass through here in cases where the previous shadow layer
|
||||
|
@ -188,7 +188,10 @@ static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
|
||||
InfallibleTArray<PTextureChild*> textures;
|
||||
sImageBridgeChildSingleton->ManagedPTextureChild(textures);
|
||||
for (int i = textures.Length() - 1; i >= 0; --i) {
|
||||
TextureClient::AsTextureClient(textures[i])->ForceRemove();
|
||||
TextureClient* client = TextureClient::AsTextureClient(textures[i]);
|
||||
if (client) {
|
||||
client->ForceRemove();
|
||||
}
|
||||
}
|
||||
sImageBridgeChildSingleton->SendWillStop();
|
||||
sImageBridgeChildSingleton->MarkShutDown();
|
||||
|
@ -27,6 +27,35 @@ TEST(GfxWidgets, Split) {
|
||||
ASSERT_TRUE(SplitDriverVersion("25.4.0.8", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
|
||||
|
||||
ASSERT_TRUE(SplitDriverVersion("424.143.84437.3", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 424 && atoi(bStr) == 143 && atoi(cStr) == 8443 && atoi(dStr) == 3);
|
||||
|
||||
ASSERT_FALSE(SplitDriverVersion("25.4.0.8.", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
|
||||
|
||||
ASSERT_TRUE(SplitDriverVersion("424.143.8.3143243", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 424 && atoi(bStr) == 143 && atoi(cStr) == 8 && atoi(dStr) == 3143);
|
||||
|
||||
ASSERT_FALSE(SplitDriverVersion("25.4.0.8..", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
|
||||
|
||||
ASSERT_FALSE(SplitDriverVersion("424.143.8.3143243.", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 424 && atoi(bStr) == 143 && atoi(cStr) == 8 && atoi(dStr) == 3143);
|
||||
|
||||
ASSERT_FALSE(SplitDriverVersion("25.4.0.8.13", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
|
||||
|
||||
ASSERT_FALSE(SplitDriverVersion("4.1.8.13.24.35", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 4 && atoi(bStr) == 1 && atoi(cStr) == 8 && atoi(dStr) == 13);
|
||||
|
||||
ASSERT_TRUE(SplitDriverVersion("28...74", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 28 && atoi(bStr) == 0 && atoi(cStr) == 0 && atoi(dStr) == 74);
|
||||
|
||||
ASSERT_FALSE(SplitDriverVersion("4.1.8.13.24.35", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 4 && atoi(bStr) == 1 && atoi(cStr) == 8 && atoi(dStr) == 13);
|
||||
|
||||
ASSERT_TRUE(SplitDriverVersion("35..42.0", aStr, bStr, cStr, dStr));
|
||||
ASSERT_TRUE(atoi(aStr) == 35 && atoi(bStr) == 0 && atoi(cStr) == 42 && atoi(dStr) == 0);
|
||||
}
|
||||
|
||||
TEST(GfxWidgets, Versioning) {
|
||||
|
@ -90,15 +90,18 @@ Decoder::Init()
|
||||
}
|
||||
|
||||
nsresult
|
||||
Decoder::Decode()
|
||||
Decoder::Decode(IResumable* aOnResume)
|
||||
{
|
||||
MOZ_ASSERT(mInitialized, "Should be initialized here");
|
||||
MOZ_ASSERT(mIterator, "Should have a SourceBufferIterator");
|
||||
|
||||
// If no IResumable was provided, default to |this|.
|
||||
IResumable* onResume = aOnResume ? aOnResume : this;
|
||||
|
||||
// We keep decoding chunks until the decode completes or there are no more
|
||||
// chunks available.
|
||||
while (!GetDecodeDone() && !HasError()) {
|
||||
auto newState = mIterator->AdvanceOrScheduleResume(this);
|
||||
auto newState = mIterator->AdvanceOrScheduleResume(onResume);
|
||||
|
||||
if (newState == SourceBufferIterator::WAITING) {
|
||||
// We can't continue because the rest of the data hasn't arrived from the
|
||||
|
@ -36,13 +36,16 @@ public:
|
||||
void Init();
|
||||
|
||||
/**
|
||||
* Decodes, reading all data currently available in the SourceBuffer. If more
|
||||
* data is needed, Decode() automatically ensures that it will be called again
|
||||
* on a DecodePool thread when the data becomes available.
|
||||
* Decodes, reading all data currently available in the SourceBuffer.
|
||||
*
|
||||
* If more data is needed, Decode() will schedule @aOnResume to be called when
|
||||
* more data is available. If @aOnResume is null or unspecified, the default
|
||||
* implementation resumes decoding on a DecodePool thread. Most callers should
|
||||
* use the default implementation.
|
||||
*
|
||||
* Any errors are reported by setting the appropriate state on the decoder.
|
||||
*/
|
||||
nsresult Decode();
|
||||
nsresult Decode(IResumable* aOnResume = nullptr);
|
||||
|
||||
/**
|
||||
* Given a maximum number of bytes we're willing to decode, @aByteLimit,
|
||||
|
@ -213,10 +213,6 @@ SourceBuffer::AddWaitingConsumer(IResumable* aConsumer)
|
||||
|
||||
MOZ_ASSERT(!mStatus, "Waiting when we're complete?");
|
||||
|
||||
if (MOZ_UNLIKELY(NS_IsMainThread())) {
|
||||
NS_WARNING("SourceBuffer consumer on the main thread needed to wait");
|
||||
}
|
||||
|
||||
mWaitingConsumers.AppendElement(aConsumer);
|
||||
}
|
||||
|
||||
|
249
image/test/gtest/TestDecoders.cpp
Normal file
249
image/test/gtest/TestDecoders.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "decoders/nsBMPDecoder.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgITools.h"
|
||||
#include "ImageFactory.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThread.h"
|
||||
#include "mozilla/nsRefPtr.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "ProgressTracker.h"
|
||||
#include "SourceBuffer.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
TEST(ImageDecoders, ImageModuleAvailable)
|
||||
{
|
||||
// We can run into problems if XPCOM modules get initialized in the wrong
|
||||
// order. It's important that this test run first, both as a sanity check and
|
||||
// to ensure we get the module initialization order we want.
|
||||
nsCOMPtr<imgITools> imgTools =
|
||||
do_CreateInstance("@mozilla.org/image/tools;1");
|
||||
EXPECT_TRUE(imgTools != nullptr);
|
||||
}
|
||||
|
||||
static void
|
||||
CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder)
|
||||
{
|
||||
EXPECT_TRUE(aDecoder->GetDecodeDone());
|
||||
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
|
||||
aDecoder->HasError());
|
||||
EXPECT_TRUE(!aDecoder->WasAborted());
|
||||
|
||||
// Verify that the decoder made the expected progress.
|
||||
Progress progress = aDecoder->TakeProgress();
|
||||
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
|
||||
bool(progress & FLAG_HAS_ERROR));
|
||||
|
||||
if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
|
||||
return; // That's all we can check for bad images.
|
||||
}
|
||||
|
||||
EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
|
||||
EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
|
||||
EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
|
||||
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
|
||||
bool(progress & FLAG_HAS_TRANSPARENCY));
|
||||
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
|
||||
bool(progress & FLAG_IS_ANIMATED));
|
||||
|
||||
// The decoder should get the correct size.
|
||||
IntSize size = aDecoder->GetSize();
|
||||
EXPECT_EQ(aTestCase.mSize.width, size.width);
|
||||
EXPECT_EQ(aTestCase.mSize.height, size.height);
|
||||
|
||||
// Get the current frame, which is always the first frame of the image
|
||||
// because CreateAnonymousDecoder() forces a first-frame-only decode.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
nsRefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
// Verify that the resulting surfaces matches our expectations.
|
||||
EXPECT_EQ(SurfaceType::DATA, surface->GetType());
|
||||
EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
|
||||
surface->GetFormat() == SurfaceFormat::B8G8R8A8);
|
||||
EXPECT_EQ(aTestCase.mSize, surface->GetSize());
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(),
|
||||
aTestCase.mFlags & TEST_CASE_IS_FUZZY));
|
||||
}
|
||||
|
||||
static void
|
||||
CheckDecoderSingleChunk(const ImageTestCase& aTestCase)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
|
||||
ASSERT_TRUE(inputStream != nullptr);
|
||||
|
||||
// Figure out how much data we have.
|
||||
uint64_t length;
|
||||
nsresult rv = inputStream->Available(&length);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
// Write the data into a SourceBuffer.
|
||||
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
|
||||
sourceBuffer->ExpectLength(length);
|
||||
rv = sourceBuffer->AppendFromInputStream(inputStream, length);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
sourceBuffer->Complete(NS_OK);
|
||||
|
||||
// Create a decoder.
|
||||
DecoderType decoderType =
|
||||
DecoderFactory::GetDecoderType(aTestCase.mMimeType);
|
||||
nsRefPtr<Decoder> decoder =
|
||||
DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
|
||||
DefaultSurfaceFlags());
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// Run the full decoder synchronously.
|
||||
decoder->Decode();
|
||||
|
||||
CheckDecoderResults(aTestCase, decoder);
|
||||
}
|
||||
|
||||
class NoResume : public IResumable
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(NoResume, override)
|
||||
virtual void Resume() override { }
|
||||
|
||||
private:
|
||||
~NoResume() { }
|
||||
};
|
||||
|
||||
static void
|
||||
CheckDecoderMultiChunk(const ImageTestCase& aTestCase)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
|
||||
ASSERT_TRUE(inputStream != nullptr);
|
||||
|
||||
// Figure out how much data we have.
|
||||
uint64_t length;
|
||||
nsresult rv = inputStream->Available(&length);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
// Create a SourceBuffer and a decoder.
|
||||
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
|
||||
sourceBuffer->ExpectLength(length);
|
||||
DecoderType decoderType =
|
||||
DecoderFactory::GetDecoderType(aTestCase.mMimeType);
|
||||
nsRefPtr<Decoder> decoder =
|
||||
DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
|
||||
DefaultSurfaceFlags());
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// Decode synchronously, using a |NoResume| IResumable so the Decoder doesn't
|
||||
// attempt to schedule itself on a nonexistent DecodePool when we write more
|
||||
// data into the SourceBuffer.
|
||||
nsRefPtr<NoResume> noResume = new NoResume();
|
||||
for (uint64_t read = 0; read < length ; ++read) {
|
||||
uint64_t available = 0;
|
||||
rv = inputStream->Available(&available);
|
||||
ASSERT_TRUE(available > 0);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = sourceBuffer->AppendFromInputStream(inputStream, 1);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
decoder->Decode(noResume);
|
||||
}
|
||||
|
||||
sourceBuffer->Complete(NS_OK);
|
||||
decoder->Decode(noResume);
|
||||
|
||||
CheckDecoderResults(aTestCase, decoder);
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, PNGSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenPNGTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, PNGMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenPNGTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, GIFSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenGIFTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, GIFMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenGIFTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, JPGSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenJPGTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, JPGMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenJPGTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, BMPSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenBMPTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, BMPMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenBMPTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, ICOSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenICOTestCase());
|
||||
}
|
||||
|
||||
// XXX(seth): Disabled. We'll fix this in bug 1196066.
|
||||
TEST(ImageDecoders, DISABLED_ICOMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenICOTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, AnimatedGIFSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, AnimatedGIFMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, AnimatedPNGSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, AnimatedPNGMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, CorruptSingleChunk)
|
||||
{
|
||||
CheckDecoderSingleChunk(CorruptTestCase());
|
||||
}
|
||||
|
||||
TEST(ImageDecoders, CorruptMultiChunk)
|
||||
{
|
||||
CheckDecoderMultiChunk(CorruptTestCase());
|
||||
}
|
@ -10,6 +10,7 @@ FAIL_ON_WARNINGS = True
|
||||
|
||||
UNIFIED_SOURCES = [
|
||||
'Common.cpp',
|
||||
'TestDecoders.cpp',
|
||||
'TestDecodeToSurface.cpp',
|
||||
'TestMetadata.cpp',
|
||||
]
|
||||
|
@ -1,2 +1,2 @@
|
||||
skip-if(!winWidget) skip-if(/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761.sjs bug415761.ico
|
||||
skip-if(!winWidget) skip-if(/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761cleanup.sjs about:blank
|
||||
skip-if(!winWidget) skip-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761.sjs bug415761.ico # See Bug 850194
|
||||
skip-if(!winWidget) skip-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761cleanup.sjs about:blank
|
||||
|
222
js/public/UbiNodeCensus.h
Normal file
222
js/public/UbiNodeCensus.h
Normal file
@ -0,0 +1,222 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef js_UbiNodeCensus_h
|
||||
#define js_UbiNodeCensus_h
|
||||
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
#include "js/UbiNode.h"
|
||||
#include "js/UbiNodeTraverse.h"
|
||||
|
||||
// A census is a ubi::Node traversal that assigns each node to one or more
|
||||
// buckets, and returns a report with the size of each bucket.
|
||||
//
|
||||
// We summarize the results of a census with counts broken down according to
|
||||
// criteria selected by the API consumer code that is requesting the census. For
|
||||
// example, the following breakdown might give an interesting overview of the
|
||||
// heap:
|
||||
//
|
||||
// - all nodes
|
||||
// - objects
|
||||
// - objects with a specific [[Class]] *
|
||||
// - strings
|
||||
// - scripts
|
||||
// - all other Node types
|
||||
// - nodes with a specific ubi::Node::typeName *
|
||||
//
|
||||
// Obviously, the parts of this tree marked with * represent many separate
|
||||
// counts, depending on how many distinct [[Class]] values and ubi::Node type
|
||||
// names we encounter.
|
||||
//
|
||||
// The supported types of breakdowns are documented in
|
||||
// js/src/doc/Debugger/Debugger.Memory.md.
|
||||
//
|
||||
// When we parse the 'breakdown' argument to takeCensus, we build a tree of
|
||||
// CountType nodes. For example, for the breakdown shown in the
|
||||
// Debugger.Memory.prototype.takeCensus, documentation:
|
||||
//
|
||||
// {
|
||||
// by: "coarseType",
|
||||
// objects: { by: "objectClass" },
|
||||
// other: { by: "internalType" }
|
||||
// }
|
||||
//
|
||||
// we would build the following tree of CountType subclasses:
|
||||
//
|
||||
// ByCoarseType
|
||||
// objects: ByObjectClass
|
||||
// each class: SimpleCount
|
||||
// scripts: SimpleCount
|
||||
// strings: SimpleCount
|
||||
// other: ByUbinodeType
|
||||
// each type: SimpleCount
|
||||
//
|
||||
// The interior nodes are all breakdown types that categorize nodes according to
|
||||
// one characteristic or another; and the leaf nodes are all SimpleType.
|
||||
//
|
||||
// Each CountType has its own concrete C++ type that holds the counts it
|
||||
// produces. SimpleCount::Count just holds totals. ByObjectClass::Count has a
|
||||
// hash table whose keys are object class names and whose values are counts of
|
||||
// some other type (in the example above, SimpleCount).
|
||||
//
|
||||
// To keep actual count nodes small, they have no vtable. Instead, each count
|
||||
// points to its CountType, which knows how to carry out all the operations we
|
||||
// need on a Count. A CountType can produce new count nodes; process nodes as we
|
||||
// visit them; build a JS object reporting the results; and destruct count
|
||||
// nodes.
|
||||
|
||||
|
||||
namespace JS {
|
||||
namespace ubi {
|
||||
|
||||
struct Census;
|
||||
|
||||
class CountBase;
|
||||
|
||||
struct CountDeleter {
|
||||
void operator()(CountBase*);
|
||||
};
|
||||
|
||||
using CountBasePtr = UniquePtr<CountBase, CountDeleter>;
|
||||
|
||||
// Abstract base class for CountType nodes.
|
||||
struct CountType {
|
||||
explicit CountType(Census& census) : census(census) { }
|
||||
virtual ~CountType() { }
|
||||
|
||||
// Destruct a count tree node that this type instance constructed.
|
||||
virtual void destructCount(CountBase& count) = 0;
|
||||
|
||||
// Return a fresh node for the count tree that categorizes nodes according
|
||||
// to this type. Return a nullptr on OOM.
|
||||
virtual CountBasePtr makeCount() = 0;
|
||||
|
||||
// Trace |count| and all its children, for garbage collection.
|
||||
virtual void traceCount(CountBase& count, JSTracer* trc) = 0;
|
||||
|
||||
// Implement the 'count' method for counts returned by this CountType
|
||||
// instance's 'newCount' method.
|
||||
virtual bool count(CountBase& count, const Node& node) = 0;
|
||||
|
||||
// Implement the 'report' method for counts returned by this CountType
|
||||
// instance's 'newCount' method.
|
||||
virtual bool report(CountBase& count, MutableHandleValue report) = 0;
|
||||
|
||||
protected:
|
||||
Census& census;
|
||||
};
|
||||
|
||||
using CountTypePtr = UniquePtr<CountType, JS::DeletePolicy<CountType>>;
|
||||
|
||||
// An abstract base class for count tree nodes.
|
||||
class CountBase {
|
||||
// In lieu of a vtable, each CountBase points to its type, which
|
||||
// carries not only the implementations of the CountBase methods, but also
|
||||
// additional parameters for the type's behavior, as specified in the
|
||||
// breakdown argument passed to takeCensus.
|
||||
CountType& type;
|
||||
|
||||
protected:
|
||||
~CountBase() { }
|
||||
|
||||
public:
|
||||
explicit CountBase(CountType& type) : type(type), total_(0) { }
|
||||
|
||||
// Categorize and count |node| as appropriate for this count's type.
|
||||
bool count(const Node& node) { return type.count(*this, node); }
|
||||
|
||||
// Construct a JavaScript object reporting the counts recorded in this
|
||||
// count, and store it in |report|. Return true on success, or false on
|
||||
// failure.
|
||||
bool report(MutableHandleValue report) { return type.report(*this, report); }
|
||||
|
||||
// Down-cast this CountBase to its true type, based on its 'type' member,
|
||||
// and run its destructor.
|
||||
void destruct() { return type.destructCount(*this); }
|
||||
|
||||
// Trace this count for garbage collection.
|
||||
void trace(JSTracer* trc) { type.traceCount(*this, trc); }
|
||||
|
||||
size_t total_;
|
||||
};
|
||||
|
||||
class RootedCount : JS::CustomAutoRooter {
|
||||
CountBasePtr count;
|
||||
|
||||
void trace(JSTracer* trc) override { count->trace(trc); }
|
||||
|
||||
public:
|
||||
RootedCount(JSContext* cx, CountBasePtr&& count)
|
||||
: CustomAutoRooter(cx),
|
||||
count(Move(count))
|
||||
{ }
|
||||
CountBase* operator->() const { return count.get(); }
|
||||
explicit operator bool() const { return count.get(); }
|
||||
operator CountBasePtr&() { return count; }
|
||||
};
|
||||
|
||||
// Common data for a census traversal, shared across all CountType nodes.
|
||||
struct Census {
|
||||
JSContext* const cx;
|
||||
// If the targetZones set is non-empty, then only consider nodes whose zone
|
||||
// is an element of the set. If the targetZones set is empty, then nodes in
|
||||
// all zones are considered.
|
||||
JS::ZoneSet targetZones;
|
||||
Zone* atomsZone;
|
||||
|
||||
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
|
||||
|
||||
bool init();
|
||||
|
||||
// A 'new' work-alike that behaves like TempAllocPolicy: report OOM on this
|
||||
// census's context, but don't charge the memory allocated to our context's
|
||||
// GC pressure counters.
|
||||
template<typename T, typename... Args>
|
||||
T* new_(Args&&... args) MOZ_HEAP_ALLOCATOR {
|
||||
void* memory = js_malloc(sizeof(T));
|
||||
if (MOZ_UNLIKELY(!memory)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new(memory) T(mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// A BreadthFirst handler type that conducts a census, using a CountBase to
|
||||
// categorize and count each node.
|
||||
class CensusHandler {
|
||||
Census& census;
|
||||
CountBasePtr& rootCount;
|
||||
|
||||
public:
|
||||
CensusHandler(Census& census, CountBasePtr& rootCount)
|
||||
: census(census),
|
||||
rootCount(rootCount)
|
||||
{ }
|
||||
|
||||
bool report(MutableHandleValue report) {
|
||||
return rootCount->report(report);
|
||||
}
|
||||
|
||||
// This class needs to retain no per-node data.
|
||||
class NodeData { };
|
||||
|
||||
bool operator() (BreadthFirst<CensusHandler>& traversal,
|
||||
Node origin, const Edge& edge,
|
||||
NodeData* referentData, bool first);
|
||||
};
|
||||
|
||||
using CensusTraversal = BreadthFirst<CensusHandler>;
|
||||
|
||||
// Examine the census options supplied by the API consumer, and use that to
|
||||
// build a CountType tree.
|
||||
bool ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
|
||||
CountTypePtr& outResult);
|
||||
|
||||
} // namespace ubi
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_UbiNodeCensus_h
|
@ -87,7 +87,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
bool maybeSetSourceMapFromOptions();
|
||||
bool emitFinalReturn();
|
||||
bool initGlobalBindings(ParseContext<FullParseHandler>& pc);
|
||||
void markFunctionsWithinEvalScript();
|
||||
bool maybeCompleteCompressSource();
|
||||
|
||||
AutoCompilationTraceLogger traceLogger;
|
||||
@ -519,29 +518,6 @@ BytecodeCompiler::initGlobalBindings(ParseContext<FullParseHandler>& pc)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BytecodeCompiler::markFunctionsWithinEvalScript()
|
||||
{
|
||||
// Mark top level functions in an eval script as being within an eval.
|
||||
|
||||
if (!script->hasObjects())
|
||||
return;
|
||||
|
||||
ObjectArray* objects = script->objects();
|
||||
size_t start = script->innerObjectsStart();
|
||||
|
||||
for (size_t i = start; i < objects->length; i++) {
|
||||
JSObject* obj = objects->vector[i];
|
||||
if (obj->is<JSFunction>()) {
|
||||
JSFunction* fun = &obj->as<JSFunction>();
|
||||
if (fun->hasScript())
|
||||
fun->nonLazyScript()->setDirectlyInsideEval();
|
||||
else if (fun->isInterpretedLazy())
|
||||
fun->lazyScript()->setDirectlyInsideEval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::maybeCompleteCompressSource()
|
||||
{
|
||||
@ -621,12 +597,6 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Note that this marking must happen before we tell Debugger
|
||||
// about the new script, in case Debugger delazifies the script's
|
||||
// inner functions.
|
||||
if (options.forEval)
|
||||
markFunctionsWithinEvalScript();
|
||||
|
||||
emitter->tellDebuggerAboutCompiledScript(cx);
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
@ -790,8 +760,6 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
||||
|
||||
script->bindings = pn->pn_funbox->bindings;
|
||||
|
||||
if (lazy->directlyInsideEval())
|
||||
script->setDirectlyInsideEval();
|
||||
if (lazy->usesArgumentsApplyAndThis())
|
||||
script->setUsesArgumentsApplyAndThis();
|
||||
if (lazy->hasBeenCloned())
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
@ -48,6 +49,8 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::frontend;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::Some;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::NumberIsInt32;
|
||||
using mozilla::PodCopy;
|
||||
@ -107,16 +110,6 @@ struct frontend::LoopStmtInfo : public StmtInfoBCE
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
FunctionBox::switchStaticScopeToFunction()
|
||||
{
|
||||
if (staticScope_->is<StaticFunctionBoxScopeObject>()) {
|
||||
MOZ_ASSERT(staticScope_->as<StaticFunctionBoxScopeObject>().functionBox() == this);
|
||||
staticScope_ = function();
|
||||
}
|
||||
MOZ_ASSERT(staticScope_ == function());
|
||||
}
|
||||
|
||||
BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
|
||||
Parser<FullParseHandler>* parser, SharedContext* sc,
|
||||
HandleScript script, Handle<LazyScript*> lazyScript,
|
||||
@ -1512,57 +1505,65 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t hops = 0;
|
||||
// Walk the static scope chain and look for an aliased binding with
|
||||
// the name pn->pn_atom.
|
||||
uint32_t hops = 0;
|
||||
Maybe<uint32_t> slot;
|
||||
FunctionBox* funbox = sc->asFunctionBox();
|
||||
if (funbox->hasExtensibleScope())
|
||||
return false;
|
||||
if (funbox->function()->isNamedLambda() && funbox->function()->atom() == pn->pn_atom)
|
||||
return false;
|
||||
if (funbox->isHeavyweight()) {
|
||||
hops++;
|
||||
if (funbox->function()->isNamedLambda())
|
||||
hops++;
|
||||
}
|
||||
if (script->directlyInsideEval())
|
||||
return false;
|
||||
RootedObject outerScope(cx, script->enclosingStaticScope());
|
||||
for (StaticScopeIter<CanGC> ssi(cx, outerScope); !ssi.done(); ssi++) {
|
||||
if (ssi.type() != StaticScopeIter<CanGC>::Function) {
|
||||
if (ssi.type() == StaticScopeIter<CanGC>::Block) {
|
||||
// Use generic ops if a catch block is encountered.
|
||||
return false;
|
||||
}
|
||||
if (ssi.hasSyntacticDynamicScopeObject())
|
||||
hops++;
|
||||
PropertyName* name = pn->pn_atom->asPropertyName();
|
||||
for (StaticScopeIter<NoGC> ssi(funbox->staticScope()); !ssi.done(); ssi++) {
|
||||
// Don't optimize names through eval.
|
||||
if (ssi.type() == StaticScopeIter<NoGC>::Eval)
|
||||
return false;
|
||||
|
||||
if (!ssi.hasSyntacticDynamicScopeObject())
|
||||
continue;
|
||||
}
|
||||
RootedScript script(cx, ssi.funScript());
|
||||
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
|
||||
return false;
|
||||
if (ssi.hasSyntacticDynamicScopeObject()) {
|
||||
uint32_t slot;
|
||||
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
|
||||
default: return false;
|
||||
|
||||
// Look up for name in function and block scopes.
|
||||
if (ssi.type() == StaticScopeIter<NoGC>::Function) {
|
||||
RootedScript funScript(cx, ssi.funScript());
|
||||
if (funScript->funHasExtensibleScope() || ssi.fun().atom() == pn->pn_atom)
|
||||
return false;
|
||||
|
||||
// Skip the current function, since we're trying to convert a
|
||||
// free name.
|
||||
if (script != funScript) {
|
||||
uint32_t slot_;
|
||||
if (lookupAliasedName(funScript, name, &slot_, pn)) {
|
||||
slot = Some(slot_);
|
||||
break;
|
||||
}
|
||||
|
||||
pn->setOp(op);
|
||||
MOZ_ALWAYS_TRUE(pn->pn_scopecoord.set(parser->tokenStream, hops, slot));
|
||||
return true;
|
||||
}
|
||||
hops++;
|
||||
} else if (ssi.type() == StaticScopeIter<NoGC>::Block) {
|
||||
RootedShape shape(cx, ssi.block().lookupAliasedName(name));
|
||||
if (shape) {
|
||||
// Don't optimize setting a 'const' binding. Let the slow
|
||||
// path do the error checking.
|
||||
if (!shape->writable() && pn->getOp() == JSOP_SETNAME)
|
||||
return false;
|
||||
slot = Some(shape->slot());
|
||||
pn->pn_dflags |= PND_LEXICAL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(ssi.type() != StaticScopeIter<NoGC>::With);
|
||||
}
|
||||
|
||||
// If this walk up and check for directlyInsideEval is ever removed,
|
||||
// we'll need to adjust CompileLazyFunction to better communicate
|
||||
// whether we're inside eval to the BytecodeEmitter. For now, this
|
||||
// walk is why CompileLazyFunction can claim that it's never inside
|
||||
// eval.
|
||||
if (script->funHasExtensibleScope() || script->directlyInsideEval())
|
||||
return false;
|
||||
hops++;
|
||||
}
|
||||
|
||||
// If we found a scope binding name, convert the name op to an aliased
|
||||
// var op.
|
||||
if (slot.isSome()) {
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
|
||||
default: return false;
|
||||
}
|
||||
pn->setOp(op);
|
||||
MOZ_ALWAYS_TRUE(pn->pn_scopecoord.set(parser->tokenStream, hops, *slot));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7007,8 +7008,11 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
||||
isIndex = true;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
// EmitClass took care of constructor already.
|
||||
if (type == ClassBody && key->pn_atom == cx->names().constructor)
|
||||
if (type == ClassBody && key->pn_atom == cx->names().constructor &&
|
||||
!propdef->as<ClassMethod>().isStatic())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
|
@ -1160,8 +1160,8 @@ ObjectBox::trace(JSTracer* trc)
|
||||
if (box->isFunctionBox()) {
|
||||
FunctionBox* funbox = box->asFunctionBox();
|
||||
funbox->bindings.trace(trc);
|
||||
if (funbox->staticScope_)
|
||||
TraceRoot(trc, &funbox->staticScope_, "funbox-staticScope");
|
||||
if (funbox->enclosingStaticScope_)
|
||||
TraceRoot(trc, &funbox->enclosingStaticScope_, "funbox-enclosingStaticScope");
|
||||
}
|
||||
box = box->traceLink;
|
||||
}
|
||||
|
@ -48,6 +48,22 @@ using mozilla::Maybe;
|
||||
|
||||
using JS::AutoGCRooter;
|
||||
|
||||
JSFunction::AutoParseUsingFunctionBox::AutoParseUsingFunctionBox(ExclusiveContext* cx,
|
||||
frontend::FunctionBox* funbox)
|
||||
: fun_(cx, funbox->function()),
|
||||
oldEnv_(cx, fun_->environment())
|
||||
{
|
||||
fun_->setFunctionBox(funbox);
|
||||
funbox->computeAllowSyntax(fun_);
|
||||
funbox->computeInWith(fun_);
|
||||
}
|
||||
|
||||
JSFunction::AutoParseUsingFunctionBox::~AutoParseUsingFunctionBox()
|
||||
{
|
||||
fun_->unsetFunctionBox();
|
||||
fun_->setEnvironment(oldEnv_);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
@ -613,12 +629,12 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
|
||||
JSObject* staticScope, ParseContext<ParseHandler>* outerpc,
|
||||
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* outerpc,
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind)
|
||||
: ObjectBox(fun, traceListHead),
|
||||
SharedContext(cx, directives, extraWarnings),
|
||||
bindings(),
|
||||
staticScope_(staticScope),
|
||||
enclosingStaticScope_(enclosingStaticScope),
|
||||
bufStart(0),
|
||||
bufEnd(0),
|
||||
length(0),
|
||||
@ -636,22 +652,17 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
|
||||
// baked into JIT code, so they must be allocated tenured. They are held by
|
||||
// the JSScript so cannot be collected during a minor GC anyway.
|
||||
MOZ_ASSERT(fun->isTenured());
|
||||
|
||||
if (staticScope->is<StaticFunctionBoxScopeObject>())
|
||||
staticScope->as<StaticFunctionBoxScopeObject>().setFunctionBox(this);
|
||||
|
||||
computeAllowSyntax(staticScope);
|
||||
computeInWith(staticScope);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox*
|
||||
Parser<ParseHandler>::newFunctionBoxWithScope(Node fn, JSFunction* fun,
|
||||
ParseContext<ParseHandler>* outerpc,
|
||||
Directives inheritedDirectives,
|
||||
GeneratorKind generatorKind,
|
||||
JSObject* staticScope)
|
||||
Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun,
|
||||
ParseContext<ParseHandler>* outerpc,
|
||||
Directives inheritedDirectives,
|
||||
GeneratorKind generatorKind,
|
||||
JSObject* enclosingStaticScope)
|
||||
{
|
||||
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
|
||||
MOZ_ASSERT(fun);
|
||||
|
||||
/*
|
||||
@ -662,9 +673,8 @@ Parser<ParseHandler>::newFunctionBoxWithScope(Node fn, JSFunction* fun,
|
||||
* function.
|
||||
*/
|
||||
FunctionBox* funbox =
|
||||
alloc.new_<FunctionBox>(context, traceListHead, fun, staticScope, outerpc,
|
||||
inheritedDirectives,
|
||||
options().extraWarningsOption,
|
||||
alloc.new_<FunctionBox>(context, traceListHead, fun, enclosingStaticScope, outerpc,
|
||||
inheritedDirectives, options().extraWarningsOption,
|
||||
generatorKind);
|
||||
if (!funbox) {
|
||||
ReportOutOfMemory(context);
|
||||
@ -678,29 +688,6 @@ Parser<ParseHandler>::newFunctionBoxWithScope(Node fn, JSFunction* fun,
|
||||
return funbox;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox*
|
||||
Parser<ParseHandler>::newFunctionBox(Node fn, HandleFunction fun,
|
||||
ParseContext<ParseHandler>* outerpc,
|
||||
Directives inheritedDirectives,
|
||||
GeneratorKind generatorKind,
|
||||
HandleObject enclosingStaticScope)
|
||||
{
|
||||
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
|
||||
|
||||
StaticFunctionBoxScopeObject* scope =
|
||||
StaticFunctionBoxScopeObject::create(context, enclosingStaticScope);
|
||||
if (!scope)
|
||||
return nullptr;
|
||||
|
||||
FunctionBox* funbox = newFunctionBoxWithScope(fn, fun, outerpc, inheritedDirectives,
|
||||
generatorKind, scope);
|
||||
if (!funbox)
|
||||
return nullptr;
|
||||
|
||||
return funbox;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::trace(JSTracer* trc)
|
||||
@ -1305,10 +1292,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
break;
|
||||
case Method:
|
||||
MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator);
|
||||
if (generatorKind == NotGenerator)
|
||||
flags = JSFunction::INTERPRETED_METHOD;
|
||||
else
|
||||
flags = JSFunction::INTERPRETED_METHOD_GENERATOR;
|
||||
flags = (generatorKind == NotGenerator
|
||||
? JSFunction::INTERPRETED_METHOD
|
||||
: JSFunction::INTERPRETED_METHOD_GENERATOR);
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
case ClassConstructor:
|
||||
@ -1325,8 +1311,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
|
||||
break;
|
||||
default:
|
||||
flags = JSFunction::INTERPRETED_NORMAL;
|
||||
break;
|
||||
flags = (generatorKind == NotGenerator
|
||||
? JSFunction::INTERPRETED_NORMAL
|
||||
: JSFunction::INTERPRETED_GENERATOR);
|
||||
}
|
||||
|
||||
fun = NewFunctionWithProto(context, nullptr, 0, flags, nullptr, atom, proto,
|
||||
|
@ -106,6 +106,11 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
||||
|
||||
Node maybeFunction; /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */
|
||||
|
||||
// If sc->isFunctionBox(), this is used to temporarily link up the
|
||||
// FunctionBox with the JSFunction so the static scope chain may be walked
|
||||
// without a JSScript.
|
||||
mozilla::Maybe<JSFunction::AutoParseUsingFunctionBox> parseUsingFunctionBox;
|
||||
|
||||
// lastYieldOffset stores the offset of the last yield that was parsed.
|
||||
// NoYieldOffset is its initial value.
|
||||
static const uint32_t NoYieldOffset = UINT32_MAX;
|
||||
@ -270,6 +275,8 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
||||
inDeclDestructuring(false)
|
||||
{
|
||||
prs->pc = this;
|
||||
if (sc->isFunctionBox())
|
||||
parseUsingFunctionBox.emplace(prs->context, sc->asFunctionBox());
|
||||
}
|
||||
|
||||
~ParseContext();
|
||||
@ -463,17 +470,10 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
* cx->tempLifoAlloc.
|
||||
*/
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
FunctionBox* newFunctionBoxWithScope(Node fn, JSFunction* fun,
|
||||
ParseContext<ParseHandler>* outerpc,
|
||||
Directives directives, GeneratorKind generatorKind,
|
||||
JSObject* staticScope);
|
||||
|
||||
private:
|
||||
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext<ParseHandler>* outerpc,
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext<ParseHandler>* outerpc,
|
||||
Directives directives, GeneratorKind generatorKind,
|
||||
HandleObject enclosingStaticScope);
|
||||
JSObject* enclosingStaticScope);
|
||||
|
||||
public:
|
||||
// Use when the funbox is the outermost.
|
||||
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives,
|
||||
GeneratorKind generatorKind, HandleObject enclosingStaticScope)
|
||||
|
@ -191,10 +191,6 @@ class SharedContext
|
||||
bool inWith_;
|
||||
bool superScopeAlreadyNeedsHomeObject_;
|
||||
|
||||
protected:
|
||||
void computeAllowSyntax(JSObject* staticScope);
|
||||
void computeInWith(JSObject* staticScope);
|
||||
|
||||
public:
|
||||
SharedContext(ExclusiveContext* cx, Directives directives,
|
||||
bool extraWarnings)
|
||||
@ -215,6 +211,8 @@ class SharedContext
|
||||
// for the static scope. FunctionBoxes are LifoAlloc'd and need to
|
||||
// manually trace their static scope.
|
||||
virtual JSObject* staticScope() const = 0;
|
||||
void computeAllowSyntax(JSObject* staticScope);
|
||||
void computeInWith(JSObject* staticScope);
|
||||
|
||||
virtual ObjectBox* toObjectBox() { return nullptr; }
|
||||
inline bool isFunctionBox() { return toObjectBox() && toObjectBox()->isFunctionBox(); }
|
||||
@ -277,7 +275,7 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
{
|
||||
public:
|
||||
Bindings bindings; /* bindings for this function */
|
||||
JSObject* staticScope_;
|
||||
JSObject* enclosingStaticScope_;
|
||||
uint32_t bufStart;
|
||||
uint32_t bufEnd;
|
||||
uint32_t startLine;
|
||||
@ -285,7 +283,6 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
uint16_t length;
|
||||
|
||||
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
|
||||
bool inWith_:1; /* some enclosing scope is a with-statement */
|
||||
bool inGenexpLambda:1; /* lambda from generator expression */
|
||||
bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */
|
||||
bool useAsm:1; /* see useAsmOrInsideUseAsm */
|
||||
@ -300,13 +297,13 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
|
||||
JSObject* staticScope, ParseContext<ParseHandler>* pc,
|
||||
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* pc,
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind);
|
||||
|
||||
ObjectBox* toObjectBox() override { return this; }
|
||||
JSFunction* function() const { return &object->as<JSFunction>(); }
|
||||
JSObject* staticScope() const override { return staticScope_; }
|
||||
void switchStaticScopeToFunction();
|
||||
JSObject* staticScope() const override { return function(); }
|
||||
JSObject* enclosingStaticScope() const { return enclosingStaticScope_; }
|
||||
|
||||
GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
|
||||
bool isGenerator() const { return generatorKind() != NotGenerator; }
|
||||
|
6
js/src/jit-test/tests/basic/bug1180054.js
Normal file
6
js/src/jit-test/tests/basic/bug1180054.js
Normal file
@ -0,0 +1,6 @@
|
||||
function entryFrame_1(d) {
|
||||
assertJitStackInvariants();
|
||||
}
|
||||
for (i = 0Xa; i < 40; i++) {
|
||||
new entryFrame_1();
|
||||
}
|
15
js/src/jit-test/tests/ion/bug1185957.js
Normal file
15
js/src/jit-test/tests/ion/bug1185957.js
Normal file
@ -0,0 +1,15 @@
|
||||
// |jit-test| error: TypeError
|
||||
|
||||
load(libdir + "class.js");
|
||||
|
||||
var test = `
|
||||
class test {
|
||||
constructor() {};
|
||||
}
|
||||
(function() {
|
||||
test()
|
||||
})();
|
||||
`;
|
||||
|
||||
if (classesEnabled())
|
||||
eval(test);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user