merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-07-22 13:59:02 +02:00
commit f6fad857f8
197 changed files with 4033 additions and 1894 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1164310 requires a clobber due to bug 1177844
Bug 1186003 needed a CLOBBER

View File

@ -93,12 +93,19 @@ this.FxAccountsMgmtService = {
delete data.accountId;
}
// XXX dirty hack because Gaia is sending getAccounts.
if (data.method == "getAccounts") {
data.method = "getAccount";
}
switch(data.method) {
case "getAccounts":
FxAccountsManager.getAccount().then(
account => {
// We only expose the email and verification status so far.
self._onFulfill(msg.id, account);
case "getAccount":
case "getKeys":
FxAccountsManager[data.method]().then(
result => {
// For the getAccounts case, we only expose the email and
// verification status so far.
self._onFulfill(msg.id, result);
},
reason => {
self._onReject(msg.id, reason);

View File

@ -1930,6 +1930,12 @@ pref("browser.tabs.remote.autostart.1", false);
pref("browser.tabs.remote.autostart.2", true);
#endif
#ifdef NIGHTLY_BUILD
#if defined(XP_MACOSX)
pref("layers.async-pan-zoom.enabled", true);
#endif
#endif
#ifdef E10S_TESTING_ONLY
// Enable e10s add-on interposition by default.
pref("extensions.interposition.enabled", true);

View File

@ -18,36 +18,21 @@ function getFocusedLocalName(browser) {
}
add_task(function* () {
gBrowser.selectedTab = gBrowser.addTab(URL);
let browser = gBrowser.selectedBrowser;
yield BrowserTestUtils.browserLoaded(browser);
let testTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let browser = testTab.linkedBrowser;
is((yield getFocusedLocalName(browser)), "button", "button is focused");
let promiseFocused = ContentTask.spawn(browser, null, function* () {
return new Promise(resolve => {
content.addEventListener("focus", function onFocus({target}) {
if (String(target.location).startsWith("data:")) {
content.removeEventListener("focus", onFocus);
resolve();
}
});
});
});
let blankTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
// The test page loaded, so open an empty tab, select it, then restore
// the test tab. This causes the test page's focused element to be removed
// from its document.
gBrowser.selectedTab = gBrowser.addTab("about:blank");
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
gBrowser.removeCurrentTab();
// Wait until the original tab is focused again.
yield promiseFocused;
yield BrowserTestUtils.switchTab(gBrowser, testTab);
// Make sure focus is given to the window because the element is now gone.
is((yield getFocusedLocalName(browser)), "body", "body is focused");
// Cleanup.
gBrowser.removeTab(blankTab);
gBrowser.removeCurrentTab();
});

View File

@ -88,7 +88,7 @@ var gPermissionManager = {
// If the uri doesn't successfully parse, try adding a http:// and parsing again
let uri;
try {
let uri = Services.io.newURI(input_url, null, null);
uri = Services.io.newURI(input_url, null, null);
} catch(ex) {
uri = Services.io.newURI("http://" + input_url, null, null);
}

View File

@ -16,6 +16,8 @@ var testRunner = {
params.url.value = "test.com";
params.btnAllow.doCommand();
is(params.tree.view.rowCount, 1, "added exception shows up in treeview");
is(params.tree.view.getCellText(0, params.nameCol), "http://test.com",
"origin name should be set correctly");
is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
"permission text should be set correctly");
params.btnApplyChanges.doCommand();
@ -27,6 +29,8 @@ var testRunner = {
test: function(params) {
params.url.value = "test.com";
params.btnBlock.doCommand();
is(params.tree.view.getCellText(0, params.nameCol), "http://test.com",
"origin name should be set correctly");
is(params.tree.view.getCellText(0, params.statusCol), params.denyText,
"permission should change to deny in UI");
params.btnApplyChanges.doCommand();
@ -38,6 +42,8 @@ var testRunner = {
test: function(params) {
params.url.value = "test.com";
params.btnAllow.doCommand();
is(params.tree.view.getCellText(0, params.nameCol), "http://test.com",
"origin name should be set correctly");
is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
"permission should revert back to allow");
params.btnApplyChanges.doCommand();
@ -68,6 +74,55 @@ var testRunner = {
params.pm.remove(uri, "popup");
},
},
{
test: function(params) {
params.url.value = "https://test.com:12345";
params.btnAllow.doCommand();
is(params.tree.view.rowCount, 1, "added exception shows up in treeview");
is(params.tree.view.getCellText(0, params.nameCol), "https://test.com:12345",
"origin name should be set correctly");
is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
"permission text should be set correctly");
params.btnApplyChanges.doCommand();
},
observances: [{ type: "cookie", origin: "https://test.com:12345", data: "added",
capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
},
{
test: function(params) {
params.url.value = "https://test.com:12345";
params.btnBlock.doCommand();
is(params.tree.view.getCellText(0, params.nameCol), "https://test.com:12345",
"origin name should be set correctly");
is(params.tree.view.getCellText(0, params.statusCol), params.denyText,
"permission should change to deny in UI");
params.btnApplyChanges.doCommand();
},
observances: [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
capability: Ci.nsIPermissionManager.DENY_ACTION }],
},
{
test: function(params) {
params.url.value = "https://test.com:12345";
params.btnAllow.doCommand();
is(params.tree.view.getCellText(0, params.nameCol), "https://test.com:12345",
"origin name should be set correctly");
is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
"permission should revert back to allow");
params.btnApplyChanges.doCommand();
},
observances: [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
},
{
test: function(params) {
params.url.value = "https://test.com:12345";
params.btnRemove.doCommand();
is(params.tree.view.rowCount, 0, "exception should be removed");
params.btnApplyChanges.doCommand();
},
observances: [{ type: "cookie", origin: "https://test.com:12345", data: "deleted" }],
},
],
_currentTest: -1,
@ -127,6 +182,7 @@ var testRunner = {
let params = {
doc: event.target,
tree: event.target.getElementById("permissionsTree"),
nameCol: event.target.getElementById("permissionsTree").treeBoxObject.columns.getColumnAt(0),
statusCol: event.target.getElementById("permissionsTree").treeBoxObject.columns.getColumnAt(1),
url: event.target.getElementById("url"),
btnAllow: event.target.getElementById("btnAllow"),

View File

@ -7,7 +7,6 @@ let gTests;
function test() {
waitForExplicitFinish();
requestLongerTimeout(2);
requestCompleteLog();
gTests = runTest();
gTests.next();
}

View File

@ -7,6 +7,13 @@
"unpack": true
},
{
"size": 4079256,
"digest": "bb5238558bcf6db2ca395513c8dccaa15dd61b3c375598eb6a685356b0c1a2d9840e3bf81bc00242b872fd798541f53d723777c754412abf0e772b7cc284937c",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",

View File

@ -7,6 +7,13 @@
"unpack": true
},
{
"size": 4431740,
"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",

View File

@ -21,7 +21,9 @@ function test() {
"-H 'X-Custom-Header-2: 8.8.8.8'",
"-H 'X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
"-H 'Referer: " + CURL_URL + "'",
"-H 'Connection: keep-alive'"
"-H 'Connection: keep-alive'",
"-H 'Pragma: no-cache'",
"-H 'Cache-Control: no-cache'"
].join(" ");
const EXPECTED_WIN_RESULT = [
@ -36,7 +38,9 @@ function test() {
'-H "X-Custom-Header-2: 8.8.8.8"',
'-H "X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
'-H "Referer: ' + CURL_URL + '"',
'-H "Connection: keep-alive"'
'-H "Connection: keep-alive"',
'-H "Pragma: no-cache"',
'-H "Cache-Control: no-cache"'
].join(" ");
const EXPECTED_RESULT = Services.appinfo.OS == "WINNT"

View File

@ -0,0 +1,107 @@
#!/bin/bash
# Use "build-gtk.sh" or "build-gtk.sh 64" to build a 64-bits tarball for tooltool.
# Use "build-gtk.sh 32" to build a 32-bits tarball for tooltool.
# Mock environments used:
# - 64-bits:
# https://s3.amazonaws.com/mozilla-releng-mock-archive/67b65e51eb091fba7941a04d249343924a3ee653
# + libxml2-devel.x86_64 gettext.x86_64 libjpeg-devel.x86_64
# - 32-bits:
# https://s3.amazonaws.com/mozilla-releng-mock-archive/58d76c6acca148a1aedcbec7fc1b8212e12807b4
# + libxml2-devel.i686 gettext.i686 libjpeg-devel.i686
set -e
pkg_config_version=0.28
fontconfig_version=2.8.0
libffi_version=3.0.13
glib_version=2.34.3
gdk_pixbuf_version=2.26.5
pixman_version=0.20.2
cairo_version=1.10.2
pango_version=1.30.1
atk_version=2.2.0
gtk__version=3.4.4
pkg_config_url=http://pkgconfig.freedesktop.org/releases/pkg-config-${pkg_config_version}.tar.gz
fontconfig_url=http://www.freedesktop.org/software/fontconfig/release/fontconfig-${fontconfig_version}.tar.gz
libffi_url=ftp://sourceware.org/pub/libffi/libffi-${libffi_version}.tar.gz
glib_url=http://ftp.gnome.org/pub/gnome/sources/glib/${glib_version%.*}/glib-${glib_version}.tar.xz
gdk_pixbuf_url=http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${gdk_pixbuf_version%.*}/gdk-pixbuf-${gdk_pixbuf_version}.tar.xz
pixman_url=http://cairographics.org/releases/pixman-${pixman_version}.tar.gz
cairo_url=http://cairographics.org/releases/cairo-${cairo_version}.tar.gz
pango_url=http://ftp.gnome.org/pub/GNOME/sources/pango/${pango_version%.*}/pango-${pango_version}.tar.xz
atk_url=http://ftp.gnome.org/pub/GNOME/sources/atk/${atk_version%.*}/atk-${atk_version}.tar.xz
gtk__url=http://ftp.gnome.org/pub/gnome/sources/gtk+/${gtk__version%.*}/gtk+-${gtk__version}.tar.xz
cwd=$(pwd)
root_dir=$(mktemp -d)
cd $root_dir
if test -z $TMPDIR; then
TMPDIR=/tmp/
fi
make_flags=-j12
build() {
name=$1
shift
pkg=$(echo $name | tr '+-' '__')
version=$(eval echo \$${pkg}_version)
url=$(eval echo \$${pkg}_url)
wget -c -P $TMPDIR $url
tar -axf $TMPDIR/$name-$version.tar.*
mkdir -p build/$name
cd build/$name
eval ../../$name-$version/configure --disable-static $* $configure_args
make $make_flags
make install-strip DESTDIR=$root_dir/gtk3
find $root_dir/gtk3 -name \*.la -delete
cd ../..
}
case "$1" in
32)
configure_args='--host=i686-pc-linux --build=i686-pc-linux CC="gcc -m32" CXX="g++ -m32"'
lib=lib
;;
*)
configure_args=
lib=lib64
;;
esac
export PKG_CONFIG_LIBDIR=/usr/$lib/pkgconfig:/usr/share/pkgconfig
# The pkg-config version in the mock images is buggy is how it handles
# PKG_CONFIG_SYSROOT_DIR. So we need our own.
build pkg-config
ln -sf /usr/include $root_dir/gtk3/usr/
ln -sf /usr/$lib $root_dir/gtk3/usr/
if [ "$lib" = lib64 ]; then
ln -s lib $root_dir/gtk3/usr/local/lib64
fi
export PKG_CONFIG_PATH=$root_dir/gtk3/usr/local/lib/pkgconfig
export PKG_CONFIG_SYSROOT_DIR=$root_dir/gtk3
export LD_LIBRARY_PATH=$root_dir/gtk3/usr/local/lib
export PATH=$root_dir/gtk3/usr/local/bin:${PATH}
build fontconfig
build libffi
build glib
build gdk-pixbuf --without-libtiff
build pixman --disable-gtk
build cairo --enable-tee
build pango
build atk
make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
build gtk+
rm -rf $root_dir/gtk3/usr/local/share/gtk-doc
rm -rf $root_dir/gtk3/usr/local/share/locale
cd $cwd
tar -C $root_dir -Jcf gtk3.tar.xz gtk3

View File

@ -8,6 +8,11 @@ MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
# Hack to make this file available as a resource:// URI.
TESTING_JS_MODULES += [
'tests/mochitest/resource_test_file.html',
]
XPIDL_SOURCES += [
'nsIAddonPolicyService.idl',
'nsIDomainPolicy.idl',

View File

@ -11,7 +11,7 @@
* This interface allows the security manager to query custom per-addon security
* policy.
*/
[scriptable,uuid(fedf126c-988e-42df-82c9-f2ac99cd65f3)]
[scriptable,uuid(8a034ef9-9d14-4c5d-8319-06c1ab574baa)]
interface nsIAddonPolicyService : nsISupports
{
/**
@ -19,4 +19,14 @@ interface nsIAddonPolicyService : nsISupports
* data from |aURI|.
*/
boolean addonMayLoadURI(in AString aAddonId, in nsIURI aURI);
/**
* Returns true if a given extension:// URI is web-accessible.
*/
boolean extensionURILoadableByAnyone(in nsIURI aURI);
/**
* Maps an extension URI to the ID of the addon it belongs to.
*/
AString extensionURIToAddonId(in nsIURI aURI);
};

View File

@ -360,6 +360,20 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
return GetChannelURIPrincipal(aChannel, aPrincipal);
}
nsresult
nsScriptSecurityManager::MaybeSetAddonIdFromURI(OriginAttributes& aAttrs, nsIURI* aURI)
{
nsAutoCString scheme;
nsresult rv = aURI->GetScheme(scheme);
NS_ENSURE_SUCCESS(rv, rv);
if (scheme.EqualsLiteral("moz-extension") && GetAddonPolicyService()) {
rv = GetAddonPolicyService()->ExtensionURIToAddonId(aURI, aAttrs.mAddonId);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
/* The principal of the URI that this channel is loading. This is never
* affected by things like sandboxed loads, or loads where we forcefully
* inherit the principal. Think of this as the principal of the server
@ -391,6 +405,8 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
}
OriginAttributes attrs(UNKNOWN_APP_ID, false);
rv = MaybeSetAddonIdFromURI(attrs, uri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
@ -745,6 +761,16 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
// the methods that work on chains of nested URIs and they will only look
// at the flags for our one URI.
// Special case: moz-extension has a whitelist of URIs that are loadable by
// anyone.
if (targetScheme.EqualsLiteral("moz-extension") && GetAddonPolicyService()) {
bool loadable = false;
rv = GetAddonPolicyService()->ExtensionURILoadableByAnyone(targetBaseURI, &loadable);
if (NS_SUCCEEDED(rv) && loadable) {
return NS_OK;
}
}
// Check for system target URI
rv = DenyAccessIfURIHasFlags(targetBaseURI,
nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);
@ -1087,6 +1113,8 @@ nsScriptSecurityManager::
OriginAttributes attrs;
aLoadContext->GetAppId(&attrs.mAppId);
aLoadContext->GetIsInBrowserElement(&attrs.mInBrowser);
nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
@ -1099,6 +1127,8 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
{
// XXXbholley - Make this more general in bug 1165466.
OriginAttributes attrs(aDocShell->GetAppId(), aDocShell->GetIsInBrowserElement());
nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;

View File

@ -8,10 +8,15 @@
#define nsScriptSecurityManager_h__
#include "nsIScriptSecurityManager.h"
#include "nsIAddonPolicyService.h"
#include "mozilla/Maybe.h"
#include "nsIAddonPolicyService.h"
#include "nsIPrincipal.h"
#include "nsCOMPtr.h"
#include "nsIChannelEventSink.h"
#include "nsIObserver.h"
#include "nsServiceManagerUtils.h"
#include "plstr.h"
#include "js/TypeDecls.h"
@ -115,6 +120,9 @@ private:
inline void
AddSitesToFileURIWhitelist(const nsCString& aSiteList);
// If aURI is a moz-extension:// URI, set mAddonId to the associated addon.
nsresult MaybeSetAddonIdFromURI(mozilla::OriginAttributes& aAttrs, nsIURI* aURI);
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
bool mPrefInitialized;
bool mIsJavaScriptEnabled;
@ -124,6 +132,17 @@ private:
// policy machinery will be removed soon.
nsCOMPtr<nsIDomainPolicy> mDomainPolicy;
// Cached addon policy service. We can't generate this in Init() because
// that's too early to get a service.
mozilla::Maybe<nsCOMPtr<nsIAddonPolicyService>> mAddonPolicyService;
nsIAddonPolicyService* GetAddonPolicyService()
{
if (mAddonPolicyService.isNothing()) {
mAddonPolicyService.emplace(do_GetService("@mozilla.org/addons/policy-service;1"));
}
return mAddonPolicyService.ref();
}
static bool sStrictFileOriginPolicy;
static nsIIOService *sIOService;

View File

@ -11,3 +11,5 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
[test_bug423375.html]
[test_bug470804.html]
[test_disallowInheritPrincipal.html]
[test_extensionURL.html]
skip-if = (os == 'android' || buildapp == 'b2g') # Bug 1185773 for android, nonsensical on b2g

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html><head><title>resource test file</title></head><body></body></html>

View File

@ -0,0 +1,144 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1161831</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1161831 **/
SimpleTest.waitForExplicitFinish();
var aps = SpecialPowers.Cc["@mozilla.org/addons/policy-service;1"]
.getService(SpecialPowers.Ci.nsIAddonPolicyService).wrappedJSObject;
var oldLoadCallback = aps.setExtensionURILoadCallback(null);
var oldMapCallback = aps.setExtensionURIToAddonIdCallback(null);
var resourceHandler = SpecialPowers.Services.io.getProtocolHandler("resource")
.QueryInterface(SpecialPowers.Ci.nsISubstitutingProtocolHandler);
var extensionHandler = SpecialPowers.Services.io.getProtocolHandler("moz-extension")
.QueryInterface(SpecialPowers.Ci.nsISubstitutingProtocolHandler);
SimpleTest.registerCleanupFunction(function() {
extensionHandler.setSubstitution('cherise', null);
extensionHandler.setSubstitution('liebchen', null);
aps.setExtensionURILoadCallback(oldLoadCallback);
aps.setExtensionURIToAddonIdCallback(oldMapCallback);
});
addLoadEvent(function() {
// First, get a file:// URI to something - open to suggestions on how to do
// this more easily.
var resURI = SpecialPowers.Services.io.newURI('resource://testing-common/resource_test_file.html', null, null);
var filePath = resourceHandler.resolveURI(resURI);
ok(filePath.startsWith('file://'), 'resource:// URI resolves where we expect: ' + filePath);
var fileURI = SpecialPowers.Services.io.newURI(filePath, null, null);
// Register a moz-extension:// URI.
extensionHandler.setSubstitution('cherise', fileURI);
// Alias the above.
extensionHandler.setSubstitution('liebchen', SpecialPowers.Services.io.newURI('moz-extension://cherise', null, null));
//
// Make sure that non-file:// URIs don't work.
//
// resource://
try {
extensionHandler.setSubstitution('interdit', resURI);
ok(false, "Should have thrown for mapping moz-extension to resource");
} catch (e) {
ok(true, "Threw correctly: " + e);
}
// chrome://
try {
var chromeURI = SpecialPowers.Services.io.newURI('chrome://global/content/mozilla.xhtml', null, null);
extensionHandler.setSubstitution('verboten', chromeURI);
ok(false, "Should have thrown for mapping moz-extension to chrome");
} catch (e) {
ok(true, "Threw correctly: " + e);
}
function navigateWithLocation(ifr, url) { ifr.contentWindow.location = url; }
function navigateWithSrc(ifr, url) { ifr.setAttribute('src', url); }
function navigateFromChromeWithLocation(ifr, url) { SpecialPowers.wrap(ifr).contentWindow.location = url; }
function navigateFromChromeWithWebNav(ifr, url) {
SpecialPowers.wrap(ifr).contentWindow
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
.loadURI(url, 0, null, null, null);
}
function setWhitelistCallback(rgxp) {
var cb = SpecialPowers.wrapCallback(function(uri) { return rgxp.test(uri.spec); });
aps.setExtensionURILoadCallback(cb);
}
aps.setExtensionURIToAddonIdCallback(SpecialPowers.wrapCallback(function (uri) { return 'imaginaryaddon-' + uri.host[0]; }));
function testLoad(url, navigate, shouldThrow) {
var ifr = document.createElement('iframe');
var p = new Promise(function(resolve, reject) {
ifr.onload = function() {
ok(true, 'Loaded ' + url);
var prin = SpecialPowers.wrap(ifr.contentWindow).document.nodePrincipal;
is(prin.originNoSuffix, url, 'Principal origin is correct: ' + url);
is(prin.originAttributes.addonId, 'imaginaryaddon-' + url[url.indexOf('/') + 2], 'addonId is correct');
is(SpecialPowers.wrap(ifr.contentWindow).document.title, 'resource test file',
'document looks right');
ifr.remove();
resolve();
};
document.body.appendChild(ifr);
var threw = false;
try {
navigate(ifr, url);
} catch (e) {
ifr.remove();
threw = true;
ok(/denied|insecure/.test(e), "exceiton correct: " + e);
}
is(threw, !!shouldThrow, "Correct throwing behavior for: " + url);
!threw || resolve();
});
return p;
}
//
// Perform some loads and make sure they work correctly.
//
testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithLocation)()
.then(testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithWebNav))
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation, /* shouldThrow = */ true))
.then(setWhitelistCallback.bind(null, /cherise/))
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation))
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation, /* shouldThrow = */ true))
.then(setWhitelistCallback.bind(null, /cherise|liebchen/))
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation))
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithSrc))
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithSrc))
.then(SimpleTest.finish.bind(SimpleTest),
function(e) { ok(false, "rejected promise: " + e); SimpleTest.finish() }
);
});
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1161831">Mozilla Bug 1161831</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -39,14 +39,16 @@ struct ChromePackage
}
};
struct ResourceMapping
struct SubstitutionMapping
{
nsCString resource;
nsCString scheme;
nsCString path;
SerializedURI resolvedURI;
bool operator ==(const ResourceMapping& rhs) const
bool operator ==(const SubstitutionMapping& rhs) const
{
return resource.Equals(rhs.resource) &&
return scheme.Equals(rhs.scheme) &&
path.Equals(rhs.path) &&
resolvedURI == rhs.resolvedURI;
}
};
@ -134,24 +136,27 @@ struct ParamTraits<ChromePackage>
};
template <>
struct ParamTraits<ResourceMapping>
struct ParamTraits<SubstitutionMapping>
{
typedef ResourceMapping paramType;
typedef SubstitutionMapping paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.resource);
WriteParam(aMsg, aParam.scheme);
WriteParam(aMsg, aParam.path);
WriteParam(aMsg, aParam.resolvedURI);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
nsCString resource;
nsCString scheme, path;
SerializedURI resolvedURI;
if (ReadParam(aMsg, aIter, &resource) &&
if (ReadParam(aMsg, aIter, &scheme) &&
ReadParam(aMsg, aIter, &path) &&
ReadParam(aMsg, aIter, &resolvedURI)) {
aResult->resource = resource;
aResult->scheme = scheme;
aResult->path = path;
aResult->resolvedURI = resolvedURI;
return true;
}
@ -160,7 +165,9 @@ struct ParamTraits<ResourceMapping>
static void Log(const paramType& aParam, std::wstring* aLog)
{
aLog->append(StringPrintf(L"[%s, %s, %u]", aParam.resource.get(),
aLog->append(StringPrintf(L"[%s://%s, %s, %u]",
aParam.scheme.get(),
aParam.path.get(),
aParam.resolvedURI.spec.get()));
}
};

View File

@ -445,7 +445,7 @@ nsChromeRegistryChrome::SendRegisteredChrome(
mozilla::dom::PContentParent* aParent)
{
InfallibleTArray<ChromePackage> packages;
InfallibleTArray<ResourceMapping> resources;
InfallibleTArray<SubstitutionMapping> resources;
InfallibleTArray<OverrideMapping> overrides;
EnumerationArgs args = {

View File

@ -17,7 +17,7 @@ nsChromeRegistryContent::nsChromeRegistryContent()
void
nsChromeRegistryContent::RegisterRemoteChrome(
const InfallibleTArray<ChromePackage>& aPackages,
const InfallibleTArray<ResourceMapping>& aResources,
const InfallibleTArray<SubstitutionMapping>& aSubstitutions,
const InfallibleTArray<OverrideMapping>& aOverrides,
const nsACString& aLocale,
bool aReset)
@ -36,9 +36,9 @@ nsChromeRegistryContent::RegisterRemoteChrome(
RegisterPackage(aPackages[i]);
}
for (uint32_t i = aResources.Length(); i > 0; ) {
for (uint32_t i = aSubstitutions.Length(); i > 0; ) {
--i;
RegisterResource(aResources[i]);
RegisterSubstitution(aSubstitutions[i]);
}
for (uint32_t i = aOverrides.Length(); i > 0; ) {
@ -94,32 +94,32 @@ nsChromeRegistryContent::RegisterPackage(const ChromePackage& aPackage)
}
void
nsChromeRegistryContent::RegisterResource(const ResourceMapping& aResource)
nsChromeRegistryContent::RegisterSubstitution(const SubstitutionMapping& aSubstitution)
{
nsCOMPtr<nsIIOService> io (do_GetIOService());
if (!io)
return;
nsCOMPtr<nsIProtocolHandler> ph;
nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
nsresult rv = io->GetProtocolHandler(aSubstitution.scheme.get(), getter_AddRefs(ph));
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIResProtocolHandler> rph (do_QueryInterface(ph));
if (!rph)
nsCOMPtr<nsISubstitutingProtocolHandler> sph (do_QueryInterface(ph));
if (!sph)
return;
nsCOMPtr<nsIURI> resolvedURI;
if (aResource.resolvedURI.spec.Length()) {
if (aSubstitution.resolvedURI.spec.Length()) {
nsresult rv = NS_NewURI(getter_AddRefs(resolvedURI),
aResource.resolvedURI.spec,
aResource.resolvedURI.charset.get(),
aSubstitution.resolvedURI.spec,
aSubstitution.resolvedURI.charset.get(),
nullptr, io);
if (NS_FAILED(rv))
return;
}
rv = rph->SetSubstitution(aResource.resource, resolvedURI);
rv = sph->SetSubstitution(aSubstitution.path, resolvedURI);
if (NS_FAILED(rv))
return;
}

View File

@ -10,7 +10,7 @@
#include "nsClassHashtable.h"
struct ChromePackage;
struct ResourceMapping;
struct SubstitutionMapping;
struct OverrideMapping;
class nsChromeRegistryContent : public nsChromeRegistry
@ -19,7 +19,7 @@ class nsChromeRegistryContent : public nsChromeRegistry
nsChromeRegistryContent();
void RegisterRemoteChrome(const InfallibleTArray<ChromePackage>& aPackages,
const InfallibleTArray<ResourceMapping>& aResources,
const InfallibleTArray<SubstitutionMapping>& aResources,
const InfallibleTArray<OverrideMapping>& aOverrides,
const nsACString& aLocale,
bool aReset);
@ -41,7 +41,7 @@ class nsChromeRegistryContent : public nsChromeRegistry
void RegisterPackage(const ChromePackage& aPackage);
void RegisterOverride(const OverrideMapping& aOverride);
void RegisterResource(const ResourceMapping& aResource);
void RegisterSubstitution(const SubstitutionMapping& aResource);
private:
struct PackageEntry

View File

@ -300,6 +300,7 @@ GK_ATOM(digit, "digit")
GK_ATOM(dir, "dir")
GK_ATOM(dirAutoSetBy, "dirAutoSetBy")
GK_ATOM(directionality, "directionality")
GK_ATOM(directory, "directory")
GK_ATOM(disableOutputEscaping, "disable-output-escaping")
GK_ATOM(disabled, "disabled")
GK_ATOM(disablehistory, "disablehistory")
@ -2291,7 +2292,6 @@ GK_ATOM(containerRelevant, "container-relevant")
GK_ATOM(contentinfo, "contentinfo")
GK_ATOM(cycles, "cycles")
GK_ATOM(datatable, "datatable")
GK_ATOM(directory, "directory")
GK_ATOM(eventFromInput, "event-from-input")
GK_ATOM(grammar, "grammar")
GK_ATOM(gridcell, "gridcell")

View File

@ -3778,10 +3778,10 @@ nsGlobalWindow::GetParent(ErrorResult& aError)
NS_IMETHODIMP
nsGlobalWindow::GetScriptableParent(nsIDOMWindow** aParent)
{
FORWARD_TO_INNER(GetScriptableParent, (aParent), NS_ERROR_UNEXPECTED);
FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_UNEXPECTED);
ErrorResult rv;
nsCOMPtr<nsIDOMWindow> parent = GetParent(rv);
nsCOMPtr<nsIDOMWindow> parent = GetParentOuter(rv);
parent.forget(aParent);
return rv.StealNSResult();

View File

@ -13,7 +13,7 @@ namespace mozilla {
void
WebGL2Context::DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLintptr offset)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("drawRangeElements: Not Implemented.");
}
} // namespace mozilla

View File

@ -333,13 +333,13 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
void
WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("framebufferTextureLayer: Not Implemented.");
}
void
WebGL2Context::GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat, GLenum pname, JS::MutableHandleValue retval)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("getInternalformatParameter: Not Implemented.");
}
// Map attachments intended for the default buffer, to attachments for a non-

View File

@ -431,7 +431,7 @@ WebGL2Context::TexSubImage3D(GLenum target, GLint level,
GLenum format, GLenum type, dom::ImageData* data,
ErrorResult& rv)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("texSubImage3D: Not implemented.");
}
void
@ -439,7 +439,7 @@ WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("copyTexSubImage3D: Not implemented.");
}
void
@ -447,7 +447,7 @@ WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalf
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, const dom::ArrayBufferView& data)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("compressedTexImage3D: Not implemented.");
}
void
@ -455,7 +455,7 @@ WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const dom::ArrayBufferView& data)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("compressedTexSubImage3D: Not implemented.");
}
JS::Value

View File

@ -16,66 +16,6 @@
namespace mozilla {
typedef union { GLint i; GLfloat f; GLuint u; } fi_t;
static inline
GLfloat PuntToFloat(GLint i)
{
fi_t tmp;
tmp.i = i;
return tmp.f;
}
static inline
GLfloat PuntToFloat(GLuint u)
{
fi_t tmp;
tmp.u = u;
return tmp.f;
}
bool
WebGL2Context::ValidateAttribPointerType(bool integerMode, GLenum type,
GLsizei* out_alignment, const char* info)
{
MOZ_ASSERT(out_alignment);
switch (type) {
case LOCAL_GL_BYTE:
case LOCAL_GL_UNSIGNED_BYTE:
*out_alignment = 1;
return true;
case LOCAL_GL_SHORT:
case LOCAL_GL_UNSIGNED_SHORT:
*out_alignment = 2;
return true;
case LOCAL_GL_INT:
case LOCAL_GL_UNSIGNED_INT:
*out_alignment = 4;
return true;
}
if (!integerMode) {
switch (type) {
case LOCAL_GL_HALF_FLOAT:
*out_alignment = 2;
return true;
case LOCAL_GL_FLOAT:
case LOCAL_GL_FIXED:
case LOCAL_GL_INT_2_10_10_10_REV:
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
*out_alignment = 4;
return true;
}
}
ErrorInvalidEnum("%s: invalid enum value 0x%x", info, type);
return false;
}
bool
WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*info*/)
{
@ -83,42 +23,7 @@ WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*
}
// -------------------------------------------------------------------------
// Uniforms and attributes
void
WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride,
GLintptr offset)
{
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribIPointer"))
return;
if (!ValidateAttribPointer(true, index, size, type, LOCAL_GL_FALSE, stride, offset,
"vertexAttribIPointer"))
{
return;
}
MOZ_ASSERT(mBoundVertexArray);
mBoundVertexArray->EnsureAttrib(index);
InvalidateBufferFetching();
WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
vd.buf = mBoundArrayBuffer;
vd.stride = stride;
vd.size = size;
vd.byteOffset = offset;
vd.type = type;
vd.normalized = false;
vd.integer = true;
MakeContextCurrent();
gl->fVertexAttribIPointer(index, size, type, stride, reinterpret_cast<void*>(offset));
}
// Uniforms
void
WebGL2Context::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
@ -339,85 +244,6 @@ WebGL2Context::UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose
gl->fUniformMatrix4x3fv(rawLoc, numElementsToUpload, transpose, data);
}
void
WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
{
if (IsContextLost())
return;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4i(index, x, y, z, w);
} else {
mVertexAttrib0Vector[0] = PuntToFloat(x);
mVertexAttrib0Vector[1] = PuntToFloat(y);
mVertexAttrib0Vector[2] = PuntToFloat(z);
mVertexAttrib0Vector[3] = PuntToFloat(w);
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, size_t length, const GLint* v)
{
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
return;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4iv(index, v);
} else {
mVertexAttrib0Vector[0] = PuntToFloat(v[0]);
mVertexAttrib0Vector[1] = PuntToFloat(v[1]);
mVertexAttrib0Vector[2] = PuntToFloat(v[2]);
mVertexAttrib0Vector[3] = PuntToFloat(v[3]);
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, const dom::Sequence<GLint>& v)
{
VertexAttribI4iv(index, v.Length(), v.Elements());
}
void
WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
{
if (IsContextLost())
return;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4ui(index, x, y, z, w);
} else {
mVertexAttrib0Vector[0] = PuntToFloat(x);
mVertexAttrib0Vector[1] = PuntToFloat(y);
mVertexAttrib0Vector[2] = PuntToFloat(z);
mVertexAttrib0Vector[3] = PuntToFloat(w);
}
}
void
WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
{
if (IsContextLost())
return;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4uiv(index, v);
} else {
mVertexAttrib0Vector[0] = PuntToFloat(v[0]);
mVertexAttrib0Vector[1] = PuntToFloat(v[1]);
mVertexAttrib0Vector[2] = PuntToFloat(v[2]);
mVertexAttrib0Vector[3] = PuntToFloat(v[3]);
}
}
void
WebGL2Context::VertexAttribI4uiv(GLuint index, const dom::Sequence<GLuint>& v)
{
VertexAttribI4uiv(index, v.Length(), v.Elements());
}
// -------------------------------------------------------------------------
// Uniform Buffer Objects and Transform Feedback Buffers

View File

@ -0,0 +1,199 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGL2Context.h"
#include "GLContext.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
#include "mozilla/Casting.h"
namespace mozilla {
bool
WebGL2Context::ValidateAttribPointerType(bool integerMode, GLenum type,
GLsizei* out_alignment, const char* info)
{
MOZ_ASSERT(out_alignment);
switch (type) {
case LOCAL_GL_BYTE:
case LOCAL_GL_UNSIGNED_BYTE:
*out_alignment = 1;
return true;
case LOCAL_GL_SHORT:
case LOCAL_GL_UNSIGNED_SHORT:
*out_alignment = 2;
return true;
case LOCAL_GL_INT:
case LOCAL_GL_UNSIGNED_INT:
*out_alignment = 4;
return true;
}
if (!integerMode) {
switch (type) {
case LOCAL_GL_HALF_FLOAT:
*out_alignment = 2;
return true;
case LOCAL_GL_FLOAT:
case LOCAL_GL_FIXED:
case LOCAL_GL_INT_2_10_10_10_REV:
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
*out_alignment = 4;
return true;
}
}
ErrorInvalidEnum("%s: invalid enum value 0x%x", info, type);
return false;
}
// -------------------------------------------------------------------------
// Vertex Attributes
void
WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride,
GLintptr offset)
{
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribIPointer"))
return;
if (!ValidateAttribPointer(true, index, size, type, LOCAL_GL_FALSE, stride, offset,
"vertexAttribIPointer"))
{
return;
}
MOZ_ASSERT(mBoundVertexArray);
mBoundVertexArray->EnsureAttrib(index);
InvalidateBufferFetching();
WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
vd.buf = mBoundArrayBuffer;
vd.stride = stride;
vd.size = size;
vd.byteOffset = offset;
vd.type = type;
vd.normalized = false;
vd.integer = true;
MakeContextCurrent();
gl->fVertexAttribIPointer(index, size, type, stride, reinterpret_cast<void*>(offset));
}
void
WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
{
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribI4i"))
return;
mVertexAttribType[index] = LOCAL_GL_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4i(index, x, y, z, w);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(x);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(y);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(z);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(w);
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, size_t length, const GLint* v)
{
if (!ValidateAttribIndex(index, "vertexAttribI4iv"))
return;
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
return;
mVertexAttribType[index] = LOCAL_GL_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4iv(index, v);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(v[0]);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(v[1]);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(v[2]);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(v[3]);
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, const dom::Sequence<GLint>& v)
{
VertexAttribI4iv(index, v.Length(), v.Elements());
}
void
WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
{
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribI4ui"))
return;
mVertexAttribType[index] = LOCAL_GL_UNSIGNED_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4ui(index, x, y, z, w);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(x);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(y);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(z);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(w);
}
}
void
WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
{
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))
return;
mVertexAttribType[index] = LOCAL_GL_UNSIGNED_INT;
if (index || gl->IsGLES()) {
MakeContextCurrent();
gl->fVertexAttribI4uiv(index, v);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(v[0]);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(v[1]);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(v[2]);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(v[3]);
}
}
void
WebGL2Context::VertexAttribI4uiv(GLuint index, const dom::Sequence<GLuint>& v)
{
VertexAttribI4uiv(index, v.Length(), v.Elements());
}
} // namespace mozilla

View File

@ -901,6 +901,11 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
}
// increment the generation number - Do this early because later
// in CreateOffscreenGL(), "default" objects are created that will
// pick up the old generation.
++mGeneration;
// Get some prefs for some preferred/overriden things
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
@ -949,9 +954,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
mResetLayer = true;
mOptionsFrozen = true;
// increment the generation number
++mGeneration;
// Update our internal stuff:
if (gl->WorkAroundDriverBugs() && gl->IsANGLE()) {
if (!mOptions.alpha && gl->Caps().alpha)

View File

@ -1461,12 +1461,21 @@ protected:
UniquePtr<FakeBlackTexture>& opaqueTextureScopedPtr,
UniquePtr<FakeBlackTexture>& transparentTextureScopedPtr);
// Generic Vertex Attributes
UniquePtr<GLenum[]> mVertexAttribType;
GLfloat mVertexAttrib0Vector[4];
GLfloat mFakeVertexAttrib0BufferObjectVector[4];
size_t mFakeVertexAttrib0BufferObjectSize;
GLuint mFakeVertexAttrib0BufferObject;
WebGLVertexAttrib0Status mFakeVertexAttrib0BufferStatus;
void GetVertexAttribFloat(GLuint index, GLfloat* out_result);
void GetVertexAttribInt(GLuint index, GLint* out_result);
void GetVertexAttribUint(GLuint index, GLuint* out_result);
JSObject* GetVertexAttribFloat32Array(JSContext* cx, GLuint index);
JSObject* GetVertexAttribInt32Array(JSContext* cx, GLuint index);
JSObject* GetVertexAttribUint32Array(JSContext* cx, GLuint index);
GLint mStencilRefFront;
GLint mStencilRefBack;
GLuint mStencilValueMaskFront;

View File

@ -159,6 +159,20 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
case WebGLExtensionID::WEBGL_debug_renderer_info:
{
bool isEnabled = true;
#ifdef RELEASE_BUILD
// Keep this disabled on Release and Beta for now. (see bug 1171228)
isEnabled = false;
#endif
if (Preferences::GetBool("webgl.disable-debug-renderer-info", false))
isEnabled = false;
return isEnabled;
}
case WebGLExtensionID::WEBGL_depth_texture:
// WEBGL_depth_texture supports DEPTH_STENCIL textures
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))

View File

@ -4,16 +4,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLContextUtils.h"
#include "WebGLBuffer.h"
#include "WebGLShader.h"
#include "WebGLProgram.h"
#include "WebGLFramebuffer.h"
#include "WebGLRenderbuffer.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
#include "GLContext.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/Preferences.h"
#include "nsString.h"
#include "WebGLBuffer.h"
#include "WebGLContextUtils.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
#include "WebGLRenderbuffer.h"
#include "WebGLShader.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
namespace mozilla {
@ -57,6 +60,18 @@ WebGLContext::Enable(GLenum cap)
gl->fEnable(cap);
}
static JS::Value
StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv)
{
JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
if (!jsStr) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return JS::NullValue();
}
return JS::StringValue(jsStr);
}
bool
WebGLContext::GetStencilBits(GLint* out_stencilBits)
{
@ -176,19 +191,47 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
// Privileged string params exposed by WEBGL_debug_renderer_info:
// Privileged string params exposed by WEBGL_debug_renderer_info.
// The privilege check is done in WebGLContext::IsExtensionSupported.
// So here we just have to check that the extension is enabled.
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
switch (pname) {
case UNMASKED_VENDOR_WEBGL:
case UNMASKED_RENDERER_WEBGL:
GLenum glstringname = LOCAL_GL_NONE;
if (pname == UNMASKED_VENDOR_WEBGL) {
glstringname = LOCAL_GL_VENDOR;
} else if (pname == UNMASKED_RENDERER_WEBGL) {
glstringname = LOCAL_GL_RENDERER;
{
const char* overridePref = nullptr;
GLenum driverEnum = LOCAL_GL_NONE;
switch (pname) {
case UNMASKED_RENDERER_WEBGL:
overridePref = "webgl.renderer-string-override";
driverEnum = LOCAL_GL_RENDERER;
break;
case UNMASKED_VENDOR_WEBGL:
overridePref = "webgl.vendor-string-override";
driverEnum = LOCAL_GL_VENDOR;
break;
default:
MOZ_CRASH("bad `pname`");
}
bool hasRetVal = false;
nsAutoString ret;
if (overridePref) {
nsresult res = Preferences::GetString(overridePref, &ret);
if (NS_SUCCEEDED(res) && ret.Length() > 0)
hasRetVal = true;
}
if (!hasRetVal) {
const char* chars = reinterpret_cast<const char*>(gl->fGetString(driverEnum));
ret = NS_ConvertASCIItoUTF16(chars);
hasRetVal = true;
}
return StringValue(cx, ret, rv);
}
const GLchar* string = (const GLchar*) gl->fGetString(glstringname);
return StringValue(cx, string, rv);
}
}

View File

@ -1941,7 +1941,9 @@ WebGLContext::InitAndValidateGL()
}
// Default value for all disabled vertex attributes is [0, 0, 0, 1]
mVertexAttribType = MakeUnique<GLenum[]>(mGLMaxVertexAttribs);
for (int32_t index = 0; index < mGLMaxVertexAttribs; ++index) {
mVertexAttribType[index] = LOCAL_GL_FLOAT;
VertexAttrib4f(index, 0, 0, 0, 1);
}

View File

@ -16,8 +16,72 @@
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
#include "mozilla/Casting.h"
namespace mozilla {
void
WebGLContext::GetVertexAttribFloat(GLuint index, GLfloat* out_result)
{
if (index) {
gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, out_result);
} else {
out_result[0] = mVertexAttrib0Vector[0];
out_result[1] = mVertexAttrib0Vector[1];
out_result[2] = mVertexAttrib0Vector[2];
out_result[3] = mVertexAttrib0Vector[3];
}
}
void
WebGLContext::GetVertexAttribInt(GLuint index, GLint* out_result)
{
if (index) {
gl->fGetVertexAttribIiv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, out_result);
} else {
out_result[0] = BitwiseCast<GLint>(mVertexAttrib0Vector[0]);
out_result[1] = BitwiseCast<GLint>(mVertexAttrib0Vector[1]);
out_result[2] = BitwiseCast<GLint>(mVertexAttrib0Vector[2]);
out_result[3] = BitwiseCast<GLint>(mVertexAttrib0Vector[3]);
}
}
void
WebGLContext::GetVertexAttribUint(GLuint index, GLuint* out_result)
{
if (index) {
gl->fGetVertexAttribIuiv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, out_result);
} else {
out_result[0] = BitwiseCast<GLuint>(mVertexAttrib0Vector[0]);
out_result[1] = BitwiseCast<GLuint>(mVertexAttrib0Vector[1]);
out_result[2] = BitwiseCast<GLuint>(mVertexAttrib0Vector[2]);
out_result[3] = BitwiseCast<GLuint>(mVertexAttrib0Vector[3]);
}
}
JSObject*
WebGLContext::GetVertexAttribFloat32Array(JSContext* cx, GLuint index)
{
GLfloat attrib[4];
GetVertexAttribFloat(index, &attrib[0]);
return dom::Float32Array::Create(cx, this, 4, attrib);
}
JSObject*
WebGLContext::GetVertexAttribInt32Array(JSContext* cx, GLuint index)
{
GLint attrib[4];
GetVertexAttribInt(index, &attrib[0]);
return dom::Int32Array::Create(cx, this, 4, attrib);
}
JSObject*
WebGLContext::GetVertexAttribUint32Array(JSContext* cx, GLuint index) {
GLuint attrib[4];
GetVertexAttribUint(index, &attrib[0]);
return dom::Uint32Array::Create(cx, this, 4, attrib);
}
void
WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0)
{
@ -27,6 +91,8 @@ WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0)
if (!ValidateAttribIndex(index, "vertexAttrib1f"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
@ -50,6 +116,8 @@ WebGLContext::VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1)
if (!ValidateAttribIndex(index, "vertexAttrib2f"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
@ -73,6 +141,8 @@ WebGLContext::VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2)
if (!ValidateAttribIndex(index, "vertexAttrib3f"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
@ -97,6 +167,8 @@ WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
if (!ValidateAttribIndex(index, "vertexAttrib4f"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
@ -122,6 +194,8 @@ WebGLContext::VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
if (!ValidateAttribIndex(index, "vertexAttrib1fv"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
gl->fVertexAttrib1fv(index, ptr);
@ -145,6 +219,8 @@ WebGLContext::VertexAttrib2fv_base(GLuint index, uint32_t arrayLength,
if (!ValidateAttribIndex(index, "vertexAttrib2fv"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
gl->fVertexAttrib2fv(index, ptr);
@ -168,6 +244,8 @@ WebGLContext::VertexAttrib3fv_base(GLuint index, uint32_t arrayLength,
if (!ValidateAttribIndex(index, "vertexAttrib3fv"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
gl->fVertexAttrib3fv(index, ptr);
@ -191,6 +269,8 @@ WebGLContext::VertexAttrib4fv_base(GLuint index, uint32_t arrayLength,
if (!ValidateAttribIndex(index, "vertexAttrib4fv"))
return;
mVertexAttribType[index] = LOCAL_GL_FLOAT;
MakeContextCurrent();
if (index) {
gl->fVertexAttrib4fv(index, ptr);
@ -259,71 +339,59 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
MakeContextCurrent();
switch (pname) {
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].buf.get(), rv);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
return JS::Int32Value(mBoundVertexArray->mAttribs[index].stride);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
if (!mBoundVertexArray->mAttribs[index].enabled)
return JS::Int32Value(4);
return JS::Int32Value(mBoundVertexArray->mAttribs[index].size);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
if (!mBoundVertexArray->mAttribs[index].enabled)
return JS::NumberValue(uint32_t(LOCAL_GL_FLOAT));
return JS::NumberValue(uint32_t(mBoundVertexArray->mAttribs[index].type));
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
if (IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
break;
case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
{
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].buf.get(), rv);
}
JS::RootedObject obj(cx);
switch (mVertexAttribType[index]) {
case LOCAL_GL_FLOAT:
obj = GetVertexAttribFloat32Array(cx, index);
break;
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
{
return JS::Int32Value(mBoundVertexArray->mAttribs[index].stride);
}
case LOCAL_GL_INT:
obj = GetVertexAttribInt32Array(cx, index);
break;
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
{
if (!mBoundVertexArray->mAttribs[index].enabled)
return JS::Int32Value(4);
return JS::Int32Value(mBoundVertexArray->mAttribs[index].size);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
{
if (!mBoundVertexArray->mAttribs[index].enabled)
return JS::NumberValue(uint32_t(LOCAL_GL_FLOAT));
return JS::NumberValue(uint32_t(mBoundVertexArray->mAttribs[index].type));
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
{
if (IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
{
return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
case LOCAL_GL_UNSIGNED_INT:
obj = GetVertexAttribUint32Array(cx, index);
break;
}
break;
}
case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
{
GLfloat vec[4] = {0, 0, 0, 1};
if (index) {
gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, &vec[0]);
} else {
vec[0] = mVertexAttrib0Vector[0];
vec[1] = mVertexAttrib0Vector[1];
vec[2] = mVertexAttrib0Vector[2];
vec[3] = mVertexAttrib0Vector[3];
}
JSObject* obj = dom::Float32Array::Create(cx, this, 4, vec);
if (!obj) {
if (!obj)
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
}
return JS::ObjectOrNullValue(obj);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
{
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].enabled);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].enabled);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
{
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].normalized);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].normalized);
default:
break;
default:
break;
}
ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);

View File

@ -67,6 +67,7 @@ UNIFIED_SOURCES += [
'WebGL2ContextTransformFeedback.cpp',
'WebGL2ContextUniforms.cpp',
'WebGL2ContextVAOs.cpp',
'WebGL2ContextVertices.cpp',
'WebGLActiveInfo.cpp',
'WebGLBuffer.cpp',
'WebGLContext.cpp',

View File

@ -2,6 +2,12 @@
<html>
<script>
var Cu = parent.Components.utils;
Cu.import("resource://gre/modules/AppConstants.jsm");
// This gives us `AppConstants` in the global scope.
// We need this because we only expose debug_renderer_info #ifndef MOZ_RELEASE_BUILD.
// This should match AppConstants.RELEASE_BUILD.
// This file has the portion of the test_webgl_renderer_info chrome mochitest
// that has to run as non-chrome to check that this WebGL extension is not exposed to content
@ -28,30 +34,58 @@ function run() {
const UNMASKED_VENDOR_WEBGL = 0x9245;
const UNMASKED_RENDERER_WEBGL = 0x9246;
var shouldHaveRendererInfo = false;
if (!AppConstants.RELEASE_BUILD)
shouldHaveRendererInfo = true;
var canvas = document.createElement("canvas");
var gl = canvas.getContext("experimental-webgl");
ok(!gl.getError(), "getError on newly created WebGL context should return NO_ERROR");
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_VENDOR_WEBGL without having enabled the WEBGL_debug_renderer_info extension");
"Should not be able to query UNMASKED_VENDOR_WEBGL without having enabled the"
+ " WEBGL_debug_renderer_info extension");
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_RENDERER_WEBGL without having enabled the WEBGL_debug_renderer_info extension");
"Should not be able to query UNMASKED_RENDERER_WEBGL without having enabled the"
+ " WEBGL_debug_renderer_info extension");
var exts = gl.getSupportedExtensions();
ok(exts.indexOf("WEBGL_debug_renderer_info") == -1,
"WEBGL_debug_renderer_info should not be listed by getSupportedExtensions in non-chrome contexts");
var debugRendererInfoExtension = gl.getExtension("WEBGL_debug_renderer_info");
ok(!debugRendererInfoExtension,
"WEBGL_debug_renderer_info should not be available through getExtension in non-chrome contexts");
if (shouldHaveRendererInfo) {
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in"
+ " non-chrome contexts on non-RELEASE_BUILDs");
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_VENDOR_WEBGL if enabling WEBGL_debug_renderer_info failed");
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_RENDERER_WEBGL if enabling WEBGL_debug_renderer_info failed");
var ext = gl.getExtension("WEBGL_debug_renderer_info");
ok(!!ext,
"WEBGL_debug_renderer_info should be available through getExtension in non-chrome"
+ " contexts on non-RELEASE_BUILDs");
ok(gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.NO_ERROR,
"Should be able to query UNMASKED_VENDOR_WEBGL if enabling"
+ " WEBGL_debug_renderer_info succeeded");
ok(gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.NO_ERROR,
"Should be able to query UNMASKED_RENDERER_WEBGL if enabling"
+ " WEBGL_debug_renderer_info succeeded");
} else {
ok(exts.indexOf("WEBGL_debug_renderer_info") == -1,
"WEBGL_debug_renderer_info should not be listed by getSupportedExtensions in"
+ " non-chrome contexts");
var ext = gl.getExtension("WEBGL_debug_renderer_info");
ok(!ext,
"WEBGL_debug_renderer_info should not be available through getExtension in"
+ " non-chrome contexts");
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_VENDOR_WEBGL if enabling"
+ " WEBGL_debug_renderer_info failed");
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_RENDERER_WEBGL if enabling"
+ " WEBGL_debug_renderer_info failed");
}
window.postMessage({allTestsFinished: true}, "*");
}
</script>
</html>
</html>

View File

@ -43,13 +43,13 @@ function checkChromeCase(canvas) {
var exts = gl.getSupportedExtensions();
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in chrome contexts");
var debugRendererInfoExtension = gl.getExtension("WEBGL_debug_renderer_info");
ok(debugRendererInfoExtension,
var ext = gl.getExtension("WEBGL_debug_renderer_info");
ok(ext,
"WEBGL_debug_renderer_info should be available through getExtension in chrome contexts");
ok(debugRendererInfoExtension.UNMASKED_VENDOR_WEBGL == UNMASKED_VENDOR_WEBGL,
ok(ext.UNMASKED_VENDOR_WEBGL == UNMASKED_VENDOR_WEBGL,
"UNMASKED_VENDOR_WEBGL has the correct value");
ok(debugRendererInfoExtension.UNMASKED_RENDERER_WEBGL == UNMASKED_RENDERER_WEBGL,
ok(ext.UNMASKED_RENDERER_WEBGL == UNMASKED_RENDERER_WEBGL,
"UNMASKED_RENDERER_WEBGL has the correct value");
ok(isNonEmptyString(gl.getParameter(UNMASKED_VENDOR_WEBGL)) && gl.getError() == gl.NO_ERROR,
@ -67,7 +67,7 @@ function main()
// Now run the non-chrome code to verify the security of this WebGL chrome-only extension.
var iframe = document.createElement("iframe");
iframe.src = "http://mochi.test:8888/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
iframe.src = "chrome://mochitests/content/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
iframe.onload = function () {

View File

@ -22,6 +22,7 @@ skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in
skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
[webgl-mochitest/test_noprog_draw.html]
[webgl-mochitest/test_privileged_exts.html]
[webgl-mochitest/test_renderer_strings.html]
[webgl-mochitest/test_texsubimage_float.html]
[webgl-mochitest/test_uninit_data.html]
[webgl-mochitest/test_webgl_available.html]

View File

@ -24,7 +24,7 @@ function TestExt(gl, name) {
}
// Privileged extensions:
TestExt(gl, 'WEBGL_debug_renderer_info');
TestExt(gl, 'WEBGL_debug_shaders');
})();
</script>

View File

@ -0,0 +1,98 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
function AssertError(gl, expected, info) {
var actual = gl.getError();
while (gl.getError()) {}
ok(actual == expected,
'For ' + info + ', expected 0x' + expected.toString(16) + ', got 0x'
+ actual.toString(16));
}
var gl;
var RENDERER_OVERRIDE = 'overridden renderer';
var VENDOR_OVERRIDE = 'overridden vendor';
function TestExt() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
AssertError(gl, 0, 'start of test');
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
ok(renderer,
'UNMASKED_RENDERER_WEBGL value should not be empty, was \'' + renderer + '\'');
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
ok(vendor, 'UNMASKED_VENDOR_WEBGL value should not be empty, was \'' + vendor + '\'');
var prefArrArr = [
['webgl.renderer-string-override', RENDERER_OVERRIDE],
['webgl.vendor-string-override', VENDOR_OVERRIDE],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestOverrides);
}
function TestOverrides() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
AssertError(gl, 0, 'start of test');
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
ok(renderer == RENDERER_OVERRIDE,
'UNMASKED_RENDERER_WEBGL value should be \'' + RENDERER_OVERRIDE + '\', was \''
+ renderer + '\'');
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
ok(vendor == VENDOR_OVERRIDE,
'UNMASKED_VENDOR_WEBGL value should be \'' + VENDOR_OVERRIDE + '\', was \'' + vendor
+ '\'');
var prefArrArr = [
['webgl.disable-debug-renderer-info', true],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestDisable);
}
function TestDisable() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(!ext, 'Should not have access to \'WEBGL_debug_renderer_info\'.');
ok(true, 'Test complete.');
SimpleTest.finish();
}
(function() {
var canvas = document.createElement('canvas');
gl = canvas.getContext('experimental-webgl');
if (!gl) {
todo(gl, 'Get WebGL working here first.');
ok(true, 'Test complete.');
return;
}
SimpleTest.waitForExplicitFinish();
var prefArrArr = [
['webgl.disable-debug-renderer-info', false],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestExt);
})();
</script>
</body>
</html>

View File

@ -1074,10 +1074,8 @@ IMEContentObserver::SelectionChangeEvent::Run()
}
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
notification.mSelectionChangeData.mOffset =
selection.mReply.mOffset;
notification.mSelectionChangeData.mLength =
selection.mReply.mString.Length();
notification.mSelectionChangeData.mOffset = selection.mReply.mOffset;
*notification.mSelectionChangeData.mString = selection.mReply.mString;
notification.mSelectionChangeData.SetWritingMode(
selection.GetWritingMode());
notification.mSelectionChangeData.mReversed = selection.mReply.mReversed;

View File

@ -4013,7 +4013,10 @@ HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal()
mDecoder->NotifyOwnerActivityChanged();
}
bool pauseElement = !IsActive() || ComputedMuted();
bool pauseElement = !IsActive();
#ifdef MOZ_B2G
pauseElement |= ComputedMuted();
#endif
SuspendOrResumeElement(pauseElement, !IsActive());

View File

@ -12315,6 +12315,8 @@ Database::RegisterTransaction(TransactionBase* aTransaction)
MOZ_ASSERT(aTransaction);
MOZ_ASSERT(!mTransactions.GetEntry(aTransaction));
MOZ_ASSERT(mDirectoryLock);
MOZ_ASSERT(!mInvalidated);
MOZ_ASSERT(!mClosed);
if (NS_WARN_IF(!mTransactions.PutEntry(aTransaction, fallible))) {
return false;
@ -18693,6 +18695,10 @@ FactoryOp::Run()
SendResults();
return NS_OK;
// We raced, no need to crash.
case State_Completed:
return NS_OK;
default:
MOZ_CRASH("Bad state!");
}
@ -18750,6 +18756,14 @@ FactoryOp::ActorDestroy(ActorDestroyReason aWhy)
AssertIsOnBackgroundThread();
NoteActorDestroyed();
if (mState == State_WaitingForTransactionsToComplete) {
// We didn't get an opportunity to clean up. Do that now.
mState = State_SendingResults;
IDB_REPORT_INTERNAL_ERR();
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
SendResults();
}
}
bool
@ -19346,9 +19360,10 @@ OpenDatabaseOp::NoteDatabaseClosed(Database* aDatabase)
AssertIsOnOwningThread();
MOZ_ASSERT(aDatabase);
MOZ_ASSERT(mState == State_WaitingForOtherDatabasesToClose ||
mState == State_WaitingForTransactionsToComplete ||
mState == State_DatabaseWorkVersionChange);
if (mState == State_DatabaseWorkVersionChange) {
if (mState != State_WaitingForOtherDatabasesToClose) {
MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty());
MOZ_ASSERT(mRequestedVersion >
aDatabase->Metadata()->mCommonMetadata.version(),
@ -19412,7 +19427,8 @@ OpenDatabaseOp::DispatchToWorkThread()
MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty());
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread()) ||
IsActorDestroyed()) {
IsActorDestroyed() ||
mDatabase->IsInvalidated()) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}

View File

@ -56,7 +56,7 @@ function testSteps()
ok(false, "Should not receive a blocked event");
};
event = yield undefined;
let event = yield undefined;
is(event.type, "success", "Got success event");
is(databases.length, 0, "All databases with version 1 were closed");
@ -145,6 +145,35 @@ function testSteps()
is(event.type, "success", "Got success event");
// Test 3: A blocked database left in that state should not hang shutdown.
info("Opening 1 database with version 1");
request = indexedDB.open(databaseName, 1);
request.onerror = errorHandler;
request.onblocked = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.type, "success", "Got success event");
db = request.result;
is(db.version, 1, "Got version 1");
info("Opening database with version 2");
request = indexedDB.open(databaseName, 2);
request.onerror = function(e) {
e.preventDefault();
};
request.onsuccess = errorHandler;
request.onblocked = grabEventAndContinueHandler;
event = yield undefined;
ok(true, "Got blocked");
// Just allow this to remain blocked ...
finishTest();
yield undefined;
}

View File

@ -1838,7 +1838,7 @@ ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor)
bool
ContentChild::RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
InfallibleTArray<ResourceMapping>&& resources,
InfallibleTArray<SubstitutionMapping>&& resources,
InfallibleTArray<OverrideMapping>&& overrides,
const nsCString& locale,
const bool& reset)
@ -1866,8 +1866,8 @@ ContentChild::RecvRegisterChromeItem(const ChromeRegistryItem& item)
chromeRegistry->RegisterOverride(item.get_OverrideMapping());
break;
case ChromeRegistryItem::TResourceMapping:
chromeRegistry->RegisterResource(item.get_ResourceMapping());
case ChromeRegistryItem::TSubstitutionMapping:
chromeRegistry->RegisterSubstitution(item.get_SubstitutionMapping());
break;
default:

View File

@ -21,7 +21,7 @@
struct ChromePackage;
class nsIObserver;
struct ResourceMapping;
struct SubstitutionMapping;
struct OverrideMapping;
class nsIDomainPolicy;
@ -282,7 +282,7 @@ public:
virtual bool DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor) override;
virtual bool RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
InfallibleTArray<ResourceMapping>&& resources,
InfallibleTArray<SubstitutionMapping>&& resources,
InfallibleTArray<OverrideMapping>&& overrides,
const nsCString& locale,
const bool& reset) override;

View File

@ -260,13 +260,13 @@ parent:
returns (bool noCompositionEvent, nsString composition);
/**
* OnEventNeedingAckReceived() is called when a child process dispatches a
* OnEventNeedingAckHandled() is called after a child process dispatches a
* composition event or a selection event which is sent from the parent
* process.
*
* message The message value of the received event.
* message The message value of the handled event.
*/
prio(urgent) async OnEventNeedingAckReceived(uint32_t message);
prio(urgent) async OnEventNeedingAckHandled(uint32_t message);
/**
* Tells chrome to start plugin IME. If this results in a string getting

View File

@ -71,7 +71,7 @@ include "mozilla/dom/indexedDB/SerializationHelpers.h";
using GeoPosition from "nsGeoPositionIPCSerialiser.h";
using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h";
using struct ResourceMapping from "mozilla/chrome/RegistryMessageUtils.h";
using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h";
using struct OverrideMapping from "mozilla/chrome/RegistryMessageUtils.h";
using base::ChildPrivileges from "base/process_util.h";
using base::ProcessId from "base/process.h";
@ -94,7 +94,7 @@ union ChromeRegistryItem
{
ChromePackage;
OverrideMapping;
ResourceMapping;
SubstitutionMapping;
};
namespace mozilla {
@ -521,7 +521,7 @@ child:
PTestShell();
RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
RegisterChrome(ChromePackage[] packages, SubstitutionMapping[] substitutions,
OverrideMapping[] overrides, nsCString locale, bool reset);
RegisterChromeItem(ChromeRegistryItem item);

View File

@ -2230,20 +2230,20 @@ TabChild::RecvKeyEvent(const nsString& aType,
bool
TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
{
unused << SendOnEventNeedingAckReceived(event.message);
WidgetCompositionEvent localEvent(event);
localEvent.widget = mPuppetWidget;
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
unused << SendOnEventNeedingAckHandled(event.message);
return true;
}
bool
TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
{
unused << SendOnEventNeedingAckReceived(event.message);
WidgetSelectionEvent localEvent(event);
localEvent.widget = mPuppetWidget;
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
unused << SendOnEventNeedingAckHandled(event.message);
return true;
}

View File

@ -2093,13 +2093,13 @@ TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
const nsIMEUpdatePreference updatePreference =
widget->GetIMEUpdatePreference();
if (updatePreference.WantPositionChanged()) {
IMEStateManager::NotifyIME(aIMENotification, widget, true);
mContentCache.MaybeNotifyIME(widget, aIMENotification);
}
return true;
}
bool
TabParent::RecvOnEventNeedingAckReceived(const uint32_t& aMessage)
TabParent::RecvOnEventNeedingAckHandled(const uint32_t& aMessage)
{
// This is called when the child process receives WidgetCompositionEvent or
// WidgetSelectionEvent.
@ -2108,10 +2108,10 @@ TabParent::RecvOnEventNeedingAckReceived(const uint32_t& aMessage)
return true;
}
// While calling OnEventNeedingAckReceived(), TabParent *might* be destroyed
// While calling OnEventNeedingAckHandled(), TabParent *might* be destroyed
// since it may send notifications to IME.
nsRefPtr<TabParent> kungFuDeathGrip(this);
mContentCache.OnEventNeedingAckReceived(widget, aMessage);
mContentCache.OnEventNeedingAckHandled(widget, aMessage);
return true;
}

View File

@ -177,7 +177,7 @@ public:
bool* aConsumedByIME) override;
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
const widget::IMENotification& aEventMessage) override;
virtual bool RecvOnEventNeedingAckReceived(const uint32_t& aMessage) override;
virtual bool RecvOnEventNeedingAckHandled(const uint32_t& aMessage) override;
virtual bool RecvEndIMEComposition(const bool& aCancel,
bool* aNoCompositionEvent,
nsString* aComposition) override;

View File

@ -38,26 +38,27 @@ AudioSink::AudioSink(MediaDecoderStateMachine* aStateMachine,
{
}
nsresult
nsRefPtr<GenericPromise>
AudioSink::Init()
{
nsRefPtr<GenericPromise> p = mEndPromise.Ensure(__func__);
nsresult rv = NS_NewNamedThread("Media Audio",
getter_AddRefs(mThread),
nullptr,
MEDIA_THREAD_STACK_SIZE);
if (NS_FAILED(rv)) {
mStateMachine->OnAudioSinkError();
return rv;
mEndPromise.Reject(rv, __func__);
return p;
}
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &AudioSink::AudioLoop);
rv = mThread->Dispatch(event, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
mStateMachine->OnAudioSinkError();
return rv;
mEndPromise.Reject(rv, __func__);
return p;
}
return NS_OK;
return p;
}
int64_t
@ -100,7 +101,10 @@ AudioSink::Shutdown()
{
mThread->Shutdown();
mThread = nullptr;
MOZ_ASSERT(!mAudioStream);
if (mAudioStream) {
mAudioStream->Shutdown();
mAudioStream = nullptr;
}
}
void
@ -142,9 +146,10 @@ AudioSink::AudioLoop()
AssertOnAudioThread();
SINK_LOG("AudioLoop started");
if (NS_FAILED(InitializeAudioStream())) {
nsresult rv = InitializeAudioStream();
if (NS_FAILED(rv)) {
NS_WARNING("Initializing AudioStream failed.");
mStateMachine->DispatchOnAudioSinkError();
mEndPromise.Reject(rv, __func__);
return;
}
@ -233,16 +238,10 @@ void
AudioSink::Cleanup()
{
AssertCurrentThreadInMonitor();
nsRefPtr<AudioStream> audioStream;
audioStream.swap(mAudioStream);
// Suppress the callback when the stop is requested by MediaDecoderStateMachine.
// See Bug 115334.
if (!mStopAudioThread) {
mStateMachine->DispatchOnAudioSinkComplete();
}
ReentrantMonitorAutoExit exit(GetReentrantMonitor());
audioStream->Shutdown();
mEndPromise.Resolve(true, __func__);
// Since the promise if resolved asynchronously, we don't shutdown
// AudioStream here so MDSM::ResyncAudioClock can get the correct
// audio position.
}
bool

View File

@ -10,6 +10,7 @@
#include "MediaDecoderReader.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/Atomics.h"
#include "mozilla/MozPromise.h"
namespace mozilla {
@ -23,7 +24,9 @@ public:
AudioSink(MediaDecoderStateMachine* aStateMachine,
int64_t aStartTime, AudioInfo aInfo, dom::AudioChannel aChannel);
nsresult Init();
// Return a promise which will be resolved when AudioSink finishes playing,
// or rejected if any error.
nsRefPtr<GenericPromise> Init();
int64_t GetPosition();
@ -140,6 +143,8 @@ private:
bool mSetPreservesPitch;
bool mPlaying;
MozPromiseHolder<GenericPromise> mEndPromise;
};
} // namespace mozilla

View File

@ -186,17 +186,20 @@ static char const *const gWebMCodecs[7] = {
"opus",
nullptr
};
#endif
/* static */ bool
DecoderTraits::IsWebMType(const nsACString& aType)
{
#ifdef MOZ_WEBM
if (!MediaDecoder::IsWebMEnabled()) {
return false;
}
return CodecListContains(gWebMTypes, aType);
}
#endif
return false;
}
#ifdef MOZ_GSTREAMER
static bool
@ -205,10 +208,9 @@ IsGStreamerSupportedType(const nsACString& aMimeType)
if (!MediaDecoder::IsGStreamerEnabled())
return false;
#ifdef MOZ_WEBM
if (DecoderTraits::IsWebMType(aMimeType) && !Preferences::GetBool("media.prefer-gstreamer", false))
return false;
#endif
if (IsOggType(aMimeType) && !Preferences::GetBool("media.prefer-gstreamer", false))
return false;
@ -355,6 +357,16 @@ IsMP4SupportedType(const nsACString& aType,
MP4Decoder::CanHandleMediaType(aType, aCodecs, haveAAC, haveH264, haveMP3);
}
#endif
/* static */ bool
DecoderTraits::IsMP4Type(const nsACString& aType)
{
#ifdef MOZ_FMP4
return IsMP4SupportedType(aType);
#endif
return false;
}
static bool
IsMP3SupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
@ -412,56 +424,44 @@ bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType)
/* static */
CanPlayStatus
DecoderTraits::CanHandleMediaType(const char* aMIMEType,
bool aHaveRequestedCodecs,
const nsAString& aRequestedCodecs)
DecoderTraits::CanHandleCodecsType(const char* aMIMEType,
const nsAString& aRequestedCodecs)
{
MOZ_ASSERT(NS_IsMainThread());
char const* const* codecList = nullptr;
CanPlayStatus result = CANPLAY_NO;
#ifdef MOZ_RAW
if (IsRawType(nsDependentCString(aMIMEType))) {
codecList = gRawCodecs;
result = CANPLAY_MAYBE;
}
#endif
if (IsOggType(nsDependentCString(aMIMEType))) {
codecList = MediaDecoder::IsOpusEnabled() ? gOggCodecsWithOpus : gOggCodecs;
result = CANPLAY_MAYBE;
}
#ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) {
codecList = gWaveCodecs;
result = CANPLAY_MAYBE;
}
#endif
#if defined(MOZ_WEBM) && !defined(MOZ_OMX_WEBM_DECODER)
#if !defined(MOZ_OMX_WEBM_DECODER)
if (IsWebMType(nsDependentCString(aMIMEType))) {
codecList = gWebMCodecs;
result = CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_FMP4
if (IsMP4SupportedType(nsDependentCString(aMIMEType),
aRequestedCodecs)) {
return aHaveRequestedCodecs ? CANPLAY_YES : CANPLAY_MAYBE;
}
#endif
if (IsMP3SupportedType(nsDependentCString(aMIMEType),
aRequestedCodecs)) {
return aHaveRequestedCodecs ? CANPLAY_YES : CANPLAY_MAYBE;
}
#ifdef MOZ_GSTREAMER
if (GStreamerDecoder::CanHandleMediaType(nsDependentCString(aMIMEType),
aHaveRequestedCodecs ? &aRequestedCodecs : nullptr)) {
if (aHaveRequestedCodecs)
if (IsMP4Type(nsDependentCString(aMIMEType))) {
if (IsMP4SupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) {
return CANPLAY_YES;
return CANPLAY_MAYBE;
} else {
// We can only reach this position if a particular codec was requested,
// fmp4 is supported and working: the codec must be invalid.
return CANPLAY_NO;
}
}
#endif
if (IsMP3SupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) {
return CANPLAY_YES;
}
#ifdef MOZ_OMX_DECODER
if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
result = CANPLAY_MAYBE;
if (nsDependentCString(aMIMEType).EqualsASCII("audio/mpeg")) {
codecList = gMpegAudioCodecs;
#ifdef MOZ_OMX_WEBM_DECODER
@ -475,27 +475,18 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
}
#endif
#ifdef MOZ_DIRECTSHOW
if (DirectShowDecoder::GetSupportedCodecs(nsDependentCString(aMIMEType), &codecList)) {
result = CANPLAY_MAYBE;
}
DirectShowDecoder::GetSupportedCodecs(nsDependentCString(aMIMEType), &codecList);
#endif
#ifdef MOZ_APPLEMEDIA
if (IsAppleMediaSupportedType(nsDependentCString(aMIMEType), &codecList)) {
result = CANPLAY_MAYBE;
}
IsAppleMediaSupportedType(nsDependentCString(aMIMEType), &codecList);
#endif
#ifdef MOZ_ANDROID_OMX
if (MediaDecoder::IsAndroidMediaEnabled() &&
EnsureAndroidMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), &codecList))
result = CANPLAY_MAYBE;
#endif
#ifdef NECKO_PROTOCOL_rtsp
if (IsRtspSupportedType(nsDependentCString(aMIMEType))) {
result = CANPLAY_MAYBE;
if (MediaDecoder::IsAndroidMediaEnabled()) {
EnsureAndroidMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), &codecList);
}
#endif
if (result == CANPLAY_NO || !aHaveRequestedCodecs || !codecList) {
return result;
if (!codecList) {
return CANPLAY_MAYBE;
}
// See http://www.rfc-editor.org/rfc/rfc4281.txt for the description
@ -515,9 +506,83 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
// Last codec name was empty
return CANPLAY_NO;
}
return CANPLAY_YES;
}
/* static */
CanPlayStatus
DecoderTraits::CanHandleMediaType(const char* aMIMEType,
bool aHaveRequestedCodecs,
const nsAString& aRequestedCodecs)
{
MOZ_ASSERT(NS_IsMainThread());
if (aHaveRequestedCodecs) {
CanPlayStatus result = CanHandleCodecsType(aMIMEType, aRequestedCodecs);
if (result == CANPLAY_NO || result == CANPLAY_YES) {
return result;
}
}
#ifdef MOZ_RAW
if (IsRawType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
if (IsOggType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
if (IsMP4Type(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#if !defined(MOZ_OMX_WEBM_DECODER)
if (IsWebMType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
if (IsMP3SupportedType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#ifdef MOZ_GSTREAMER
if (GStreamerDecoder::CanHandleMediaType(nsDependentCString(aMIMEType),
aHaveRequestedCodecs ? &aRequestedCodecs : nullptr)) {
return aHaveRequestedCodecs ? CANPLAY_YES : CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_OMX_DECODER
if (IsOmxSupportedType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_DIRECTSHOW
if (DirectShowDecoder::GetSupportedCodecs(nsDependentCString(aMIMEType), nullptr)) {
return CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_APPLEMEDIA
if (IsAppleMediaSupportedType(nsDependentCString(aMIMEType), nullptr)) {
return CANPLAY_MAYBE;
}
#endif
#ifdef MOZ_ANDROID_OMX
if (MediaDecoder::IsAndroidMediaEnabled() &&
EnsureAndroidMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), nullptr)) {
return CANPLAY_MAYBE;
}
#endif
#ifdef NECKO_PROTOCOL_rtsp
if (IsRtspSupportedType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
return CANPLAY_NO;
}
// Instantiates but does not initialize decoder.
static
already_AddRefed<MediaDecoder>
@ -604,12 +669,10 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
return decoder.forget();
}
#endif
#ifdef MOZ_WEBM
if (DecoderTraits::IsWebMType(aType)) {
decoder = new WebMDecoder();
return decoder.forget();
}
#endif
#ifdef MOZ_DIRECTSHOW
// Note: DirectShow should come before WMF, so that we prefer DirectShow's
// MP3 support over WMF's.
@ -694,13 +757,11 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
decoderReader = new AndroidMediaReader(aDecoder, aType);
} else
#endif
#ifdef MOZ_WEBM
if (IsWebMType(aType)) {
decoderReader = Preferences::GetBool("media.format-reader.webm", true) ?
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new WebMDemuxer(aDecoder->GetResource()))) :
new WebMReader(aDecoder);
} else
#endif
#ifdef MOZ_DIRECTSHOW
if (IsDirectShowSupportedType(aType)) {
decoderReader = new DirectShowReader(aDecoder);
@ -736,9 +797,7 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
(IsOmxSupportedType(aType) &&
!IsB2GSupportOnlyType(aType)) ||
#endif
#ifdef MOZ_WEBM
IsWebMType(aType) ||
#endif
#ifdef MOZ_GSTREAMER
IsGStreamerSupportedType(aType) ||
#endif

View File

@ -29,7 +29,7 @@ class DecoderTraits {
public:
// Returns the CanPlayStatus indicating if we can handle this
// MIME type. The MIME type should not include the codecs parameter.
// That parameter should be passed in aCodecs, and will only be
// That parameter should be passed in aRequestedCodecs, and will only be
// used if whether a given MIME type being handled depends on the
// codec that will be used. If the codecs parameter has not been
// specified, pass false in aHaveRequestedCodecs.
@ -37,6 +37,14 @@ public:
bool aHaveRequestedCodecs,
const nsAString& aRequestedCodecs);
// Returns the CanPlayStatus indicating if we can handle this MIME type and
// codecs type natively, excluding any plugins-based reader (such as
// GStreamer)
// The MIME type should not include the codecs parameter.
// That parameter is passed in aRequestedCodecs.
static CanPlayStatus CanHandleCodecsType(const char* aMIMEType,
const nsAString& aRequestedCodecs);
// Returns true if we should handle this MIME type when it appears
// as an <object> or as a toplevel page. If, in practice, our support
// for the type is more limited than appears in the wild, we should return
@ -63,6 +71,7 @@ public:
static bool DecoderWaitsForOnConnected(const nsACString& aType);
static bool IsWebMType(const nsACString& aType);
static bool IsMP4Type(const nsACString& aType);
};
} // namespace mozilla

View File

@ -1086,8 +1086,7 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
SetPlayStartTime(TimeStamp::Now());
MOZ_ASSERT(IsPlaying());
nsresult rv = StartAudioThread();
NS_ENSURE_SUCCESS_VOID(rv);
StartAudioThread();
// Tell DecodedStream to start playback with specified start time and media
// info. This is consistent with how we create AudioSink in StartAudioThread().
@ -1481,6 +1480,7 @@ void MediaDecoderStateMachine::StopAudioThread()
}
mAudioSink = nullptr;
}
mAudioSinkPromise.DisconnectIfExists();
}
nsresult
@ -1783,31 +1783,31 @@ MediaDecoderStateMachine::RequestVideoData()
}
}
nsresult
void
MediaDecoderStateMachine::StartAudioThread()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mAudioCaptured) {
MOZ_ASSERT(!mAudioSink);
return NS_OK;
return;
}
if (HasAudio() && !mAudioSink) {
auto audioStartTime = GetMediaTime();
mAudioCompleted = false;
mAudioSink = new AudioSink(this, audioStartTime,
mAudioSink = new AudioSink(this, GetMediaTime(),
mInfo.mAudio, mDecoder->GetAudioChannel());
// OnAudioSinkError() will be called before Init() returns if an error
// occurs during initialization.
nsresult rv = mAudioSink->Init();
NS_ENSURE_SUCCESS(rv, rv);
mAudioSinkPromise.Begin(
mAudioSink->Init()->Then(
OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnAudioSinkComplete,
&MediaDecoderStateMachine::OnAudioSinkError));
mAudioSink->SetVolume(mVolume);
mAudioSink->SetPlaybackRate(mPlaybackRate);
mAudioSink->SetPreservesPitch(mPreservesPitch);
}
return NS_OK;
}
int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
@ -2456,12 +2456,12 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
AbstractThread::MainThread()->Dispatch(event.forget());
mSentPlaybackEndedEvent = true;
}
// Stop audio sink after call to AudioEndTime() above, otherwise it will
// return an incorrect value due to a null mAudioSink.
StopAudioThread();
mDecodedStream->StopPlayback();
// Stop audio sink after call to AudioEndTime() above, otherwise it will
// return an incorrect value due to a null mAudioSink.
StopAudioThread();
mDecodedStream->StopPlayback();
}
return NS_OK;
}
@ -3122,11 +3122,12 @@ void MediaDecoderStateMachine::OnAudioSinkComplete()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mAudioCaptured) {
return;
}
MOZ_ASSERT(!mAudioCaptured, "Should be disconnected when capturing audio.");
mAudioSinkPromise.Complete();
ResyncAudioClock();
mAudioCompleted = true;
// Kick the decode thread; it may be sleeping waiting for this to finish.
mDecoder->GetReentrantMonitor().NotifyAll();
}
@ -3135,11 +3136,9 @@ void MediaDecoderStateMachine::OnAudioSinkError()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// AudioSink not used with captured streams, so ignore errors in this case.
if (mAudioCaptured) {
return;
}
MOZ_ASSERT(!mAudioCaptured, "Should be disconnected when capturing audio.");
mAudioSinkPromise.Complete();
ResyncAudioClock();
mAudioCompleted = true;

View File

@ -517,7 +517,7 @@ protected:
// Starts the audio thread. The decoder monitor must be held with exactly
// one lock count. Called on the state machine thread.
nsresult StartAudioThread();
void StartAudioThread();
// Notification method invoked when mPlayState changes.
void PlayStateChanged();
@ -679,28 +679,13 @@ public:
}
private:
// Called by the AudioSink to signal that all outstanding work is complete
// Resolved by the AudioSink to signal that all outstanding work is complete
// and the sink is shutting down.
void OnAudioSinkComplete();
public:
void DispatchOnAudioSinkComplete()
{
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnAudioSinkComplete);
OwnerThread()->Dispatch(runnable.forget());
}
private:
// Called by the AudioSink to signal errors.
// Rejected by the AudioSink to signal errors.
void OnAudioSinkError();
void DispatchOnAudioSinkError()
{
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnAudioSinkError);
OwnerThread()->Dispatch(runnable.forget());
}
// Return true if the video decoder's decode speed can not catch up the
// play time.
bool NeedToSkipToNextKeyframe();
@ -1317,6 +1302,8 @@ private:
// Media data resource from the decoder.
nsRefPtr<MediaResource> mResource;
MozPromiseRequestHolder<GenericPromise> mAudioSinkPromise;
private:
// The buffered range. Mirrored from the decoder thread.
Mirror<media::TimeIntervals> mBuffered;

View File

@ -1138,6 +1138,10 @@ MediaFormatReader::WaitForData(MediaData::Type aType)
TrackType trackType = aType == MediaData::VIDEO_DATA ?
TrackType::kVideoTrack : TrackType::kAudioTrack;
auto& decoder = GetDecoderData(trackType);
if (!decoder.mWaitingForData) {
// We aren't waiting for data any longer.
return WaitForDataPromise::CreateAndResolve(decoder.mType, __func__);
}
nsRefPtr<WaitForDataPromise> p = decoder.mWaitingPromise.Ensure(__func__);
ScheduleUpdate(trackType);
return p;

View File

@ -71,8 +71,9 @@ IsSupportedAudioCodec(const nsAString& aCodec,
bool& aOutContainsMP3)
{
// AAC-LC or HE-AAC in M4A.
aOutContainsAAC = aCodec.EqualsASCII("mp4a.40.2") ||
aCodec.EqualsASCII("mp4a.40.5");
aOutContainsAAC = aCodec.EqualsASCII("mp4a.40.2") // MPEG4 AAC-LC
|| aCodec.EqualsASCII("mp4a.40.5") // MPEG4 HE-AAC
|| aCodec.EqualsASCII("mp4a.67"); // MPEG2 AAC-LC
if (aOutContainsAAC) {
return true;
}

View File

@ -83,46 +83,41 @@ IsTypeSupported(const nsAString& aType)
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
bool found = false;
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
nsAutoString codecs;
bool hasCodecs = NS_SUCCEEDED(parser.GetParameter("codecs", codecs));
for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
if ((mimeType.EqualsASCII("video/mp4") ||
mimeType.EqualsASCII("audio/mp4")) &&
(!Preferences::GetBool("media.mediasource.mp4.enabled", false)
#ifdef MOZ_WIDGET_ANDROID
// MP4 won't work unless we have JellyBean+
|| AndroidBridge::Bridge()->GetAPIVersion() < 16
#endif
)) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
if (DecoderTraits::IsMP4Type(mimeTypeUTF8)) {
if (!Preferences::GetBool("media.mediasource.mp4.enabled", false)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (hasCodecs &&
DecoderTraits::CanHandleCodecsType(mimeTypeUTF8.get(),
codecs) == CANPLAY_NO) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
return NS_OK;
} else if (DecoderTraits::IsWebMType(mimeTypeUTF8)) {
if (!Preferences::GetBool("media.mediasource.webm.enabled", false) ||
Preferences::GetBool("media.mediasource.format-reader", false)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (hasCodecs &&
DecoderTraits::CanHandleCodecsType(mimeTypeUTF8.get(),
codecs) == CANPLAY_NO) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
return NS_OK;
}
if ((mimeType.EqualsASCII("video/webm") ||
mimeType.EqualsASCII("audio/webm")) &&
!Preferences::GetBool("media.mediasource.webm.enabled", false)) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
found = true;
break;
}
}
if (!found) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
// Check aType against HTMLMediaElement list of MIME types. Since we've
// already restricted the container format, this acts as a specific check
// of any specified "codecs" parameter of aType.
if (dom::HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (Preferences::GetBool("media.mediasource.format-reader", false) &&
!mimeType.EqualsASCII("video/mp4") && !mimeType.EqualsASCII("audio/mp4")) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
return NS_OK;
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
namespace dom {

View File

@ -35,54 +35,68 @@ support-files =
bipbop/bipbop13.m4s^headers^ bipbop/bipbop_video13.m4s^headers^
[test_BufferedSeek.html]
skip-if = true # bug 1182946
[test_BufferedSeek_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_BufferingWait.html]
skip-if = true # bug 1093133
skip-if = true # bug 1182946
[test_BufferingWait_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_EndOfStream.html]
skip-if = (toolkit == 'android' || buildapp == 'mulet') #timeout android/mulet only bug 1101187
skip-if = (true || toolkit == 'android' || buildapp == 'mulet') #timeout android/mulet only bug 1101187 and bug 1182946
[test_EndOfStream_mp4.html]
skip-if = (toolkit == 'android' || buildapp == 'mulet') || ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_DurationUpdated.html]
skip-if = true # bug 1182946
[test_DurationUpdated_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_FrameSelection.html]
skip-if = true # bug 1182946
[test_HaveMetadataUnbufferedSeek.html]
skip-if = true # bug 1182946
[test_HaveMetadataUnbufferedSeek_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_LoadedMetadataFired.html]
skip-if = true # bug 1182946
[test_LoadedMetadataFired_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_MediaSource.html]
skip-if = true # bug 1182946
[test_MediaSource_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_MediaSource_disabled.html]
[test_SeekableAfterEndOfStream.html]
skip-if = true # bug 1182946
[test_SeekableAfterEndOfStream_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekableAfterEndOfStreamSplit.html]
skip-if = true # bug 1182946
[test_SeekableAfterEndOfStreamSplit_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekableBeforeEndOfStream.html]
skip-if = true # bug 1182946
[test_SeekableBeforeEndOfStream_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekableBeforeEndOfStreamSplit.html]
skip-if = true # bug 1182946
[test_SeekableBeforeEndOfStreamSplit_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SeekTwice_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SetModeThrows.html]
skip-if = true # bug 1182946
[test_SplitAppendDelay.html]
skip-if = true # bug 1182946
[test_SplitAppendDelay_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_SplitAppend.html]
skip-if = true # bug 1182946
[test_SplitAppend_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_TimestampOffset_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_TruncatedDuration.html]
skip-if = true # bug 1182946
[test_TruncatedDuration_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_WaitingOnMissingData.html]

View File

@ -1,5 +1,16 @@
const KEYSYSTEM_TYPE = "org.w3.clearkey";
function IsMacOSSnowLeopardOrEarlier() {
var re = /Mac OS X (\d+)\.(\d+)/;
var ver = navigator.userAgent.match(re);
if (!ver || ver.length != 3) {
return false;
}
var major = ver[1] | 0;
var minor = ver[2] | 0;
return major == 10 && minor <= 6;
}
function bail(message)
{
return function(err) {

View File

@ -46,8 +46,12 @@ function beginTest() {
manager.runTests(gEMETests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -89,8 +89,12 @@ function beginTest() {
manager.runTests(gEMENonMSEFailTests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -154,8 +154,12 @@ function beginTest() {
manager.runTests(gEMETests.filter(t => t.sessionCount === 1), startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -111,8 +111,12 @@ function beginTest() {
manager.runTests(gEMETests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -292,8 +292,12 @@ function beginTest() {
Promise.all(tests.map(Test)).then(function() { SimpleTest.finish(); });
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>

View File

@ -40,8 +40,12 @@ function beginTest() {
manager.runTests(gEMETests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -43,8 +43,12 @@ function beginTest() {
manager.runTests(gEMETests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -42,8 +42,12 @@ function beginTest() {
manager.runTests(gEMETests, startTest);
}
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
SetupEMEPref(beginTest);
} else {
todo(false, "Test disabled on this platform.");
}
</script>
</pre>
</body>

View File

@ -130,16 +130,6 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId,
return true;
}
*rv = PPluginModule::Bridge(aContentParent, chromeParent);
if (NS_FAILED(*rv)) {
#if defined(MOZ_CRASHREPORTER)
// We are going to abort due to the failure, lets note the cause
// in the report for diagnosing.
nsAutoCString error;
error.AppendPrintf("%X %d", *rv, chromeParent->GetIPCChannel()->GetChannelState__TotallyRacy());
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BridgePluginError"), error);
#endif
return false;
}
return true;
}

View File

@ -1261,6 +1261,8 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
if (IsSupported(GLFeature::gpu_shader4)) {
SymLoadStruct gpuShader4Symbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, { "GetVertexAttribIiv", "GetVertexAttribIivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, { "GetVertexAttribIuiv", "GetVertexAttribIuivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fVertexAttribI4i, { "VertexAttribI4i", "VertexAttribI4iEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, { "VertexAttribI4iv","VertexAttribI4ivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, { "VertexAttribI4ui", "VertexAttribI4uiEXT", nullptr } },

View File

@ -2376,6 +2376,22 @@ public:
// -----------------------------------------------------------------------------
// GL 3.0, GL ES 3.0 & EXT_gpu_shader4
public:
void fGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
{
ASSERT_SYMBOL_PRESENT(fGetVertexAttribIiv);
BEFORE_GL_CALL;
mSymbols.fGetVertexAttribIiv(index, pname, params);
AFTER_GL_CALL;
}
void fGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
{
ASSERT_SYMBOL_PRESENT(fGetVertexAttribIuiv);
BEFORE_GL_CALL;
mSymbols.fGetVertexAttribIuiv(index, pname, params);
AFTER_GL_CALL;
}
void fVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
{
BEFORE_GL_CALL;

View File

@ -620,6 +620,10 @@ struct GLContextSymbols
PFNGLUNIFORMBLOCKBINDINGPROC fUniformBlockBinding;
// EXT_gpu_shader4
typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint* params);
PFNGLGETVERTEXATTRIBIIVPROC fGetVertexAttribIiv;
typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint* params);
PFNGLGETVERTEXATTRIBIUIVPROC fGetVertexAttribIuiv;
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
PFNGLVERTEXATTRIBI4IPROC fVertexAttribI4i;
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint* v);

View File

@ -407,7 +407,7 @@ BufferTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
// If the last frame wasn't uploaded yet, and we -don't- have a partial update,
// we still need to update the full surface.
if (aRegion && !mNeedsFullUpdate) {
mMaybeUpdatedRegion = mMaybeUpdatedRegion.Or(mMaybeUpdatedRegion, *aRegion);
mMaybeUpdatedRegion.OrWith(*aRegion);
} else {
mNeedsFullUpdate = true;
}

View File

@ -971,7 +971,7 @@ TestDataStructuresChild::Test18()
ra.SetCapacity(nelements);
for (int i = 0; i < nelements; ++i) {
nsIntRegion r;
r = r.Or(nsIntRect(0, 0, 10, 10), nsIntRect(10, 10, 10, 10));
r.Or(nsIntRect(0, 0, 10, 10), nsIntRect(10, 10, 10, 10));
ra.AppendElement(r);
}

View File

@ -11,6 +11,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Move.h"
#include "mozilla/TypeTraits.h"
#include "jspubtd.h"
@ -643,7 +644,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
/* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
template <typename CX>
void init(CX* cx) {
void registerWithRootLists(CX* cx) {
js::ThingRootKind kind = js::RootKind<T>::rootKind();
this->stack = &cx->roots.stackRoots_[kind];
this->prev = *stack;
@ -656,15 +657,16 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(js::ContextFriendFields::get(cx));
registerWithRootLists(js::ContextFriendFields::get(cx));
}
Rooted(JSContext* cx, const T& initial
template <typename S>
Rooted(JSContext* cx, S&& initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
: ptr(mozilla::Forward<S>(initial))
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(js::ContextFriendFields::get(cx));
registerWithRootLists(js::ContextFriendFields::get(cx));
}
explicit Rooted(js::ContextFriendFields* cx
@ -672,15 +674,16 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx);
registerWithRootLists(cx);
}
Rooted(js::ContextFriendFields* cx, const T& initial
template <typename S>
Rooted(js::ContextFriendFields* cx, S&& initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
: ptr(mozilla::Forward<S>(initial))
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx);
registerWithRootLists(cx);
}
explicit Rooted(js::PerThreadDataFriendFields* pt
@ -688,15 +691,16 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
registerWithRootLists(pt);
}
Rooted(js::PerThreadDataFriendFields* pt, const T& initial
template <typename S>
Rooted(js::PerThreadDataFriendFields* pt, S&& initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
: ptr(mozilla::Forward<S>(initial))
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
registerWithRootLists(pt);
}
explicit Rooted(JSRuntime* rt
@ -704,15 +708,16 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(js::PerThreadDataFriendFields::getMainThread(rt));
registerWithRootLists(js::PerThreadDataFriendFields::getMainThread(rt));
}
Rooted(JSRuntime* rt, const T& initial
template <typename S>
Rooted(JSRuntime* rt, S&& initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
: ptr(mozilla::Forward<S>(initial))
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(js::PerThreadDataFriendFields::getMainThread(rt));
registerWithRootLists(js::PerThreadDataFriendFields::getMainThread(rt));
}
~Rooted() {

View File

@ -0,0 +1,186 @@
/* -*- 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 gc_HashTable_h
#define gc_HashTable_h
#include "js/HashTable.h"
#include "js/RootingAPI.h"
namespace js {
template <typename> struct DefaultTracer;
// A TraceableHashMap is a HashMap with an additional trace method that knows
// how to visit all keys and values in the table. HashMaps that contain GC
// pointers that must be traced to be kept alive will generally want to use
// this TraceableHashMap specializeation in lieu of HashMap.
//
// Most types of GC pointers as keys and values can be traced with no extra
// infrastructure. For structs and non-gc-pointer members, ensure that there
// is a specialization of DefaultTracer<T> with an appropriate trace method
// available to handle the custom type.
//
// Note that although this HashMap's trace will deal correctly with moved keys,
// it does not itself know when to barrier or trace keys. To function properly
// it must either be used with Rooted, or barriered and traced manually.
template <typename Key,
typename Value,
typename HashPolicy = DefaultHasher<Key>,
typename AllocPolicy = TempAllocPolicy,
typename KeyTraceFunc = DefaultTracer<Key>,
typename ValueTraceFunc = DefaultTracer<Value>>
class TraceableHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
public JS::DynamicTraceable
{
using Base = HashMap<Key, Value, HashPolicy, AllocPolicy>;
public:
explicit TraceableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
void trace(JSTracer* trc) override {
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
ValueTraceFunc::trace(trc, &e.front().value(), "hashmap value");
Key key = e.front().key();
KeyTraceFunc::trace(trc, &key, "hashmap key");
if (key != e.front().key())
e.rekeyFront(key);
}
}
// TraceableHashMap is movable
TraceableHashMap(TraceableHashMap&& rhs) : Base(mozilla::Forward<TraceableHashMap>(rhs)) {}
void operator=(TraceableHashMap&& rhs) {
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
Base::operator=(mozilla::Forward<TraceableHashMap>(rhs));
}
private:
// TraceableHashMap is not copyable or assignable
TraceableHashMap(const TraceableHashMap& hm) = delete;
TraceableHashMap& operator=(const TraceableHashMap& hm) = delete;
};
template <typename Outer, typename... MapArgs>
class TraceableHashMapOperations
{
using Map = TraceableHashMap<MapArgs...>;
using Lookup = typename Map::Lookup;
using Ptr = typename Map::Ptr;
using AddPtr = typename Map::AddPtr;
using Range = typename Map::Range;
using Enum = typename Map::Enum;
const Map& map() const { return static_cast<const Outer*>(this)->extract(); }
public:
bool initialized() const { return map().initialized(); }
Ptr lookup(const Lookup& l) const { return map().lookup(l); }
AddPtr lookupForAdd(const Lookup& l) const { return map().lookupForAdd(l); }
Range all() const { return map().all(); }
bool empty() const { return map().empty(); }
uint32_t count() const { return map().count(); }
size_t capacity() const { return map().capacity(); }
uint32_t generation() const { return map().generation(); }
bool has(const Lookup& l) const { return map().lookup(l).found(); }
};
template <typename Outer, typename... MapArgs>
class MutableTraceableHashMapOperations
: public TraceableHashMapOperations<Outer, MapArgs...>
{
using Map = TraceableHashMap<MapArgs...>;
using Lookup = typename Map::Lookup;
using Ptr = typename Map::Ptr;
using AddPtr = typename Map::AddPtr;
using Range = typename Map::Range;
using Enum = typename Map::Enum;
Map& map() { return static_cast<Outer*>(this)->extract(); }
public:
bool init(uint32_t len = 16) { return map().init(len); }
void clear() { map().clear(); }
void finish() { map().finish(); }
void remove(Ptr p) { map().remove(p); }
template<typename KeyInput, typename ValueInput>
bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) {
return map().add(p, mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
}
template<typename KeyInput>
bool add(AddPtr& p, KeyInput&& k) {
return map().add(p, mozilla::Forward<KeyInput>(k), Map::Value());
}
template<typename KeyInput, typename ValueInput>
bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) {
return map().relookupOrAdd(p, k,
mozilla::Forward<KeyInput>(k),
mozilla::Forward<ValueInput>(v));
}
template<typename KeyInput, typename ValueInput>
bool put(KeyInput&& k, ValueInput&& v) {
return map().put(mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
}
template<typename KeyInput, typename ValueInput>
bool putNew(KeyInput&& k, ValueInput&& v) {
return map().putNew(mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
}
};
template <template <typename...> class TraceableHashMap, typename... MapArgs>
class RootedBase<TraceableHashMap<MapArgs...>>
: public MutableTraceableHashMapOperations<JS::Rooted<TraceableHashMap<MapArgs...>>, MapArgs...>
{
using Map = TraceableHashMap<MapArgs...>;
friend class TraceableHashMapOperations<JS::Rooted<Map>, MapArgs...>;
const Map& extract() const { return *static_cast<const JS::Rooted<Map>*>(this)->address(); }
friend class MutableTraceableHashMapOperations<JS::Rooted<Map>, MapArgs...>;
Map& extract() { return *static_cast<JS::Rooted<Map>*>(this)->address(); }
};
template <template <typename...> class TraceableHashMap, typename... MapArgs>
class MutableHandleBase<TraceableHashMap<MapArgs...>>
: public MutableTraceableHashMapOperations<JS::MutableHandle<TraceableHashMap<MapArgs...>>,
MapArgs...>
{
using Map = TraceableHashMap<MapArgs...>;
friend class TraceableHashMapOperations<JS::MutableHandle<Map>, MapArgs...>;
const Map& extract() const {
return *static_cast<const JS::MutableHandle<Map>*>(this)->address();
}
friend class MutableTraceableHashMapOperations<JS::MutableHandle<Map>, MapArgs...>;
Map& extract() { return *static_cast<JS::MutableHandle<Map>*>(this)->address(); }
};
template <template <typename...> class TraceableHashMap, typename... MapArgs>
class HandleBase<TraceableHashMap<MapArgs...>>
: public TraceableHashMapOperations<JS::Handle<TraceableHashMap<MapArgs...>>, MapArgs...>
{
using Map = TraceableHashMap<MapArgs...>;
friend class TraceableHashMapOperations<JS::Handle<Map>, MapArgs...>;
const Map& extract() const { return *static_cast<const JS::Handle<Map>*>(this)->address(); }
};
// The default implementation of DefaultTracer will leave alone POD types.
template <typename T> struct DefaultTracer {
static_assert(mozilla::IsPod<T>::value, "non-pod types must not be ignored");
static void trace(JSTracer* trc, T* t, const char* name) {}
};
} /* namespace js */
#endif /* gc_HashTable_h */

View File

@ -4041,18 +4041,6 @@ CType::Finalize(JSFreeOp* fop, JSObject* obj)
}
}
void
TraceFieldInfoHash(JSTracer* trc, FieldInfoHash* fields)
{
for (FieldInfoHash::Enum e(*fields); !e.empty(); e.popFront()) {
JSString* key = e.front().key();
JS_CallUnbarrieredStringTracer(trc, &key, "fieldName");
if (key != e.front().key())
e.rekeyFront(JS_ASSERT_STRING_IS_FLAT(key));
JS_CallObjectTracer(trc, &e.front().value().mType, "fieldType");
}
}
void
CType::Trace(JSTracer* trc, JSObject* obj)
{
@ -4069,7 +4057,7 @@ CType::Trace(JSTracer* trc, JSObject* obj)
return;
FieldInfoHash* fields = static_cast<FieldInfoHash*>(slot.toPrivate());
TraceFieldInfoHash(trc, fields);
fields->trace(trc);
break;
}
case TYPE_function: {
@ -5478,31 +5466,6 @@ PostBarrierCallback(JSTracer* trc, JSString* key, void* data)
table->rekeyIfMoved(JS_ASSERT_STRING_IS_FLAT(prior), JS_ASSERT_STRING_IS_FLAT(key));
}
// Holds a pointer to a FieldInfoHash while it is being constructed, tracing it
// on GC and destroying it when it dies unless release() has been called first.
class FieldInfoHolder : public JS::CustomAutoRooter
{
public:
FieldInfoHolder(JSContext* cx, FieldInfoHash* fields)
: CustomAutoRooter(cx), fields_(fields) {}
~FieldInfoHolder() {
delete fields_;
}
virtual void trace(JSTracer* trc) override {
if (fields_)
TraceFieldInfoHash(trc, fields_);
}
FieldInfoHash* operator->() { return fields_; }
operator FieldInfoHash*() { return fields_; }
FieldInfoHash* release() {
FieldInfoHash* result = fields_;
fields_ = nullptr;
return result;
}
private:
FieldInfoHash* fields_;
};
bool
StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsObj_)
{
@ -5529,12 +5492,9 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
JSPROP_READONLY | JSPROP_PERMANENT))
return false;
// Create a FieldInfoHash to stash on the type object, and an array to root
// its constituents. (We cannot simply stash the hash in a reserved slot now
// to get GC safety for free, since if anything in this function fails we
// do not want to mutate 'typeObj'.)
FieldInfoHolder fields(cx, cx->new_<FieldInfoHash>());
if (!fields || !fields->init(len)) {
// Create a FieldInfoHash to stash on the type object.
Rooted<FieldInfoHash> fields(cx);
if (!fields.init(len)) {
JS_ReportOutOfMemory(cx);
return false;
}
@ -5556,7 +5516,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
return false;
// Make sure each field name is unique
FieldInfoHash::AddPtr entryPtr = fields->lookupForAdd(name);
FieldInfoHash::AddPtr entryPtr = fields.lookupForAdd(name);
if (entryPtr) {
JS_ReportError(cx, "struct fields must have unique names");
return false;
@ -5606,8 +5566,8 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
info.mType = fieldType;
info.mIndex = i;
info.mOffset = fieldOffset;
ASSERT_OK(fields->add(entryPtr, name, info));
JS_StoreStringPostBarrierCallback(cx, PostBarrierCallback, name, fields);
ASSERT_OK(fields.add(entryPtr, name, info));
JS_StoreStringPostBarrierCallback(cx, PostBarrierCallback, name, fields.address());
structSize = fieldOffset + fieldSize;
@ -5636,7 +5596,14 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
if (!SizeTojsval(cx, structSize, &sizeVal))
return false;
JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PrivateValue(fields.release()));
// Move the field hash to the heap and store it in the typeObj.
FieldInfoHash *heapHash = cx->new_<FieldInfoHash>(mozilla::Move(fields.get()));
if (!heapHash) {
JS_ReportOutOfMemory(cx);
return false;
}
MOZ_ASSERT(heapHash->initialized());
JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PrivateValue(heapHash));
JS_SetReservedSlot(typeObj, SLOT_SIZE, sizeVal);
JS_SetReservedSlot(typeObj, SLOT_ALIGN, Int32Value(structAlign));

View File

@ -14,7 +14,7 @@
#include "prlink.h"
#include "ctypes/typedefs.h"
#include "js/HashTable.h"
#include "js/TraceableHashTable.h"
#include "js/Vector.h"
#include "vm/String.h"
@ -279,7 +279,8 @@ struct FieldHashPolicy : DefaultHasher<JSFlatString*>
}
};
typedef HashMap<JSFlatString*, FieldInfo, FieldHashPolicy, SystemAllocPolicy> FieldInfoHash;
typedef TraceableHashMap<JSFlatString*, FieldInfo, FieldHashPolicy, SystemAllocPolicy>
FieldInfoHash;
void
TraceFieldInfoHash(JSTracer* trc, FieldInfoHash* fields);
@ -533,6 +534,13 @@ namespace UInt64 {
} // namespace UInt64
} // namespace ctypes
template <> struct DefaultTracer<ctypes::FieldInfo> {
static void trace(JSTracer* trc, ctypes::FieldInfo* t, const char* name) {
JS_CallObjectTracer(trc, &t->mType, "fieldType");
}
};
} // namespace js
#endif /* ctypes_CTypes_h */

View File

@ -40,16 +40,6 @@ typedef RootedValueMap::Range RootRange;
typedef RootedValueMap::Entry RootEntry;
typedef RootedValueMap::Enum RootEnum;
// Note: the following two functions cannot be static as long as we are using
// GCC 4.4, since it requires template function parameters to have external
// linkage.
void
MarkPropertyDescriptorRoot(JSTracer* trc, JSPropertyDescriptor* pd, const char* name)
{
pd->trace(trc);
}
// We cannot instantiate (even indirectly) the abstract JS::DynamicTraceable.
// Instead we cast to a ConcreteTraceable, then upcast before calling trace so
// that we get the implementation defined dynamically in the vtable.
@ -95,8 +85,6 @@ MarkExactStackRootsAcrossTypes(T context, JSTracer* trc)
MarkExactStackRootList<LazyScript*>(trc, context, "exact-lazy-script");
MarkExactStackRootList<jsid>(trc, context, "exact-id");
MarkExactStackRootList<Value>(trc, context, "exact-value");
MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
trc, context, "JSPropertyDescriptor");
MarkExactStackRootList<JS::StaticTraceable,
js::DispatchWrapper<JS::StaticTraceable>::TraceWrapped>(
trc, context, "StaticTraceable");
@ -203,18 +191,6 @@ AutoGCRooter::trace(JSTracer* trc)
return;
}
case OBJU32HASHMAP: {
AutoObjectUnsigned32HashMap* self = static_cast<AutoObjectUnsigned32HashMap*>(this);
AutoObjectUnsigned32HashMap::HashMapImpl& map = self->map;
for (AutoObjectUnsigned32HashMap::Enum e(map); !e.empty(); e.popFront()) {
JSObject* key = e.front().key();
TraceRoot(trc, &key, "AutoObjectUnsignedHashMap key");
if (key != e.front().key())
e.rekeyFront(key);
}
return;
}
case HASHABLEVALUE: {
AutoHashableValueRooter* rooter = static_cast<AutoHashableValueRooter*>(this);
rooter->trace(trc);

View File

@ -10,6 +10,7 @@
#include "jsfriendapi.h"
#include "gc/Barrier.h"
#include "js/TraceableHashTable.h"
namespace js {
@ -130,6 +131,22 @@ TraceCycleCollectorChildren(JS::CallbackTracer* trc, ObjectGroup* group);
} // namespace gc
template <typename T>
struct DefaultTracer<T*>
{
static void trace(JSTracer* trc, T** t, const char* name) {
TraceManuallyBarrieredEdge(trc, t, name);
}
};
template <typename T>
struct DefaultTracer<RelocatablePtr<T*>>
{
static void trace(JSTracer* trc, RelocatablePtr<T*> t, const char* name) {
TraceEdge(trc, t, name);
}
};
} // namespace js
#endif /* js_Tracer_h */

View File

@ -870,7 +870,7 @@ BaselineCompiler::emitProfilerEnterFrame()
// Starts off initially disabled.
Label noInstrument;
CodeOffsetLabel toggleOffset = masm.toggledJump(&noInstrument);
masm.profilerEnterFrame(BaselineStackReg, R0.scratchReg());
masm.profilerEnterFrame(masm.getStackPointer(), R0.scratchReg());
masm.bind(&noInstrument);
// Store the start offset in the appropriate location.
@ -3780,7 +3780,7 @@ BaselineCompiler::emit_JSOP_RESUME()
AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skip);
masm.loadPtr(AbsoluteAddress(cx->runtime()->addressOfProfilingActivation()), scratchReg);
masm.storePtr(BaselineStackReg,
masm.storePtr(masm.getStackPointer(),
Address(scratchReg, JitActivation::offsetOfLastProfilingFrame()));
masm.bind(&skip);
}

View File

@ -228,7 +228,7 @@ class FrameInfo
StackValue* popped = &stack[spIndex];
if (adjust == AdjustStack && popped->kind() == StackValue::Stack)
masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
masm.addToStackPtr(Imm32(sizeof(Value)));
// Assert when anything uses this value.
popped->reset();
@ -241,7 +241,7 @@ class FrameInfo
pop(DontAdjustStack);
}
if (adjust == AdjustStack && poppedStack > 0)
masm.addPtr(Imm32(sizeof(Value) * poppedStack), BaselineStackReg);
masm.addToStackPtr(Imm32(sizeof(Value) * poppedStack));
}
inline void push(const Value& val) {
StackValue* sv = rawPush();

View File

@ -3956,7 +3956,7 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
masm.loadUnboxedProperty(BaseIndex(objReg, scratchReg, TimesOne), unboxedType_,
TypedOrValueRegister(R0));
if (popR1)
masm.addPtr(ImmWord(sizeof(size_t)), BaselineStackReg);
masm.addToStackPtr(ImmWord(sizeof(size_t)));
} else {
MOZ_ASSERT(acctype_ == ICGetElemNativeStub::NativeGetter ||
acctype_ == ICGetElemNativeStub::ScriptedGetter);
@ -5642,7 +5642,7 @@ ICInNativeCompiler::generateStubCode(MacroAssembler& masm)
masm.loadPtr(Address(ICStubReg, ICIn_NativePrototype::offsetOfHolderShape()),
scratch);
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failurePopR0Scratch);
masm.addPtr(Imm32(sizeof(size_t)), StackPointer);
masm.addToStackPtr(Imm32(sizeof(size_t)));
}
masm.moveValue(BooleanValue(true), R0);

View File

@ -3613,7 +3613,7 @@ CodeGenerator::generateArgumentsChecks(bool bailout)
continue;
Label skip;
Address addr(StackPointer, ArgToStackOffset((i - info.startArgSlot()) * sizeof(Value)));
Address addr(masm.getStackPointer(), ArgToStackOffset((i - info.startArgSlot()) * sizeof(Value)));
masm.branchTestObject(Assembler::NotEqual, addr, &skip);
Register obj = masm.extractObject(addr, temp);
masm.guardTypeSetMightBeIncomplete(types, obj, temp, &success);

View File

@ -1633,7 +1633,7 @@ MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
{
// Prepare a register set for use in this case.
AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
MOZ_ASSERT(!regs.has(BaselineStackReg));
MOZ_ASSERT(!regs.has(getStackPointer()));
regs.take(bailoutInfo);
// Reset SP to the point where clobbering starts.
@ -1654,7 +1654,7 @@ MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
subPtr(Imm32(4), copyCur);
subFromStackPtr(Imm32(4));
load32(Address(copyCur, 0), temp);
store32(temp, Address(BaselineStackReg, 0));
store32(temp, Address(getStackPointer(), 0));
jump(&copyLoop);
bind(&endOfCopy);
}
@ -2695,7 +2695,7 @@ MacroAssembler::Push(JSValueType type, Register reg)
void
MacroAssembler::PushValue(const Address& addr)
{
MOZ_ASSERT(addr.base != StackPointer);
MOZ_ASSERT(addr.base != getStackPointer());
pushValue(addr);
framePushed_ += sizeof(Value);
}

View File

@ -1012,15 +1012,20 @@ class ICStubCompiler
inline AllocatableGeneralRegisterSet availableGeneralRegs(size_t numInputs) const {
AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
MOZ_ASSERT(!regs.has(BaselineStackReg));
#if defined(JS_CODEGEN_ARM)
MOZ_ASSERT(!regs.has(BaselineStackReg));
MOZ_ASSERT(!regs.has(ICTailCallReg));
regs.take(BaselineSecondScratchReg);
#elif defined(JS_CODEGEN_MIPS)
MOZ_ASSERT(!regs.has(BaselineStackReg));
MOZ_ASSERT(!regs.has(ICTailCallReg));
MOZ_ASSERT(!regs.has(BaselineSecondScratchReg));
#elif defined(JS_CODEGEN_ARM64)
MOZ_ASSERT(!regs.has(PseudoStackPointer));
MOZ_ASSERT(!regs.has(RealStackPointer));
MOZ_ASSERT(!regs.has(ICTailCallReg));
#else
MOZ_ASSERT(!regs.has(BaselineStackReg));
#endif
regs.take(BaselineFrameReg);
regs.take(ICStubReg);

View File

@ -73,8 +73,6 @@ static constexpr FloatRegister ScratchSimdReg = InvalidFloatReg;
// StackPointer is intentionally undefined on ARM64 to prevent misuse:
// using sp as a base register is only valid if sp % 16 == 0.
static constexpr Register RealStackPointer = { Registers::sp };
// TODO: We're not quite there yet.
static constexpr Register StackPointer = { Registers::sp };
static constexpr Register PseudoStackPointer = { Registers::x28 };
static constexpr ARMRegister PseudoStackPointer64 = { Registers::x28, 64 };

View File

@ -16,9 +16,8 @@ namespace jit {
static constexpr Register BaselineFrameReg = r23;
static constexpr ARMRegister BaselineFrameReg64 = { BaselineFrameReg, 64 };
// The BaselineStackReg cannot be sp, because that register is treated
// as xzr/wzr during load/store operations.
static constexpr Register BaselineStackReg = PseudoStackPointer;
// BaselineStackReg is intentionally undefined on ARM64.
// Refer to the comment next to the definition of RealStackPointer.
// ValueOperands R0, R1, and R2.
// R0 == JSReturnReg, and R2 uses registers not preserved across calls.

View File

@ -5,6 +5,9 @@
* 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 "js/RootingAPI.h"
#include "js/TraceableHashTable.h"
#include "jsapi-tests/tests.h"
BEGIN_TEST(testGCExactRooting)
@ -152,3 +155,78 @@ BEGIN_TEST(testGCRootedDynamicStructInternalStackStorageAugmented)
return true;
}
END_TEST(testGCRootedDynamicStructInternalStackStorageAugmented)
using MyHashMap = js::TraceableHashMap<js::Shape*, JSObject*>;
BEGIN_TEST(testGCRootedHashMap)
{
JS::Rooted<MyHashMap> map(cx, MyHashMap(cx));
CHECK(map.init(15));
CHECK(map.initialized());
for (size_t i = 0; i < 10; ++i) {
RootedObject obj(cx, JS_NewObject(cx, nullptr));
RootedValue val(cx, UndefinedValue());
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
CHECK(JS_SetProperty(cx, obj, buffer, val));
CHECK(map.putNew(obj->as<NativeObject>().lastProperty(), obj));
}
JS_GC(rt);
JS_GC(rt);
for (auto r = map.all(); !r.empty(); r.popFront()) {
RootedObject obj(cx, r.front().value());
CHECK(obj->as<NativeObject>().lastProperty() == r.front().key());
}
return true;
}
END_TEST(testGCRootedHashMap)
static bool
FillMyHashMap(JSContext* cx, MutableHandle<MyHashMap> map)
{
for (size_t i = 0; i < 10; ++i) {
RootedObject obj(cx, JS_NewObject(cx, nullptr));
RootedValue val(cx, UndefinedValue());
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
if (!JS_SetProperty(cx, obj, buffer, val))
return false;
if (!map.putNew(obj->as<NativeObject>().lastProperty(), obj))
return false;
}
return true;
}
static bool
CheckMyHashMap(JSContext* cx, Handle<MyHashMap> map)
{
for (auto r = map.all(); !r.empty(); r.popFront()) {
RootedObject obj(cx, r.front().value());
if (obj->as<NativeObject>().lastProperty() != r.front().key())
return false;
}
return true;
}
BEGIN_TEST(testGCHandleHashMap)
{
JS::Rooted<MyHashMap> map(cx, MyHashMap(cx));
CHECK(map.init(15));
CHECK(map.initialized());
CHECK(FillMyHashMap(cx, &map));
JS_GC(rt);
JS_GC(rt);
CHECK(CheckMyHashMap(cx, map));
return true;
}
END_TEST(testGCHandleHashMap)

View File

@ -2507,7 +2507,7 @@ JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
/*** Property descriptors ************************************************************************/
struct JSPropertyDescriptor {
struct JSPropertyDescriptor : public JS::StaticTraceable {
JSObject* obj;
unsigned attrs;
JSGetterOp getter;
@ -2518,9 +2518,8 @@ struct JSPropertyDescriptor {
: obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue())
{}
static void trace(JSPropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
void trace(JSTracer* trc);
static js::ThingRootKind rootKind() { return js::THING_ROOT_PROPERTY_DESCRIPTOR; }
};
namespace JS {

View File

@ -666,19 +666,6 @@ typedef JS::AutoVectorRooter<JSString*> AutoStringVector;
typedef JS::AutoVectorRooter<PropertyName*> AutoPropertyNameVector;
typedef JS::AutoVectorRooter<Shape*> AutoShapeVector;
class AutoObjectUnsigned32HashMap : public AutoHashMapRooter<JSObject*, uint32_t>
{
public:
explicit AutoObjectUnsigned32HashMap(JSContext* cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoHashMapRooter<JSObject*, uint32_t>(cx, OBJU32HASHMAP)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/* AutoArrayRooter roots an external array of Values. */
class AutoArrayRooter : private JS::AutoGCRooter
{

View File

@ -272,7 +272,6 @@ class JS_PUBLIC_API(AutoGCRooter)
IONMASM = -19, /* js::jit::MacroAssembler */
WRAPVECTOR = -20, /* js::AutoWrapperVector */
WRAPPER = -21, /* js::AutoWrapperRooter */
OBJU32HASHMAP=-23, /* js::AutoObjectUnsigned32HashMap */
JSONPARSER = -25, /* js::JSONParser */
CUSTOM = -26 /* js::CustomAutoRooter */
};
@ -325,8 +324,6 @@ enum ThingRootKind
THING_ROOT_LAZY_SCRIPT,
THING_ROOT_ID,
THING_ROOT_VALUE,
THING_ROOT_PROPERTY_DESCRIPTOR,
THING_ROOT_PROP_DESC,
THING_ROOT_STATIC_TRACEABLE,
THING_ROOT_DYNAMIC_TRACEABLE,
THING_ROOT_LIMIT

View File

@ -122,6 +122,7 @@ EXPORTS.js += [
'../public/RootingAPI.h',
'../public/SliceBudget.h',
'../public/StructuredClone.h',
'../public/TraceableHashTable.h',
'../public/TraceKind.h',
'../public/TracingAPI.h',
'../public/TrackedOptimizationInfo.h',

View File

@ -1832,15 +1832,8 @@ js::IsDebugScopeSlow(ProxyObject* proxy)
/* static */ MOZ_ALWAYS_INLINE void
DebugScopes::liveScopesPostWriteBarrier(JSRuntime* rt, LiveScopeMap* map, ScopeObject* key)
{
// As above. Otherwise, barriers could fire during GC when moving the
// value.
typedef HashMap<ScopeObject*,
MissingScopeKey,
DefaultHasher<ScopeObject*>,
RuntimeAllocPolicy> UnbarrieredLiveScopeMap;
typedef gc::HashKeyRef<UnbarrieredLiveScopeMap, ScopeObject*> Ref;
if (key && IsInsideNursery(key))
rt->gc.storeBuffer.putGeneric(Ref(reinterpret_cast<UnbarrieredLiveScopeMap*>(map), key));
rt->gc.storeBuffer.putGeneric(gc::HashKeyRef<LiveScopeMap, ScopeObject*>(map, key));
}
DebugScopes::DebugScopes(JSContext* cx)

View File

@ -1521,8 +1521,11 @@ jit::JitActivation::getRematerializedFrame(JSContext* cx, const JitFrameIterator
if (!rematerializedFrames_) {
rematerializedFrames_ = cx->new_<RematerializedFrameTable>(cx);
if (!rematerializedFrames_ || !rematerializedFrames_->init()) {
if (!rematerializedFrames_)
return nullptr;
if (!rematerializedFrames_->init()) {
rematerializedFrames_ = nullptr;
ReportOutOfMemory(cx);
return nullptr;
}
}
@ -1531,8 +1534,10 @@ jit::JitActivation::getRematerializedFrame(JSContext* cx, const JitFrameIterator
RematerializedFrameTable::AddPtr p = rematerializedFrames_->lookupForAdd(top);
if (!p) {
RematerializedFrameVector empty(cx);
if (!rematerializedFrames_->add(p, top, Move(empty)))
if (!rematerializedFrames_->add(p, top, Move(empty))) {
ReportOutOfMemory(cx);
return nullptr;
}
// The unit of rematerialization is an uninlined frame and its inlined
// frames. Since inlined frames do not exist outside of snapshots, it

View File

@ -41,6 +41,7 @@
#include "builtin/MapObject.h"
#include "js/Date.h"
#include "js/TraceableHashTable.h"
#include "vm/SharedArrayObject.h"
#include "vm/TypedArrayObject.h"
#include "vm/WrapperObject.h"
@ -267,8 +268,9 @@ struct JSStructuredCloneWriter {
Value tVal)
: out(cx), objs(out.context()),
counts(out.context()), entries(out.context()),
memory(out.context()), callbacks(cb), closure(cbClosure),
transferable(out.context(), tVal), transferableObjects(out.context()) { }
memory(out.context(), CloneMemory(out.context())), callbacks(cb),
closure(cbClosure), transferable(out.context(), tVal), transferableObjects(out.context())
{}
~JSStructuredCloneWriter();
@ -283,6 +285,9 @@ struct JSStructuredCloneWriter {
}
private:
JSStructuredCloneWriter() = delete;
JSStructuredCloneWriter(const JSStructuredCloneWriter&) = delete;
JSContext* context() { return out.context(); }
bool writeTransferMap();
@ -324,8 +329,8 @@ struct JSStructuredCloneWriter {
// The "memory" list described in the HTML5 internal structured cloning algorithm.
// memory is a superset of objs; items are never removed from Memory
// until a serialization operation is finished
typedef AutoObjectUnsigned32HashMap CloneMemory;
CloneMemory memory;
using CloneMemory = TraceableHashMap<JSObject*, uint32_t>;
Rooted<CloneMemory> memory;
// The user defined callbacks that will be used for cloning.
const JSStructuredCloneCallbacks* callbacks;

View File

@ -3495,8 +3495,8 @@ nsDisplayBoxShadowOuter::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilde
oldShadow = geometry->mBounds;
newShadow = GetBounds(aBuilder, &snap);
} else {
oldShadow = oldShadow.Sub(geometry->mBounds, geometry->mBorderRect);
newShadow = newShadow.Sub(GetBounds(aBuilder, &snap), GetBorderRect());
oldShadow.Sub(geometry->mBounds, geometry->mBorderRect);
newShadow.Sub(GetBounds(aBuilder, &snap), GetBorderRect());
}
aInvalidRegion->Or(oldShadow, newShadow);
}

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