Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2014-09-25 16:46:51 -04:00
commit 4cf7455ce4
370 changed files with 47130 additions and 2679 deletions

View File

@ -104,7 +104,7 @@ var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
// or has a flat subtree.
function isSingleLineage(acc) {
for (let child = acc; child; child = child.firstChild) {
if (child.childCount > 1) {
if (Utils.visibleChildCount(child) > 1) {
return false;
}
}
@ -118,7 +118,7 @@ var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
if ([Roles.TEXT_LEAF, Roles.STATICTEXT].indexOf(child.role) >= 0) {
continue;
}
if (child.childCount > 0 || child.actionCount > 0) {
if (Utils.visibleChildCount(child) > 0 || child.actionCount > 0) {
return false;
}
}

View File

@ -360,6 +360,16 @@ this.Utils = { // jshint ignore:line
return hidden && hidden === 'true';
},
visibleChildCount: function visibleChildCount(aAccessible) {
let count = 0;
for (let child = aAccessible.firstChild; child; child = child.nextSibling) {
if (!this.isHidden(child)) {
++count;
}
}
return count;
},
inHiddenSubtree: function inHiddenSubtree(aAccessible) {
for (let acc=aAccessible; acc; acc=acc.parent) {
if (this.isHidden(acc)) {

View File

@ -3,6 +3,11 @@
<head>
<title>Traversal Rule test document</title>
<meta charset="utf-8" />
<style>
.content:before {
content: "Content";
}
</style>
</head>
<body>
<h3 id="heading-1">A small first heading</h3>
@ -96,6 +101,25 @@
<td>1</td>
</tr>
</table>
<section id="grid" role="grid">
<ol role="row">
<li role="presentation"></li>
<li role="columnheader" aria-label="Sunday">S</li>
<li role="columnheader">M</li>
</ol>
<ol role="row">
<li role="rowheader" aria-label="Week 1">1</li>
<li role="gridcell"><span>3</span><div></div></li>
<li role="gridcell"><span>4</span><div>7</div></li>
</ol>
<ol role="row">
<li role="rowheader">2</li>
<li role="gridcell"><span>5</span><div role="presentation">8</div></li>
<li id="gridcell4" role="gridcell">
<span>6</span><div aria-hidden="true"><div class="content"></div></div>
</li>
</ol>
</section>
<div id="separator-2" role="separator">Just an innocuous separator</div>
<table id="table-2">
<thead>

View File

@ -94,7 +94,7 @@
['separator-1', 'separator-2']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Table, null,
['table-1', 'table-2']);
['table-1', 'grid', 'table-2']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Simple, null,
['heading-1', 'Name:', 'input-1-1', 'label-1-2',
@ -114,13 +114,15 @@
' power is unfathomable.',
'• Lists of Programming Languages', 'Lisp ',
'1. Scheme', '2. Racket', '3. Clojure',
'4. Standard Lisp', 'link-0', ' Lisp', 'checkbox-1-5',
' LeLisp', '• JavaScript', 'heading-5',
'image-2', 'image-3', 'Not actually an image',
'link-1', 'anchor-1', 'link-2', 'anchor-2', 'link-3',
'3', '1', '4', '1', 'Just an innocuous separator',
'Dirty Words', 'Meaning', 'Mud', 'Wet Dirt',
'Dirt', 'Messy Stuff']);
'4. Standard Lisp', 'link-0', ' Lisp',
'checkbox-1-5', ' LeLisp', '• JavaScript',
'heading-5', 'image-2', 'image-3',
'Not actually an image', 'link-1', 'anchor-1',
'link-2', 'anchor-2', 'link-3', '3', '1', '4',
'1', 'S', 'M', '1', '3', '4', '7', '2', '5', '8',
'6', 'Just an innocuous separator', 'Dirty Words',
'Meaning', 'Mud', 'Wet Dirt', 'Dirt',
'Messy Stuff']);
gQueue.invoke();
}

View File

@ -105,7 +105,7 @@ function test() {
function test1(aCallback) {
gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => {
checkWatchExpressions(26, {
a: "ReferenceError: a is not defined, did you mean 'z'?",
a: "ReferenceError: a is not defined",
this: { type: "object", class: "Object" },
prop: { type: "object", class: "String" },
args: { type: "undefined" }

View File

@ -173,6 +173,9 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
if (!mPolicies[p]->permits(aContentType,
aContentLocation,
nonce,
// aExtra is only non-null if
// the channel got redirected.
(aExtra != nullptr),
violatedDirective)) {
// If the policy is violated and not report-only, reject the load and
// report to the console
@ -792,7 +795,8 @@ class CSPReportSenderRunnable MOZ_FINAL : public nsRunnable
uint64_t aInnerWindowID,
nsCSPContext* aCSPContext)
: mBlockedContentSource(aBlockedContentSource)
, mOriginalURI(aOriginalURI) , mViolatedPolicyIndex(aViolatedPolicyIndex)
, mOriginalURI(aOriginalURI)
, mViolatedPolicyIndex(aViolatedPolicyIndex)
, mReportOnlyFlag(aReportOnlyFlag)
, mViolatedDirective(aViolatedDirective)
, mSourceFile(aSourceFile)
@ -1024,6 +1028,7 @@ nsCSPContext::PermitsAncestry(nsIDocShell* aDocShell, bool* outPermitsAncestry)
if (!mPolicies[i]->permits(nsIContentPolicy::TYPE_DOCUMENT,
ancestorsArray[a],
EmptyString(), // no nonce
false, // no redirect
violatedDirective)) {
// Policy is violated
// Send reports, but omit the ancestor URI if cross-origin as per spec

View File

@ -30,18 +30,21 @@ GetCspParserLog()
#define CSPPARSERLOG(args) PR_LOG(GetCspParserLog(), 4, args)
static const char16_t COLON = ':';
static const char16_t SEMICOLON = ';';
static const char16_t SLASH = '/';
static const char16_t PLUS = '+';
static const char16_t DASH = '-';
static const char16_t DOT = '.';
static const char16_t UNDERLINE = '_';
static const char16_t WILDCARD = '*';
static const char16_t WHITESPACE = ' ';
static const char16_t SINGLEQUOTE = '\'';
static const char16_t OPEN_CURL = '{';
static const char16_t CLOSE_CURL = '}';
static const char16_t COLON = ':';
static const char16_t SEMICOLON = ';';
static const char16_t SLASH = '/';
static const char16_t PLUS = '+';
static const char16_t DASH = '-';
static const char16_t DOT = '.';
static const char16_t UNDERLINE = '_';
static const char16_t TILDE = '~';
static const char16_t WILDCARD = '*';
static const char16_t WHITESPACE = ' ';
static const char16_t SINGLEQUOTE = '\'';
static const char16_t OPEN_CURL = '{';
static const char16_t CLOSE_CURL = '}';
static const char16_t NUMBER_SIGN = '#';
static const char16_t QUESTIONMARK = '?';
static uint32_t kSubHostPathCharacterCutoff = 512;
@ -145,6 +148,23 @@ nsCSPParser::resetCurChar(const nsAString& aToken)
resetCurValue();
}
// The path is terminated by the first question mark ("?") or
// number sign ("#") character, or by the end of the URI.
// http://tools.ietf.org/html/rfc3986#section-3.3
bool
nsCSPParser::atEndOfPath()
{
return (atEnd() || peek(QUESTIONMARK) || peek(NUMBER_SIGN));
}
bool
nsCSPParser::atValidPathChar()
{
return (peek(isCharacterToken) || peek(isNumberToken) ||
peek(DASH) || peek(DOT) ||
peek(UNDERLINE) || peek(TILDE));
}
void
nsCSPParser::logWarningErrorToConsole(uint32_t aSeverityFlag,
const char* aProperty,
@ -189,25 +209,6 @@ nsCSPParser::schemeChar()
accept(DOT);
}
bool
nsCSPParser::fileAndArguments()
{
CSPPARSERLOG(("nsCSPParser::fileAndArguments, mCurToken: %s, mCurValue: %s",
NS_ConvertUTF16toUTF8(mCurToken).get(),
NS_ConvertUTF16toUTF8(mCurValue).get()));
// Possibly we already parsed part of the file in path(), therefore accepting "."
if (accept(DOT) && !accept(isCharacterToken)) {
return false;
}
// From now on, accept pretty much anything to avoid unnecessary errors
while (!atEnd()) {
advance();
}
return true;
}
// port = ":" ( 1*DIGIT / "*" )
bool
nsCSPParser::port()
@ -253,24 +254,23 @@ nsCSPParser::subPath(nsCSPHostSrc* aCspHost)
// in case we are parsing unrecognized characters in the following loop.
uint32_t charCounter = 0;
while (!atEnd() && !peek(DOT)) {
++charCounter;
while (hostChar() || accept(UNDERLINE)) {
/* consume */
++charCounter;
}
if (accept(SLASH)) {
++charCounter;
while (!atEndOfPath()) {
if (peek(SLASH)) {
aCspHost->appendPath(mCurValue);
// Resetting current value since we are appending parts of the path
// to aCspHost, e.g; "http://www.example.com/path1/path2" then the
// first part is "/path1", second part "/path2"
resetCurValue();
}
if (atEnd()) {
return true;
else if (!atValidPathChar()) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag,
"couldntParseInvalidSource",
params, ArrayLength(params));
return false;
}
if (charCounter > kSubHostPathCharacterCutoff) {
advance();
if (++charCounter > kSubHostPathCharacterCutoff) {
return false;
}
}
@ -298,7 +298,10 @@ nsCSPParser::path(nsCSPHostSrc* aCspHost)
params, ArrayLength(params));
return false;
}
if (atEnd()) {
if (atEndOfPath()) {
// one slash right after host [port] is also considered a path, e.g.
// www.example.com/ should result in www.example.com/
aCspHost->appendPath(mCurValue);
return true;
}
// path can begin with "/" but not "//"
@ -324,7 +327,7 @@ nsCSPParser::subHost()
// in case we are parsing unrecognized characters in the following loop.
uint32_t charCounter = 0;
while (!atEnd() && !peek(COLON) && !peek(SLASH)) {
while (!atEndOfPath() && !peek(COLON) && !peek(SLASH)) {
++charCounter;
while (hostChar()) {
/* consume */
@ -468,7 +471,7 @@ nsCSPParser::hostSource()
cspHost->setPort(mCurValue);
}
if (atEnd()) {
if (atEndOfPath()) {
return cspHost;
}
@ -482,14 +485,6 @@ nsCSPParser::hostSource()
delete cspHost;
return nullptr;
}
// Calling fileAndArguments to see if there are any files to parse;
// if an error occurs, fileAndArguments() reports the error; if
// fileAndArguments returns true, we have a valid file, so we add it.
if (fileAndArguments()) {
cspHost->setFileAndArguments(mCurValue);
}
return cspHost;
}

View File

@ -126,7 +126,6 @@ class nsCSPParser {
bool schemeChar();
bool port();
bool path(nsCSPHostSrc* aCspHost);
bool fileAndArguments();
bool subHost(); // helper function to parse subDomains
bool subPath(nsCSPHostSrc* aCspHost); // helper function to parse paths
@ -173,6 +172,9 @@ class nsCSPParser {
mCurValue.Truncate();
}
bool atEndOfPath();
bool atValidPathChar();
void resetCurChar(const nsAString& aToken);
void logWarningErrorToConsole(uint32_t aSeverityFlag,

View File

@ -214,7 +214,7 @@ nsCSPBaseSrc::~nsCSPBaseSrc()
// nsCSPKeywordSrc and nsCSPHashSource fall back to this base class
// implementation which will never allow the load.
bool
nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -251,7 +251,7 @@ nsCSPSchemeSrc::~nsCSPSchemeSrc()
}
bool
nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -288,7 +288,7 @@ nsCSPHostSrc::~nsCSPHostSrc()
}
bool
nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -342,6 +342,34 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
return false;
}
// If there is a path, we have to enforce path-level matching,
// unless the channel got redirected, see:
// http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects
if (!aWasRedirected && !mPath.IsEmpty()) {
// cloning uri so we can ignore the ref
nsCOMPtr<nsIURI> uri;
aUri->CloneIgnoringRef(getter_AddRefs(uri));
nsAutoCString uriPath;
rv = uri->GetPath(uriPath);
NS_ENSURE_SUCCESS(rv, false);
// check if the last character of mPath is '/'; if so
// we just have to check loading resource is within
// the allowed path.
if (mPath.Last() == '/') {
if (!StringBeginsWith(NS_ConvertUTF8toUTF16(uriPath), mPath)) {
return false;
}
}
// otherwise mPath whitelists a specific file, and we have to
// check if the loading resource matches that whitelisted file.
else {
if (!mPath.Equals(NS_ConvertUTF8toUTF16(uriPath))) {
return false;
}
}
}
// If port uses wildcard, allow the load.
if (mPort.EqualsASCII("*")) {
return true;
@ -369,7 +397,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
}
}
// At the end: scheme, host, port, match; allow the load.
// At the end: scheme, host, path, and port match -> allow the load.
return true;
}
@ -397,9 +425,8 @@ nsCSPHostSrc::toString(nsAString& outStr) const
outStr.Append(mPort);
}
// in CSP 1.1, paths are ignoed
// outStr.Append(mPath);
// outStr.Append(mFileAndArguments);
// append path
outStr.Append(mPath);
}
void
@ -423,13 +450,6 @@ nsCSPHostSrc::appendPath(const nsAString& aPath)
ToLowerCase(mPath);
}
void
nsCSPHostSrc::setFileAndArguments(const nsAString& aFile)
{
mFileAndArguments = aFile;
ToLowerCase(mFileAndArguments);
}
/* ===== nsCSPKeywordSrc ===================== */
nsCSPKeywordSrc::nsCSPKeywordSrc(CSPKeyword aKeyword)
@ -469,7 +489,7 @@ nsCSPNonceSrc::~nsCSPNonceSrc()
}
bool
nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -599,7 +619,7 @@ nsCSPDirective::~nsCSPDirective()
}
bool
nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -610,7 +630,7 @@ nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce) const
#endif
for (uint32_t i = 0; i < mSrcs.Length(); i++) {
if (mSrcs[i]->permits(aUri, aNonce)) {
if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected)) {
return true;
}
}
@ -621,7 +641,7 @@ bool
nsCSPDirective::permits(nsIURI* aUri) const
{
nsString dummyNonce;
return permits(aUri, dummyNonce);
return permits(aUri, dummyNonce, false);
}
bool
@ -754,6 +774,7 @@ bool
nsCSPPolicy::permits(nsContentPolicyType aContentType,
nsIURI* aUri,
const nsAString& aNonce,
bool aWasRedirected,
nsAString& outViolatedDirective) const
{
#ifdef PR_LOGGING
@ -774,7 +795,7 @@ nsCSPPolicy::permits(nsContentPolicyType aContentType,
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
// Check if the directive name matches
if (mDirectives[i]->restrictsContentType(aContentType)) {
if (!mDirectives[i]->permits(aUri, aNonce)) {
if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected)) {
mDirectives[i]->toString(outViolatedDirective);
return false;
}
@ -795,7 +816,7 @@ nsCSPPolicy::permits(nsContentPolicyType aContentType,
// If the above loop runs through, we haven't found a matching directive.
// Avoid relooping, just store the result of default-src while looping.
if (defaultDir) {
if (!defaultDir->permits(aUri, aNonce)) {
if (!defaultDir->permits(aUri, aNonce, aWasRedirected)) {
defaultDir->toString(outViolatedDirective);
return false;
}

View File

@ -191,7 +191,7 @@ class nsCSPBaseSrc {
nsCSPBaseSrc();
virtual ~nsCSPBaseSrc();
virtual bool permits(nsIURI* aUri, const nsAString& aNonce) const;
virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
virtual void toString(nsAString& outStr) const = 0;
};
@ -203,7 +203,7 @@ class nsCSPSchemeSrc : public nsCSPBaseSrc {
explicit nsCSPSchemeSrc(const nsAString& aScheme);
virtual ~nsCSPSchemeSrc();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
void toString(nsAString& outStr) const;
private:
@ -217,20 +217,18 @@ class nsCSPHostSrc : public nsCSPBaseSrc {
explicit nsCSPHostSrc(const nsAString& aHost);
virtual ~nsCSPHostSrc();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
void toString(nsAString& outStr) const;
void setScheme(const nsAString& aScheme);
void setPort(const nsAString& aPort);
void appendPath(const nsAString &aPath);
void setFileAndArguments(const nsAString& aFile);
private:
nsString mScheme;
nsString mHost;
nsString mPort;
nsString mPath;
nsString mFileAndArguments;
};
/* =============== nsCSPKeywordSrc ============ */
@ -254,7 +252,7 @@ class nsCSPNonceSrc : public nsCSPBaseSrc {
explicit nsCSPNonceSrc(const nsAString& aNonce);
virtual ~nsCSPNonceSrc();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
void toString(nsAString& outStr) const;
@ -298,7 +296,7 @@ class nsCSPDirective {
explicit nsCSPDirective(enum CSPDirective aDirective);
virtual ~nsCSPDirective();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
bool permits(nsIURI* aUri) const;
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
void toString(nsAString& outStr) const;
@ -331,6 +329,7 @@ class nsCSPPolicy {
bool permits(nsContentPolicyType aContentType,
nsIURI* aUri,
const nsAString& aNonce,
bool aWasRedirected,
nsAString& outViolatedDirective) const;
bool permitsBaseURI(nsIURI* aUri) const;
bool allows(nsContentPolicyType aContentType,

View File

@ -1033,7 +1033,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
JS::Rooted<JS::Value> thisValue(cx, JS::UndefinedValue());
JS::Rooted<JS::Value> funval(cx);
if (JS_ObjectIsCallable(cx, object)) {
if (JS::IsCallable(object)) {
// If the listener is a JS function:
funval.setObject(*object);
@ -1055,7 +1055,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
return NS_ERROR_UNEXPECTED;
// Check if the object is even callable.
NS_ENSURE_STATE(JS_ObjectIsCallable(cx, &funval.toObject()));
NS_ENSURE_STATE(JS::IsCallable(&funval.toObject()));
thisValue.setObject(*object);
}

View File

@ -3980,7 +3980,7 @@ ArrayBufferBuilder::setCapacity(uint32_t aNewCap)
{
MOZ_ASSERT(!mMapPtr);
uint8_t *newdata = (uint8_t *) realloc(mDataPtr, aNewCap);
uint8_t *newdata = (uint8_t *) js_realloc(mDataPtr, aNewCap);
if (!newdata) {
return false;
}

View File

@ -287,52 +287,70 @@ nsresult TestIgnorePaths() {
{ "script-src http://www.example.com",
"script-src http://www.example.com" },
{ "script-src http://www.example.com/",
"script-src http://www.example.com" },
"script-src http://www.example.com/" },
{ "script-src http://www.example.com/path-1",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1" },
{ "script-src http://www.example.com/path-1/",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/" },
{ "script-src http://www.example.com/path-1/path_2",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/path_2" },
{ "script-src http://www.example.com/path-1/path_2/",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/path_2/" },
{ "script-src http://www.example.com/path-1/path_2/file.js",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/path_2/file.js" },
{ "script-src http://www.example.com/path-1/path_2/file_1.js",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/path_2/file_1.js" },
{ "script-src http://www.example.com/path-1/path_2/file-2.js",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/path_2/file-2.js" },
{ "script-src http://www.example.com/path-1/path_2/f.js",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1/path_2/f.js" },
{ "script-src http://www.example.com:88",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:88/",
"script-src http://www.example.com:88" },
"script-src http://www.example.com:88/" },
{ "script-src http://www.example.com:88/path-1",
"script-src http://www.example.com:88" },
"script-src http://www.example.com:88/path-1" },
{ "script-src http://www.example.com:88/path-1/",
"script-src http://www.example.com:88" },
"script-src http://www.example.com:88/path-1/" },
{ "script-src http://www.example.com:88/path-1/path_2",
"script-src http://www.example.com:88" },
"script-src http://www.example.com:88/path-1/path_2" },
{ "script-src http://www.example.com:88/path-1/path_2/",
"script-src http://www.example.com:88" },
"script-src http://www.example.com:88/path-1/path_2/" },
{ "script-src http://www.example.com:88/path-1/path_2/file.js",
"script-src http://www.example.com:88" },
"script-src http://www.example.com:88/path-1/path_2/file.js" },
{ "script-src http://www.example.com:*",
"script-src http://www.example.com:*" },
{ "script-src http://www.example.com:*/",
"script-src http://www.example.com:*" },
"script-src http://www.example.com:*/" },
{ "script-src http://www.example.com:*/path-1",
"script-src http://www.example.com:*" },
"script-src http://www.example.com:*/path-1" },
{ "script-src http://www.example.com:*/path-1/",
"script-src http://www.example.com:*" },
"script-src http://www.example.com:*/path-1/" },
{ "script-src http://www.example.com:*/path-1/path_2",
"script-src http://www.example.com:*" },
"script-src http://www.example.com:*/path-1/path_2" },
{ "script-src http://www.example.com:*/path-1/path_2/",
"script-src http://www.example.com:*" },
"script-src http://www.example.com:*/path-1/path_2/" },
{ "script-src http://www.example.com:*/path-1/path_2/file.js",
"script-src http://www.example.com:*" },
{ "report-uri http://www.example.com",
"script-src http://www.example.com:*/path-1/path_2/file.js" },
{ "script-src http://www.example.com#foo",
"script-src http://www.example.com" },
{ "script-src http://www.example.com?foo=bar",
"script-src http://www.example.com" },
{ "script-src http://www.example.com:8888#foo",
"script-src http://www.example.com:8888" },
{ "script-src http://www.example.com:8888?foo",
"script-src http://www.example.com:8888" },
{ "script-src http://www.example.com/#foo",
"script-src http://www.example.com/" },
{ "script-src http://www.example.com/?foo",
"script-src http://www.example.com/" },
{ "script-src http://www.example.com/path-1/file.js#foo",
"script-src http://www.example.com/path-1/file.js" },
{ "script-src http://www.example.com/path-1/file.js?foo",
"script-src http://www.example.com/path-1/file.js" },
{ "script-src http://www.example.com/path-1/file.js?foo#bar",
"script-src http://www.example.com/path-1/file.js" },
{ "report-uri http://www.example.com/",
"report-uri http://www.example.com/" },
{ "report-uri http://www.example.com:8888/asdf",
"report-uri http://www.example.com:8888/asdf" },
@ -401,9 +419,9 @@ nsresult TestSimplePolicies() {
{ "script-src 'none' 'none' 'none';",
"script-src 'none'" },
{ "script-src http://www.example.com/path-1//",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1//" },
{ "script-src http://www.example.com/path-1//path_2",
"script-src http://www.example.com" },
"script-src http://www.example.com/path-1//path_2" },
{ "default-src 127.0.0.1",
"default-src http://127.0.0.1" },
{ "default-src 127.0.0.1:*",
@ -619,21 +637,21 @@ nsresult TestGoodGeneratedPolicies() {
{ "connect-src https://three:81",
"connect-src https://three:81" },
{ "script-src http://self.com:80/foo",
"script-src http://self.com:80" },
"script-src http://self.com:80/foo" },
{ "object-src http://self.com/foo",
"object-src http://self.com" },
"object-src http://self.com/foo" },
{ "report-uri /report.py",
"report-uri http://www.selfuri.com/report.py"},
{ "img-src http://foo.org:34/report.py",
"img-src http://foo.org:34" },
"img-src http://foo.org:34/report.py" },
{ "media-src foo/bar/report.py",
"media-src http://foo" },
"media-src http://foo/bar/report.py" },
{ "report-uri /",
"report-uri http://www.selfuri.com/"},
{ "font-src https://self.com/report.py",
"font-src https://self.com" },
"font-src https://self.com/report.py" },
{ "connect-src https://foo.com/report.py",
"connect-src https://foo.com" },
"connect-src https://foo.com/report.py" },
{ "default-src *; report-uri http://www.reporturi.com/",
"default-src *; report-uri http://www.reporturi.com/" },
{ "default-src http://first.com",
@ -651,15 +669,15 @@ nsresult TestGoodGeneratedPolicies() {
{ "frame-src http://bar.com",
"frame-src http://bar.com" },
{ "font-src http://self.com/",
"font-src http://self.com" },
"font-src http://self.com/" },
{ "script-src 'self'",
"script-src http://www.selfuri.com" },
{ "default-src http://self.com/foo.png",
"default-src http://self.com" },
"default-src http://self.com/foo.png" },
{ "script-src http://self.com/foo.js",
"script-src http://self.com" },
"script-src http://self.com/foo.js" },
{ "object-src http://bar.com/foo.js",
"object-src http://bar.com" },
"object-src http://bar.com/foo.js" },
{ "style-src http://FOO.COM",
"style-src http://foo.com" },
{ "img-src HTTP",
@ -697,11 +715,11 @@ nsresult TestGoodGeneratedPolicies() {
{ "frame-ancestors http://self:80",
"frame-ancestors http://self:80" },
{ "frame-ancestors http://self.com/bar",
"frame-ancestors http://self.com" },
"frame-ancestors http://self.com/bar" },
{ "default-src 'self'; frame-ancestors 'self'",
"default-src http://www.selfuri.com; frame-ancestors http://www.selfuri.com" },
{ "frame-ancestors http://bar.com/foo.png",
"frame-ancestors http://bar.com" },
"frame-ancestors http://bar.com/foo.png" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -747,111 +765,111 @@ nsresult TestGoodGeneratedPoliciesForPathHandling() {
{ "img-src http://test1.example.com",
"img-src http://test1.example.com" },
{ "img-src http://test1.example.com/",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/" },
{ "img-src http://test1.example.com/path-1",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1" },
{ "img-src http://test1.example.com/path-1/",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/" },
{ "img-src http://test1.example.com/path-1/path_2/",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/" },
{ "img-src http://test1.example.com/path-1/path_2/file.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/file.js" },
{ "img-src http://test1.example.com/path-1/path_2/file_1.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/file_1.js" },
{ "img-src http://test1.example.com/path-1/path_2/file-2.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/file-2.js" },
{ "img-src http://test1.example.com/path-1/path_2/f.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/f.js" },
{ "img-src http://test1.example.com/path-1/path_2/f.oo.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/f.oo.js" },
{ "img-src test1.example.com",
"img-src http://test1.example.com" },
{ "img-src test1.example.com/",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/" },
{ "img-src test1.example.com/path-1",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1" },
{ "img-src test1.example.com/path-1/",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/" },
{ "img-src test1.example.com/path-1/path_2/",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/" },
{ "img-src test1.example.com/path-1/path_2/file.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/file.js" },
{ "img-src test1.example.com/path-1/path_2/file_1.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/file_1.js" },
{ "img-src test1.example.com/path-1/path_2/file-2.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/file-2.js" },
{ "img-src test1.example.com/path-1/path_2/f.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/f.js" },
{ "img-src test1.example.com/path-1/path_2/f.oo.js",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/path-1/path_2/f.oo.js" },
{ "img-src *.example.com",
"img-src http://*.example.com" },
{ "img-src *.example.com/",
"img-src http://*.example.com" },
"img-src http://*.example.com/" },
{ "img-src *.example.com/path-1",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1" },
{ "img-src *.example.com/path-1/",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/" },
{ "img-src *.example.com/path-1/path_2/",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/path_2/" },
{ "img-src *.example.com/path-1/path_2/file.js",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/path_2/file.js" },
{ "img-src *.example.com/path-1/path_2/file_1.js",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/path_2/file_1.js" },
{ "img-src *.example.com/path-1/path_2/file-2.js",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/path_2/file-2.js" },
{ "img-src *.example.com/path-1/path_2/f.js",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/path_2/f.js" },
{ "img-src *.example.com/path-1/path_2/f.oo.js",
"img-src http://*.example.com" },
"img-src http://*.example.com/path-1/path_2/f.oo.js" },
{ "img-src test1.example.com:80",
"img-src http://test1.example.com:80" },
{ "img-src test1.example.com:80/",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/" },
{ "img-src test1.example.com:80/path-1",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/path-1" },
{ "img-src test1.example.com:80/path-1/",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/path-1/" },
{ "img-src test1.example.com:80/path-1/path_2",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/path-1/path_2" },
{ "img-src test1.example.com:80/path-1/path_2/",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/path-1/path_2/" },
{ "img-src test1.example.com:80/path-1/path_2/file.js",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/path-1/path_2/file.js" },
{ "img-src test1.example.com:80/path-1/path_2/f.ile.js",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/path-1/path_2/f.ile.js" },
{ "img-src test1.example.com:*",
"img-src http://test1.example.com:*" },
{ "img-src test1.example.com:*/",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/" },
{ "img-src test1.example.com:*/path-1",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/path-1" },
{ "img-src test1.example.com:*/path-1/",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/path-1/" },
{ "img-src test1.example.com:*/path-1/path_2",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/path-1/path_2" },
{ "img-src test1.example.com:*/path-1/path_2/",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/path-1/path_2/" },
{ "img-src test1.example.com:*/path-1/path_2/file.js",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/path-1/path_2/file.js" },
{ "img-src test1.example.com:*/path-1/path_2/f.ile.js",
"img-src http://test1.example.com:*" },
"img-src http://test1.example.com:*/path-1/path_2/f.ile.js" },
{ "img-src http://test1.example.com/abc//",
"img-src http://test1.example.com" },
"img-src http://test1.example.com/abc//" },
{ "img-src https://test1.example.com/abc/def//",
"img-src https://test1.example.com" },
"img-src https://test1.example.com/abc/def//" },
{ "img-src https://test1.example.com/abc/def/ghi//",
"img-src https://test1.example.com" },
"img-src https://test1.example.com/abc/def/ghi//" },
{ "img-src http://test1.example.com:80/abc//",
"img-src http://test1.example.com:80" },
"img-src http://test1.example.com:80/abc//" },
{ "img-src https://test1.example.com:80/abc/def//",
"img-src https://test1.example.com:80" },
"img-src https://test1.example.com:80/abc/def//" },
{ "img-src https://test1.example.com:80/abc/def/ghi//",
"img-src https://test1.example.com:80" },
"img-src https://test1.example.com:80/abc/def/ghi//" },
{ "img-src https://test1.example.com/abc////////////def/",
"img-src https://test1.example.com" },
"img-src https://test1.example.com/abc////////////def/" },
{ "img-src https://test1.example.com/abc////////////",
"img-src https://test1.example.com" },
"img-src https://test1.example.com/abc////////////" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);

View File

@ -223,7 +223,7 @@
// (the privileged junk scope, but we don't have a good way to test for that
// specifically).
is(unprivilegedObject.expando, undefined, "parent->child references should get Xrays");
todo_is(unprivilegedObject.wrappedJSObject.expando, 42, "parent->child references should get waivable Xrays - see bug 1065811");
is(unprivilegedObject.wrappedJSObject.expando, 42, "parent->child references should get waivable Xrays");
// Send an object to the child to let it verify invariants in the other direction.
function passMe() { return 42; };

View File

@ -1,10 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 916054 - URLs with path are ignored by FF's CSP parser</title>
<title>Bug 808292 - Implement path-level host-source matching to CSP</title>
</head>
<body>
<div id="testdiv">blocked</div>
<script src="http://test1.example.com/tests/content/base/test/csp/file_csp_regexp_parsing.js"></script>
<script src="http://test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js#foo"></script>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 808292 - Implement path-level host-source matching to CSP</title>
</head>
<body>
<div id="testdiv">blocked</div>
<script src="http://example.com/tests/content/base/test/csp/file_csp_path_matching_redirect_server.sjs"></script>
</body>
</html>

View File

@ -0,0 +1,13 @@
// Redirect server specifically to handle redirects
// for path-level host-source matching
// see https://bugzilla.mozilla.org/show_bug.cgi?id=808292
function handleRequest(request, response)
{
var newLocation = "http://test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js";
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Location", newLocation, false);
}

View File

@ -81,9 +81,11 @@ support-files =
file_hash_source.html^headers^
file_self_none_as_hostname_confusion.html
file_self_none_as_hostname_confusion.html^headers^
file_csp_path_matching.html
file_csp_path_matching.js
file_csp_path_matching_redirect.html
file_csp_path_matching_redirect_server.sjs
file_csp_testserver.sjs
file_csp_regexp_parsing.html
file_csp_regexp_parsing.js
file_report_uri_missing_in_report_only_header.html
file_report_uri_missing_in_report_only_header.html^headers^
file_csp_report.html
@ -121,7 +123,8 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'and
skip-if = e10s || buildapp == 'b2g' # can't compute hashes in child process (bug 958702)
[test_self_none_as_hostname_confusion.html]
[test_bug949549.html]
[test_csp_regexp_parsing.html]
[test_csp_path_matching.html]
[test_csp_path_matching_redirect.html]
[test_report_uri_missing_in_report_only_header.html]
[test_csp_report.html]
skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observer not supported in child process (bug 1009632)

View File

@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 916054 - URLs with path are ignored by FF's CSP parser</title>
<title>Bug 808292 - Implement path-level host-source matching to CSP</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
@ -16,49 +16,51 @@
SimpleTest.waitForExplicitFinish();
/* Description of the test:
* We are loading the following url (including a fragment portion):
* http://test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js#foo
* using different policies and verify that the applied policy is accurately enforced.
*/
var policies = [
["allowed", "*"],
["allowed", "test1.example.com"],
["allowed", "test1.example.com/"],
["allowed", "test1.example.com/path-1"],
["allowed", "test1.example.com/path-1/"],
["allowed", "test1.example.com/path-1/path_2/"],
["allowed", "test1.example.com/path-1/path_2/file.js"],
["allowed", "test1.example.com/path-1/path_2/file_1.js"],
["allowed", "test1.example.com/path-1/path_2/file-2.js"],
["allowed", "test1.example.com/path-1/path_2/f.js"],
["allowed", "test1.example.com/path-1/path_2/f.oo.js"],
["allowed", "test1.example.com/tests/content/base/test/csp/"],
["allowed", "test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js"],
["allowed", "test1.example.com?foo=val"],
["allowed", "test1.example.com/?foo=val"],
["allowed", "test1.example.com/tests/content/base/test/csp/?foo=val"],
["allowed", "test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js?foo=val"],
["allowed", "test1.example.com#foo"],
["allowed", "test1.example.com/#foo"],
["allowed", "test1.example.com/tests/content/base/test/csp/#foo"],
["allowed", "test1.example.com/tests/content/base/test/csp/file_csp_path_matching.js#foo"],
["allowed", "*.example.com"],
["allowed", "*.example.com/"],
["allowed", "*.example.com/path-1"],
["allowed", "*.example.com/path-1/"],
["allowed", "*.example.com/path-1/path_2/"],
["allowed", "*.example.com/path-1/path_2/file.js"],
["allowed", "*.example.com/path-1/path_2/file_1.js"],
["allowed", "*.example.com/path-1/path_2/file-2.js"],
["allowed", "*.example.com/path-1/path_2/f.js"],
["allowed", "*.example.com/path-1/path_2/f.oo.js"],
["allowed", "*.example.com/tests/content/base/test/csp/"],
["allowed", "*.example.com/tests/content/base/test/csp/file_csp_path_matching.js"],
["allowed", "test1.example.com:80"],
["allowed", "test1.example.com:80/"],
["allowed", "test1.example.com:80/path-1"],
["allowed", "test1.example.com:80/path-1/"],
["allowed", "test1.example.com:80/path-1/path_2"],
["allowed", "test1.example.com:80/path-1/path_2/"],
["allowed", "test1.example.com:80/path-1/path_2/file.js"],
["allowed", "test1.example.com:80/path-1/path_2/f.ile.js"],
["allowed", "test1.example.com:80/tests/content/base/test/csp/"],
["allowed", "test1.example.com:80/tests/content/base/test/csp/file_csp_path_matching.js"],
["allowed", "test1.example.com:*"],
["allowed", "test1.example.com:*/"],
["allowed", "test1.example.com:*/path-1"],
["allowed", "test1.example.com:*/path-1/"],
["allowed", "test1.example.com:*/path-1/path_2"],
["allowed", "test1.example.com:*/path-1/path_2/"],
["allowed", "test1.example.com:*/path-1/path_2/file.js"],
["allowed", "test1.example.com:*/path-1/path_2/f.ile.js"],
// the following tests should fail
["blocked", "test1.example.com:88path-1/"],
["blocked", "test1.example.com:80.js"],
["blocked", "test1.example.com:*.js"],
["blocked", "test1.example.com:*."]
["allowed", "test1.example.com:*/tests/content/base/test/csp/"],
["allowed", "test1.example.com:*/tests/content/base/test/csp/file_csp_path_matching.js"],
["blocked", "test1.example.com/tests"],
["blocked", "test1.example.com/tests/content/base/test/csp"],
["blocked", "test1.example.com/tests/content/base/test/csp/file_csp_path_matching.py"],
["blocked", "test1.example.com:8888/tests"],
["blocked", "test1.example.com:8888/tests/content/base/test/csp"],
["blocked", "test1.example.com:8888/tests/content/base/test/csp/file_csp_path_matching.py"],
]
var counter = 0;
@ -72,7 +74,7 @@ function loadNextTest() {
policy = policies[counter++];
var src = "file_csp_testserver.sjs";
// append the file that should be served
src += "?file=" + escape("tests/content/base/test/csp/file_csp_regexp_parsing.html");
src += "?file=" + escape("tests/content/base/test/csp/file_csp_path_matching.html");
// append the CSP that should be used to serve the file
src += "&csp=" + escape("default-src 'none'; script-src " + policy[1]);

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 808292 - Implement path-level host-source matching to CSP (redirects)</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="visibility: hidden">
<iframe style="width:100%;" id="testframe"></iframe>
</div>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
/* Description of the test:
* First, we try to load a script where the *path* does not match.
* Second, we try to load a script which is allowed by the CSPs
* script-src directive. The script then gets redirected to
* an URL where the host matches, but the path wouldn't.
* Since 'paths' should not be taken into account after redirects,
* that load should succeed. We are using a similar test setup
* as described in the spec, see:
* http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects
*/
var policy = "script-src http://example.com http://test1.example.com/CSPAllowsScriptsInThatFolder";
var tests = [
{
// the script in file_csp_path_matching.html
// <script src="http://test1.example.com/tests/content/base/..">
// is not within the whitelisted path by the csp-policy
// hence the script is 'blocked' by CSP.
expected: "blocked",
uri: "tests/content/base/test/csp/file_csp_path_matching.html"
},
{
// the script in file_csp_path_matching_redirect.html
// <script src="http://example.com/tests/content/..">
// gets redirected to: http://test1.example.com/tests/content
// where after the redirect the path of the policy is not enforced
// anymore and hence execution of the script is 'allowed'.
expected: "allowed",
uri: "tests/content/base/test/csp/file_csp_path_matching_redirect.html"
},
];
var counter = 0;
var curTest;
function checkResult() {
try {
document.getElementById("testframe").removeEventListener('load', checkResult, false);
var testframe = document.getElementById("testframe");
var divcontent = testframe.contentWindow.document.getElementById('testdiv').innerHTML;
is(divcontent, curTest.expected, "should be blocked in test " + (counter - 1) + "!");
}
catch (e) {
ok(false, "ERROR: could not access content in test " + (counter - 1) + "!");
}
loadNextTest();
}
function loadNextTest() {
if (counter == tests.length) {
SimpleTest.finish();
}
else {
curTest = tests[counter++];
var src = "file_csp_testserver.sjs";
// append the file that should be served
src += "?file=" + escape(curTest.uri);
// append the CSP that should be used to serve the file
src += "&csp=" + escape(policy);
document.getElementById("testframe").addEventListener("load", checkResult, false);
document.getElementById("testframe").src = src;
}
}
loadNextTest();
</script>
</body>
</html>

View File

@ -33,8 +33,7 @@ window.onerror = function(message, uri, line) {
</script>
<script type="application/javascript">
window.onerror = function(message, uri, line) {
ok(message.contains("ReferenceError: c is not defined"),
"Should have correct error message");
is(message, "ReferenceError: c is not defined", "Should have correct error message");
is(uri,
"http://mochi.test:8888/tests/content/base/test/bug461735-redirect2.sjs",
"Unexpected error location URI");

View File

@ -38,8 +38,7 @@ window.onerror = function(message, uri, line) {
errorFired = false;
global = "";
window.onerror = function(message, uri, line) {
ok(message.contains("ReferenceError: c is not defined"),
"Should have correct error message");
is(message, "ReferenceError: c is not defined", "Should have correct error message");
is(uri,
"http://example.com/tests/content/base/test/bug696301-script-1.js",
"Should also have correct script URI");

View File

@ -40,8 +40,7 @@ window.onerror = function(message, uri, line) {
errorFired = false;
global = "";
window.onerror = function(message, uri, line) {
ok(message.contains("ReferenceError: c is not defined"),
"Should have correct error message");
is(message, "ReferenceError: c is not defined", "Should have correct error message");
is(uri,
"http://example.com/tests/content/base/test/bug696301-script-1.js",
"Should also have correct script URI");

View File

@ -3,6 +3,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/. */
#ifndef mozilla_dom_AnimationUtils_h
#define mozilla_dom_AnimationUtils_h
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/Nullable.h"
@ -27,3 +30,5 @@ public:
} // namespace dom
} // namespace mozilla
#endif

View File

@ -14,7 +14,7 @@ EXPORTS.mozilla.dom += [
'AnimationTimeline.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'Animation.cpp',
'AnimationEffect.cpp',
'AnimationPlayer.cpp',

View File

@ -1535,7 +1535,7 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
}
// Check if the object is even callable.
NS_ENSURE_STATE(JS_ObjectIsCallable(cx, &funval.toObject()));
NS_ENSURE_STATE(JS::IsCallable(&funval.toObject()));
{
// wrap parameters in the target compartment
// we also pass in the calling window as the first argument

View File

@ -5274,7 +5274,7 @@ nsGlobalWindow::RequestAnimationFrame(JS::Handle<JS::Value> aCallback,
JSContext* cx,
int32_t* aHandle)
{
if (!aCallback.isObject() || !JS_ObjectIsCallable(cx, &aCallback.toObject())) {
if (!aCallback.isObject() || !JS::IsCallable(&aCallback.toObject())) {
return NS_ERROR_INVALID_ARG;
}

View File

@ -1699,7 +1699,7 @@ NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
if (!JS_WrapValue(cx, &toString)) {
return false;
}
MOZ_ASSERT(JS_ObjectIsCallable(cx, &toString.toObject()));
MOZ_ASSERT(JS::IsCallable(&toString.toObject()));
JS::Rooted<JS::Value> toStringResult(cx);
if (JS_CallFunctionValue(cx, obj, toString, JS::HandleValueArray::empty(),
&toStringResult)) {

View File

@ -20,7 +20,7 @@ CallbackInterface::GetCallableProperty(JSContext* cx, JS::Handle<jsid> aPropId,
return false;
}
if (!aCallable.isObject() ||
!JS_ObjectIsCallable(cx, &aCallable.toObject())) {
!JS::IsCallable(&aCallable.toObject())) {
char* propName =
JS_EncodeString(cx, JS_FORGET_STRING_FLATNESS(JSID_TO_FLAT_STRING(aPropId)));
nsPrintfCString description("Property '%s'", propName);

View File

@ -4911,7 +4911,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
conversion = indent(CGCallbackTempRoot(name).define())
if allowTreatNonCallableAsNull and type.treatNonCallableAsNull():
haveCallable = "JS_ObjectIsCallable(cx, &${val}.toObject())"
haveCallable = "JS::IsCallable(&${val}.toObject())"
if not isDefinitelyObject:
haveCallable = "${val}.isObject() && " + haveCallable
if defaultValue is not None:
@ -4936,7 +4936,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
template = conversion
else:
template = wrapObjectTemplate(
"if (JS_ObjectIsCallable(cx, &${val}.toObject())) {\n" +
"if (JS::IsCallable(&${val}.toObject())) {\n" +
conversion +
"} else {\n" +
indent(onFailureNotCallable(failureCode).define()) +
@ -13417,7 +13417,7 @@ class CGCallback(CGClass):
def getConstructors(self):
if (not self.idlObject.isInterface() and
not self.idlObject._treatNonObjectAsNull):
body = "MOZ_ASSERT(JS_ObjectIsCallable(nullptr, mCallback));\n"
body = "MOZ_ASSERT(JS::IsCallable(mCallback));\n"
else:
# Not much we can assert about it, other than not being null, and
# CallbackObject does that already.
@ -13879,7 +13879,7 @@ class CallCallback(CallbackMethod):
def getCallGuard(self):
if self.callback._treatNonObjectAsNull:
return "JS_ObjectIsCallable(cx, mCallback) && "
return "JS::IsCallable(mCallback) && "
return ""
@ -13927,7 +13927,7 @@ class CallbackOperationBase(CallbackMethod):
return 'JS::Rooted<JS::Value> callable(cx);\n' + getCallableFromProp
return fill(
"""
bool isCallable = JS_ObjectIsCallable(cx, mCallback);
bool isCallable = JS::IsCallable(mCallback);
JS::Rooted<JS::Value> callable(cx);
if (isCallable) {
callable = JS::ObjectValue(*mCallback);

View File

@ -54,6 +54,8 @@ public:
virtual void Accept(int aFd, BluetoothSocketResultHandler* aRes) = 0;
virtual void Close(BluetoothSocketResultHandler* aRes) = 0;
protected:
virtual ~BluetoothSocketInterface();
};

View File

@ -395,7 +395,10 @@ public:
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sBluetoothSocketInterface);
sBluetoothSocketInterface->Accept(mFd, new AcceptResultHandler(GetIO()));
BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO());
GetIO()->mConsumer->SetCurrentResultHandler(res);
sBluetoothSocketInterface->Accept(mFd, res);
return NS_OK;
}
@ -476,6 +479,7 @@ BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver,
bool aAuth,
bool aEncrypt)
: mObserver(aObserver)
, mCurrentRes(nullptr)
, mImpl(nullptr)
, mAuth(aAuth)
, mEncrypt(aEncrypt)
@ -527,13 +531,15 @@ BluetoothSocket::ConnectSocket(const nsAString& aDeviceAddress, int aChannel)
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
SetCurrentResultHandler(res);
// TODO: uuid as argument
sBluetoothSocketInterface->Connect(
aDeviceAddress,
BluetoothSocketType::RFCOMM,
UUID_OBEX_OBJECT_PUSH,
aChannel, mEncrypt, mAuth,
new ConnectSocketResultHandler(mImpl));
aChannel, mEncrypt, mAuth, res);
return true;
}
@ -576,12 +582,14 @@ BluetoothSocket::ListenSocket(int aChannel)
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
SetCurrentResultHandler(res);
sBluetoothSocketInterface->Listen(
BluetoothSocketType::RFCOMM,
NS_LITERAL_STRING("OBEX Object Push"),
UUID_OBEX_OBJECT_PUSH,
aChannel, mEncrypt, mAuth,
new ListenResultHandler(mImpl));
aChannel, mEncrypt, mAuth, res);
return true;
}
@ -590,10 +598,16 @@ void
BluetoothSocket::CloseSocket()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sBluetoothSocketInterface);
if (!mImpl) {
return;
}
// Stop any watching |SocketMessageWatcher|
if (mCurrentRes) {
sBluetoothSocketInterface->Close(mCurrentRes);
}
// From this point on, we consider mImpl as being deleted.
// We sever the relationship here so any future calls to listen or connect
// will create a new implementation.
@ -633,6 +647,8 @@ BluetoothSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
SetCurrentResultHandler(nullptr);
mObserver->OnSocketConnectSuccess(this);
}
@ -641,6 +657,8 @@ BluetoothSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
SetCurrentResultHandler(nullptr);
mObserver->OnSocketConnectError(this);
}

View File

@ -13,6 +13,7 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocketObserver;
class BluetoothSocketResultHandler;
class DroidSocketImpl;
class BluetoothSocket : public mozilla::ipc::SocketConsumerBase
@ -47,8 +48,14 @@ public:
mDeviceAddress = aDeviceAddress;
}
inline void SetCurrentResultHandler(BluetoothSocketResultHandler* aRes)
{
mCurrentRes = aRes;
}
private:
BluetoothSocketObserver* mObserver;
BluetoothSocketResultHandler* mCurrentRes;
DroidSocketImpl* mImpl;
nsString mDeviceAddress;
bool mAuth;

View File

@ -9,24 +9,25 @@
#include <unistd.h>
#include <sys/socket.h>
#include "BluetoothHALHelpers.h"
#include "nsClassHashtable.h"
#include "nsXULAppAPI.h"
BEGIN_BLUETOOTH_NAMESPACE
typedef
BluetoothHALInterfaceRunnable1<BluetoothSocketResultHandler, void,
int, int>
int, int>
BluetoothSocketHALIntResultRunnable;
typedef
BluetoothHALInterfaceRunnable3<BluetoothSocketResultHandler, void,
int, const nsString, int,
int, const nsAString_internal&, int>
int, const nsString, int,
int, const nsAString_internal&, int>
BluetoothSocketHALIntStringIntResultRunnable;
typedef
BluetoothHALInterfaceRunnable1<BluetoothSocketResultHandler, void,
BluetoothStatus, BluetoothStatus>
BluetoothStatus, BluetoothStatus>
BluetoothSocketHALErrorRunnable;
static nsresult
@ -78,11 +79,11 @@ DispatchBluetoothSocketHALResult(
void
BluetoothSocketHALInterface::Listen(BluetoothSocketType aType,
const nsAString& aServiceName,
const uint8_t aServiceUuid[16],
int aChannel, bool aEncrypt,
bool aAuth,
BluetoothSocketResultHandler* aRes)
const nsAString& aServiceName,
const uint8_t aServiceUuid[16],
int aChannel, bool aEncrypt,
bool aAuth,
BluetoothSocketResultHandler* aRes)
{
int fd;
bt_status_t status;
@ -109,6 +110,34 @@ BluetoothSocketHALInterface::Listen(BluetoothSocketType aType,
( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \
((_cmsghdr)->cmsg_type == SCM_RIGHTS) )
class SocketMessageWatcher;
/* |SocketMessageWatcherWrapper| wraps SocketMessageWatcher to keep it from
* being released by hash table's Remove() method.
*/
class SocketMessageWatcherWrapper
{
public:
SocketMessageWatcherWrapper(SocketMessageWatcher* aSocketMessageWatcher)
: mSocketMessageWatcher(aSocketMessageWatcher)
{
MOZ_ASSERT(mSocketMessageWatcher);
}
SocketMessageWatcher* GetSocketMessageWatcher()
{
return mSocketMessageWatcher;
}
private:
SocketMessageWatcher* mSocketMessageWatcher;
};
/* |sWatcherHashTable| maps result handlers to corresponding watchers */
static nsClassHashtable<nsRefPtrHashKey<BluetoothSocketResultHandler>,
SocketMessageWatcherWrapper>
sWatcherHashtable;
/* |SocketMessageWatcher| receives Bluedroid's socket setup
* messages on the I/O thread. You need to inherit from this
* class to make use of it.
@ -135,11 +164,14 @@ public:
static const unsigned char OFF_CHANNEL2 = 12;
static const unsigned char OFF_STATUS = 16;
SocketMessageWatcher(int aFd)
SocketMessageWatcher(int aFd, BluetoothSocketResultHandler* aRes)
: mFd(aFd)
, mClientFd(-1)
, mLen(0)
{ }
, mRes(aRes)
{
MOZ_ASSERT(mRes);
}
virtual ~SocketMessageWatcher()
{ }
@ -164,7 +196,7 @@ public:
}
if (IsComplete() || status != STATUS_SUCCESS) {
mWatcher.StopWatchingFileDescriptor();
StopWatching();
Proceed(status);
}
}
@ -174,6 +206,9 @@ public:
void Watch()
{
// add this watcher and its result handler to hash table
sWatcherHashtable.Put(mRes, new SocketMessageWatcherWrapper(this));
MessageLoopForIO::current()->WatchFileDescriptor(
mFd,
true,
@ -182,6 +217,14 @@ public:
this);
}
void StopWatching()
{
mWatcher.StopWatchingFileDescriptor();
// remove this watcher and its result handler from hash table
sWatcherHashtable.Remove(mRes);
}
bool IsComplete() const
{
return mLen == (MSG1_SIZE + MSG2_SIZE);
@ -224,6 +267,11 @@ public:
return mClientFd;
}
BluetoothSocketResultHandler* GetResultHandler() const
{
return mRes;
}
private:
BluetoothStatus RecvMsg1()
{
@ -322,6 +370,7 @@ private:
int mClientFd;
unsigned char mLen;
uint8_t mBuf[MSG1_SIZE + MSG2_SIZE];
nsRefPtr<BluetoothSocketResultHandler> mRes;
};
/* |SocketMessageWatcherTask| starts a SocketMessageWatcher
@ -373,32 +422,27 @@ class ConnectWatcher MOZ_FINAL : public SocketMessageWatcher
{
public:
ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes)
: SocketMessageWatcher(aFd)
, mRes(aRes)
: SocketMessageWatcher(aFd, aRes)
{ }
void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
{
if (mRes) {
DispatchBluetoothSocketHALResult(
mRes, &BluetoothSocketResultHandler::Connect, GetFd(),
GetBdAddress(), GetConnectionStatus(), aStatus);
}
DispatchBluetoothSocketHALResult(
GetResultHandler(), &BluetoothSocketResultHandler::Connect,
GetFd(), GetBdAddress(), GetConnectionStatus(), aStatus);
MessageLoopForIO::current()->PostTask(
FROM_HERE, new DeleteTask<ConnectWatcher>(this));
}
private:
nsRefPtr<BluetoothSocketResultHandler> mRes;
};
void
BluetoothSocketHALInterface::Connect(const nsAString& aBdAddr,
BluetoothSocketType aType,
const uint8_t aUuid[16],
int aChannel, bool aEncrypt,
bool aAuth,
BluetoothSocketResultHandler* aRes)
BluetoothSocketType aType,
const uint8_t aUuid[16],
int aChannel, bool aEncrypt,
bool aAuth,
BluetoothSocketResultHandler* aRes)
{
int fd;
bt_status_t status;
@ -425,10 +469,10 @@ BluetoothSocketHALInterface::Connect(const nsAString& aBdAddr,
}
}
/* Specializes SocketMessageWatcher for Accept operations by
* reading the socket messages from Bluedroid and forwarding
* the received client socket to the resource handler. The
* first message is received immediately. When there's a new
/* |AcceptWatcher| specializes SocketMessageWatcher for Accept
* operations by reading the socket messages from Bluedroid and
* forwarding the received client socket to the resource handler.
* The first message is received immediately. When there's a new
* connection, Bluedroid sends the 2nd message with the socket
* info and socket file descriptor.
*/
@ -436,37 +480,69 @@ class AcceptWatcher MOZ_FINAL : public SocketMessageWatcher
{
public:
AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes)
: SocketMessageWatcher(aFd)
, mRes(aRes)
{
/* not supplying a result handler leaks received file descriptor */
MOZ_ASSERT(mRes);
}
: SocketMessageWatcher(aFd, aRes)
{ }
void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
{
if (mRes) {
DispatchBluetoothSocketHALResult(
mRes, &BluetoothSocketResultHandler::Accept, GetClientFd(),
GetBdAddress(), GetConnectionStatus(), aStatus);
}
DispatchBluetoothSocketHALResult(
GetResultHandler(), &BluetoothSocketResultHandler::Accept,
GetClientFd(), GetBdAddress(), GetConnectionStatus(), aStatus);
MessageLoopForIO::current()->PostTask(
FROM_HERE, new DeleteTask<AcceptWatcher>(this));
}
private:
nsRefPtr<BluetoothSocketResultHandler> mRes;
};
void
BluetoothSocketHALInterface::Accept(int aFd,
BluetoothSocketResultHandler* aRes)
BluetoothSocketResultHandler* aRes)
{
/* receive Bluedroid's socket-setup messages and client fd */
Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes));
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
}
/* |DeleteSocketMessageWatcherTask| deletes a watching SocketMessageWatcher
* on the I/O task
*/
class DeleteSocketMessageWatcherTask MOZ_FINAL : public Task
{
public:
DeleteSocketMessageWatcherTask(BluetoothSocketResultHandler* aRes)
: mRes(aRes)
{
MOZ_ASSERT(mRes);
}
void Run() MOZ_OVERRIDE
{
// look up hash table for the watcher corresponding to |mRes|
SocketMessageWatcherWrapper* wrapper = sWatcherHashtable.Get(mRes);
if (!wrapper) {
return;
}
// stop the watcher if it exists
SocketMessageWatcher* watcher = wrapper->GetSocketMessageWatcher();
watcher->StopWatching();
watcher->Proceed(STATUS_DONE);
}
private:
BluetoothSocketResultHandler* mRes;
};
void
BluetoothSocketHALInterface::Close(BluetoothSocketResultHandler* aRes)
{
MOZ_ASSERT(aRes);
/* stop the watcher corresponding to |aRes| */
Task* t = new DeleteSocketMessageWatcherTask(aRes);
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
}
BluetoothSocketHALInterface::BluetoothSocketHALInterface(
const btsock_interface_t* aInterface)
: mInterface(aInterface)

View File

@ -36,6 +36,8 @@ public:
void Accept(int aFd, BluetoothSocketResultHandler* aRes);
void Close(BluetoothSocketResultHandler* aRes);
protected:
BluetoothSocketHALInterface(const btsock_interface_t* aInterface);
~BluetoothSocketHALInterface();

View File

@ -54,6 +54,8 @@ public:
virtual void Accept(int aFd, BluetoothSocketResultHandler* aRes) = 0;
virtual void Close(BluetoothSocketResultHandler* aRes) = 0;
protected:
virtual ~BluetoothSocketInterface();
};

View File

@ -182,7 +182,7 @@ MobileConnectionListener::Listen(bool aStart)
NS_ENSURE_TRUE(service, false);
nsCOMPtr<nsIMobileConnection> connection;
mcService->GetItemByServiceId(mClientId, getter_AddRefs(connection));
service->GetItemByServiceId(mClientId, getter_AddRefs(connection));
NS_ENSURE_TRUE(connection, false);
nsresult rv;

View File

@ -395,7 +395,10 @@ public:
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sBluetoothSocketInterface);
sBluetoothSocketInterface->Accept(mFd, new AcceptResultHandler(GetIO()));
BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO());
GetIO()->mConsumer->SetCurrentResultHandler(res);
sBluetoothSocketInterface->Accept(mFd, res);
return NS_OK;
}
@ -476,6 +479,7 @@ BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver,
bool aAuth,
bool aEncrypt)
: mObserver(aObserver)
, mCurrentRes(nullptr)
, mImpl(nullptr)
, mAuth(aAuth)
, mEncrypt(aEncrypt)
@ -527,13 +531,15 @@ BluetoothSocket::ConnectSocket(const nsAString& aDeviceAddress, int aChannel)
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
SetCurrentResultHandler(res);
// TODO: uuid as argument
sBluetoothSocketInterface->Connect(
aDeviceAddress,
BluetoothSocketType::RFCOMM,
UUID_OBEX_OBJECT_PUSH,
aChannel, mEncrypt, mAuth,
new ConnectSocketResultHandler(mImpl));
aChannel, mEncrypt, mAuth, res);
return true;
}
@ -576,12 +582,14 @@ BluetoothSocket::ListenSocket(int aChannel)
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
SetCurrentResultHandler(res);
sBluetoothSocketInterface->Listen(
BluetoothSocketType::RFCOMM,
NS_LITERAL_STRING("OBEX Object Push"),
UUID_OBEX_OBJECT_PUSH,
aChannel, mEncrypt, mAuth,
new ListenResultHandler(mImpl));
aChannel, mEncrypt, mAuth, res);
return true;
}
@ -590,10 +598,16 @@ void
BluetoothSocket::CloseSocket()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sBluetoothSocketInterface);
if (!mImpl) {
return;
}
// Stop any watching |SocketMessageWatcher|
if (mCurrentRes) {
sBluetoothSocketInterface->Close(mCurrentRes);
}
// From this point on, we consider mImpl as being deleted.
// We sever the relationship here so any future calls to listen or connect
// will create a new implementation.
@ -633,6 +647,8 @@ BluetoothSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
SetCurrentResultHandler(nullptr);
mObserver->OnSocketConnectSuccess(this);
}
@ -641,6 +657,8 @@ BluetoothSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
SetCurrentResultHandler(nullptr);
mObserver->OnSocketConnectError(this);
}

View File

@ -13,6 +13,7 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocketObserver;
class BluetoothSocketResultHandler;
class DroidSocketImpl;
class BluetoothSocket : public mozilla::ipc::SocketConsumerBase
@ -47,8 +48,14 @@ public:
mDeviceAddress = aDeviceAddress;
}
inline void SetCurrentResultHandler(BluetoothSocketResultHandler* aRes)
{
mCurrentRes = aRes;
}
private:
BluetoothSocketObserver* mObserver;
BluetoothSocketResultHandler* mCurrentRes;
DroidSocketImpl* mImpl;
nsString mDeviceAddress;
bool mAuth;

View File

@ -9,6 +9,7 @@
#include <sys/socket.h>
#include <unistd.h>
#include "BluetoothHALHelpers.h"
#include "nsClassHashtable.h"
#include "nsXULAppAPI.h"
BEGIN_BLUETOOTH_NAMESPACE
@ -109,6 +110,34 @@ BluetoothSocketHALInterface::Listen(BluetoothSocketType aType,
( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \
((_cmsghdr)->cmsg_type == SCM_RIGHTS) )
class SocketMessageWatcher;
/* |SocketMessageWatcherWrapper| wraps SocketMessageWatcher to keep it from
* being released by hash table's Remove() method.
*/
class SocketMessageWatcherWrapper
{
public:
SocketMessageWatcherWrapper(SocketMessageWatcher* aSocketMessageWatcher)
: mSocketMessageWatcher(aSocketMessageWatcher)
{
MOZ_ASSERT(mSocketMessageWatcher);
}
SocketMessageWatcher* GetSocketMessageWatcher()
{
return mSocketMessageWatcher;
}
private:
SocketMessageWatcher* mSocketMessageWatcher;
};
/* |sWatcherHashTable| maps result handlers to corresponding watchers */
static nsClassHashtable<nsRefPtrHashKey<BluetoothSocketResultHandler>,
SocketMessageWatcherWrapper>
sWatcherHashtable;
/* |SocketMessageWatcher| receives Bluedroid's socket setup
* messages on the I/O thread. You need to inherit from this
* class to make use of it.
@ -135,11 +164,14 @@ public:
static const unsigned char OFF_CHANNEL2 = 12;
static const unsigned char OFF_STATUS = 16;
SocketMessageWatcher(int aFd)
SocketMessageWatcher(int aFd, BluetoothSocketResultHandler* aRes)
: mFd(aFd)
, mClientFd(-1)
, mLen(0)
{ }
, mRes(aRes)
{
MOZ_ASSERT(mRes);
}
virtual ~SocketMessageWatcher()
{ }
@ -164,7 +196,7 @@ public:
}
if (IsComplete() || status != STATUS_SUCCESS) {
mWatcher.StopWatchingFileDescriptor();
StopWatching();
Proceed(status);
}
}
@ -174,6 +206,9 @@ public:
void Watch()
{
// add this watcher and its result handler to hash table
sWatcherHashtable.Put(mRes, new SocketMessageWatcherWrapper(this));
MessageLoopForIO::current()->WatchFileDescriptor(
mFd,
true,
@ -182,6 +217,14 @@ public:
this);
}
void StopWatching()
{
mWatcher.StopWatchingFileDescriptor();
// remove this watcher and its result handler from hash table
sWatcherHashtable.Remove(mRes);
}
bool IsComplete() const
{
return mLen == (MSG1_SIZE + MSG2_SIZE);
@ -224,6 +267,11 @@ public:
return mClientFd;
}
BluetoothSocketResultHandler* GetResultHandler() const
{
return mRes;
}
private:
BluetoothStatus RecvMsg1()
{
@ -322,6 +370,7 @@ private:
int mClientFd;
unsigned char mLen;
uint8_t mBuf[MSG1_SIZE + MSG2_SIZE];
nsRefPtr<BluetoothSocketResultHandler> mRes;
};
/* |SocketMessageWatcherTask| starts a SocketMessageWatcher
@ -373,23 +422,18 @@ class ConnectWatcher MOZ_FINAL : public SocketMessageWatcher
{
public:
ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes)
: SocketMessageWatcher(aFd)
, mRes(aRes)
: SocketMessageWatcher(aFd, aRes)
{ }
void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
{
if (mRes) {
DispatchBluetoothSocketHALResult(
mRes, &BluetoothSocketResultHandler::Connect, GetFd(),
GetBdAddress(), GetConnectionStatus(), aStatus);
}
DispatchBluetoothSocketHALResult(
GetResultHandler(), &BluetoothSocketResultHandler::Connect,
GetFd(), GetBdAddress(), GetConnectionStatus(), aStatus);
MessageLoopForIO::current()->PostTask(
FROM_HERE, new DeleteTask<ConnectWatcher>(this));
}
private:
nsRefPtr<BluetoothSocketResultHandler> mRes;
};
void
@ -436,26 +480,18 @@ class AcceptWatcher MOZ_FINAL : public SocketMessageWatcher
{
public:
AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes)
: SocketMessageWatcher(aFd)
, mRes(aRes)
{
/* not supplying a result handler leaks received file descriptor */
MOZ_ASSERT(mRes);
}
: SocketMessageWatcher(aFd, aRes)
{ }
void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
{
if (mRes) {
DispatchBluetoothSocketHALResult(
mRes, &BluetoothSocketResultHandler::Accept, GetClientFd(),
GetBdAddress(), GetConnectionStatus(), aStatus);
}
DispatchBluetoothSocketHALResult(
GetResultHandler(), &BluetoothSocketResultHandler::Accept,
GetClientFd(), GetBdAddress(), GetConnectionStatus(), aStatus);
MessageLoopForIO::current()->PostTask(
FROM_HERE, new DeleteTask<AcceptWatcher>(this));
}
private:
nsRefPtr<BluetoothSocketResultHandler> mRes;
};
void
@ -467,6 +503,46 @@ BluetoothSocketHALInterface::Accept(int aFd,
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
}
/* |DeleteSocketMessageWatcherTask| deletes a watching SocketMessageWatcher
* on the I/O task
*/
class DeleteSocketMessageWatcherTask MOZ_FINAL : public Task
{
public:
DeleteSocketMessageWatcherTask(BluetoothSocketResultHandler* aRes)
: mRes(aRes)
{
MOZ_ASSERT(mRes);
}
void Run() MOZ_OVERRIDE
{
// look up hash table for the watcher corresponding to |mRes|
SocketMessageWatcherWrapper* wrapper = sWatcherHashtable.Get(mRes);
if (!wrapper) {
return;
}
// stop the watcher if it exists
SocketMessageWatcher* watcher = wrapper->GetSocketMessageWatcher();
watcher->StopWatching();
watcher->Proceed(STATUS_DONE);
}
private:
BluetoothSocketResultHandler* mRes;
};
void
BluetoothSocketHALInterface::Close(BluetoothSocketResultHandler* aRes)
{
MOZ_ASSERT(aRes);
/* stop the watcher corresponding to |aRes| */
Task* t = new DeleteSocketMessageWatcherTask(aRes);
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
}
BluetoothSocketHALInterface::BluetoothSocketHALInterface(
const btsock_interface_t* aInterface)
: mInterface(aInterface)

View File

@ -36,6 +36,8 @@ public:
void Accept(int aFd, BluetoothSocketResultHandler* aRes);
void Close(BluetoothSocketResultHandler* aRes);
protected:
BluetoothSocketHALInterface(const btsock_interface_t* aInterface);
~BluetoothSocketHALInterface();

View File

@ -1431,7 +1431,7 @@ WebGLContext::PresentScreenBuffer()
void
WebGLContext::DummyFramebufferOperation(const char *info)
{
GLenum status = CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
FBStatus status = CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
}

View File

@ -355,6 +355,10 @@ public:
void FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum textarget, WebGLTexture *tobj,
GLint level);
// Framebuffer validation
bool ValidateFramebufferAttachment(GLenum attachment, const char* funcName);
void FrontFace(GLenum mode);
void GenerateMipmap(GLenum target);
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram *prog,

View File

@ -64,7 +64,7 @@ WebGLContext::CurValidFBRectObject() const
if (mBoundFramebuffer) {
// We don't really need to ask the driver.
// Use 'precheck' to just check that our internal state looks good.
GLenum precheckStatus = mBoundFramebuffer->PrecheckFramebufferStatus();
FBStatus precheckStatus = mBoundFramebuffer->PrecheckFramebufferStatus();
if (precheckStatus == LOCAL_GL_FRAMEBUFFER_COMPLETE)
rect = &mBoundFramebuffer->RectangleObject();
} else {
@ -348,7 +348,7 @@ WebGLContext::CheckFramebufferStatus(GLenum target)
if (!mBoundFramebuffer)
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
return mBoundFramebuffer->CheckFramebufferStatus();
return mBoundFramebuffer->CheckFramebufferStatus().get();
}
void
@ -795,7 +795,16 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum r
if (!mBoundFramebuffer)
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
return mBoundFramebuffer->FramebufferRenderbuffer(target, attachment, rbtarget, wrb);
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
if (rbtarget != LOCAL_GL_RENDERBUFFER)
return ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
if (!ValidateFramebufferAttachment(attachment, "framebufferRenderbuffer"))
return;
return mBoundFramebuffer->FramebufferRenderbuffer(attachment, rbtarget, wrb);
}
void
@ -811,6 +820,9 @@ WebGLContext::FramebufferTexture2D(GLenum target,
if (!mBoundFramebuffer)
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
if (textarget != LOCAL_GL_TEXTURE_2D &&
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
@ -818,7 +830,10 @@ WebGLContext::FramebufferTexture2D(GLenum target,
return ErrorInvalidEnumInfo("framebufferTexture2D: invalid texture target", textarget);
}
return mBoundFramebuffer->FramebufferTexture2D(target, attachment, TexImageTarget(textarget), tobj, level);
if (!ValidateFramebufferAttachment(attachment, "framebufferTexture2D"))
return;
return mBoundFramebuffer->FramebufferTexture2D(attachment, textarget, tobj, level);
}
void
@ -1084,27 +1099,11 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
return JS::NullValue();
}
if (attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
attachment != LOCAL_GL_STENCIL_ATTACHMENT &&
attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
{
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
{
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments))
{
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: attachment", attachment);
return JS::NullValue();
}
if (!ValidateFramebufferAttachment(attachment, "getFramebufferAttachmentParameter"))
return JS::NullValue();
mBoundFramebuffer->EnsureColorAttachments(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
}
else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
{
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: attachment", attachment);
return JS::NullValue();
}
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
mBoundFramebuffer->EnsureColorAttachments(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
MakeContextCurrent();

View File

@ -520,6 +520,34 @@ bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
return true;
}
/**
* Return true if the framebuffer attachment is valid. Attachment must
* be one of depth/stencil/depth_stencil/color attachment.
*/
bool
WebGLContext::ValidateFramebufferAttachment(GLenum attachment, const char* funcName)
{
if (attachment == LOCAL_GL_DEPTH_ATTACHMENT ||
attachment == LOCAL_GL_STENCIL_ATTACHMENT ||
attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
{
return true;
}
GLenum colorAttachCount = 1;
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
colorAttachCount = mGLMaxColorAttachments;
if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 &&
attachment < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + colorAttachCount))
{
return true;
}
ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment);
return false;
}
/**
* Return true if format is a valid texture image format for source,
* taking into account enabled WebGL extensions.

View File

@ -24,7 +24,7 @@ WebGLFramebuffer::WrapObject(JSContext* cx)
}
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
: WebGLBindableName<GLenum>()
: WebGLBindableName<FBTarget>()
, WebGLContextBoundObject(context)
, mStatus(0)
, mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
@ -40,7 +40,7 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
}
WebGLFramebuffer::Attachment::Attachment(GLenum aAttachmentPoint)
WebGLFramebuffer::Attachment::Attachment(FBAttachment aAttachmentPoint)
: mAttachmentPoint(aAttachmentPoint)
, mTexImageTarget(LOCAL_GL_NONE)
, mNeedsFinalize(false)
@ -341,8 +341,8 @@ WebGLFramebuffer::Attachment::IsComplete() const
}
if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
WebGLContext::kMaxColorAttachments))
mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 +
WebGLContext::kMaxColorAttachments))
{
return IsValidFBOTextureColorFormat(webGLFormat);
}
@ -363,8 +363,8 @@ WebGLFramebuffer::Attachment::IsComplete() const
return IsValidFBORenderbufferDepthStencilFormat(internalFormat);
if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
WebGLContext::kMaxColorAttachments))
mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 +
WebGLContext::kMaxColorAttachments))
{
return IsValidFBORenderbufferColorFormat(internalFormat);
}
@ -377,7 +377,7 @@ WebGLFramebuffer::Attachment::IsComplete() const
}
void
WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, GLenum attachmentLoc) const
WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, FBAttachment attachmentLoc) const
{
if (!mNeedsFinalize)
return;
@ -391,7 +391,7 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, GLenum attachmen
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, 0);
} else {
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc,
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
LOCAL_GL_RENDERBUFFER, 0);
}
@ -412,7 +412,7 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, GLenum attachmen
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
imageTarget, glName, mipLevel);
} else {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc,
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
imageTarget, glName, mipLevel);
}
return;
@ -464,9 +464,8 @@ WebGLFramebuffer::DetachAllAttachments()
}
void
WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
GLenum attachment,
GLenum rbtarget,
WebGLFramebuffer::FramebufferRenderbuffer(FBAttachment attachment,
RBTarget rbtarget,
WebGLRenderbuffer* wrb)
{
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
@ -474,12 +473,6 @@ WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", wrb))
return;
if (target != LOCAL_GL_FRAMEBUFFER)
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
if (rbtarget != LOCAL_GL_RENDERBUFFER)
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
/* Get the requested attachment. If result is NULL, attachment is
* invalid and an error is generated.
*
@ -509,8 +502,7 @@ WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
}
void
WebGLFramebuffer::FramebufferTexture2D(GLenum target,
GLenum attachment,
WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachment,
TexImageTarget texImageTarget,
WebGLTexture* wtex,
GLint level)
@ -520,9 +512,6 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target,
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture", wtex))
return;
if (target != LOCAL_GL_FRAMEBUFFER)
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
if (wtex) {
bool isTexture2D = wtex->Target() == LOCAL_GL_TEXTURE_2D;
bool isTexTarget2D = texImageTarget == LOCAL_GL_TEXTURE_2D;
@ -563,7 +552,7 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target,
}
WebGLFramebuffer::Attachment*
WebGLFramebuffer::GetAttachmentOrNull(GLenum attachment)
WebGLFramebuffer::GetAttachmentOrNull(FBAttachment attachment)
{
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
return &mDepthStencilAttachment;
@ -574,17 +563,17 @@ WebGLFramebuffer::GetAttachmentOrNull(GLenum attachment)
if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
return &mStencilAttachment;
if (!CheckColorAttachmentNumber(attachment, "getAttachmentOrNull"))
if (!mContext->ValidateFramebufferAttachment(attachment.get(), "getAttachmentOrNull"))
return nullptr;
size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
size_t colorAttachmentId = attachment.get() - LOCAL_GL_COLOR_ATTACHMENT0;
EnsureColorAttachments(colorAttachmentId);
return &mColorAttachments[colorAttachmentId];
}
const WebGLFramebuffer::Attachment&
WebGLFramebuffer::GetAttachment(GLenum attachment) const
WebGLFramebuffer::GetAttachment(FBAttachment attachment) const
{
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
return mDepthStencilAttachment;
@ -593,12 +582,12 @@ WebGLFramebuffer::GetAttachment(GLenum attachment) const
if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
return mStencilAttachment;
if (!CheckColorAttachmentNumber(attachment, "getAttachment")) {
if (!mContext->ValidateFramebufferAttachment(attachment.get(), "getAttachment")) {
MOZ_ASSERT(false);
return mColorAttachments[0];
}
size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
size_t colorAttachmentId = attachment.get() - LOCAL_GL_COLOR_ATTACHMENT0;
if (colorAttachmentId >= mColorAttachments.Length()) {
MOZ_ASSERT(false);
return mColorAttachments[0];
@ -613,17 +602,17 @@ WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[i].Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_TEXTURE_2D, nullptr, 0);
FramebufferTexture2D(LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_TEXTURE_2D, nullptr, 0);
// a texture might be attached more that once while editing the framebuffer
}
}
if (mDepthAttachment.Texture() == tex)
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
FramebufferTexture2D(LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
if (mStencilAttachment.Texture() == tex)
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
FramebufferTexture2D(LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
if (mDepthStencilAttachment.Texture() == tex)
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
FramebufferTexture2D(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
}
void
@ -632,17 +621,17 @@ WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
size_t count = mColorAttachments.Length();
for (size_t i = 0; i < count; i++) {
if (mColorAttachments[i].Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_RENDERBUFFER, nullptr);
FramebufferRenderbuffer(LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_RENDERBUFFER, nullptr);
// a renderbuffer might be attached more that once while editing the framebuffer
}
}
if (mDepthAttachment.Renderbuffer() == rb)
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
FramebufferRenderbuffer(LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
if (mStencilAttachment.Renderbuffer() == rb)
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
FramebufferRenderbuffer(LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
if (mDepthStencilAttachment.Renderbuffer() == rb)
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
FramebufferRenderbuffer(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
}
bool
@ -757,7 +746,7 @@ WebGLFramebuffer::RectangleObject() const
return GetAnyRectObject();
}
GLenum
FBStatus
WebGLFramebuffer::PrecheckFramebufferStatus() const
{
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
@ -777,13 +766,13 @@ WebGLFramebuffer::PrecheckFramebufferStatus() const
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
}
GLenum
FBStatus
WebGLFramebuffer::CheckFramebufferStatus() const
{
if (mStatus != 0)
return mStatus;
mStatus = PrecheckFramebufferStatus();
mStatus = PrecheckFramebufferStatus().get();
if (mStatus != LOCAL_GL_FRAMEBUFFER_COMPLETE)
return mStatus;
@ -897,33 +886,6 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
return true;
}
bool WebGLFramebuffer::CheckColorAttachmentNumber(GLenum attachment, const char* functionName) const
{
const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
if (mContext->IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
{
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
return false;
}
} else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0) {
if (attachment > LOCAL_GL_COLOR_ATTACHMENT0 &&
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
{
mContext->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x. "
"Try the WEBGL_draw_buffers extension if supported.", functionName, attachment);
return false;
} else {
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
return false;
}
}
return true;
}
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId)
{
MOZ_ASSERT(colorAttachmentId < WebGLContext::kMaxColorAttachments);

View File

@ -25,7 +25,7 @@ namespace gl {
class WebGLFramebuffer MOZ_FINAL
: public nsWrapperCache
, public WebGLBindableName<GLenum>
, public WebGLBindableName<FBTarget>
, public WebGLRefCountedObject<WebGLFramebuffer>
, public LinkedListElement<WebGLFramebuffer>
, public WebGLContextBoundObject
@ -41,12 +41,12 @@ public:
// deleting a texture or renderbuffer immediately detaches it
WebGLRefPtr<WebGLTexture> mTexturePtr;
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
GLenum mAttachmentPoint;
FBAttachment mAttachmentPoint;
TexImageTarget mTexImageTarget;
GLint mTexImageLevel;
mutable bool mNeedsFinalize;
explicit Attachment(GLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
explicit Attachment(FBAttachment aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
~Attachment();
bool IsDefined() const;
@ -88,18 +88,16 @@ public:
bool HasImage() const;
bool IsComplete() const;
void FinalizeAttachment(gl::GLContext* gl, GLenum attachmentLoc) const;
void FinalizeAttachment(gl::GLContext* gl, FBAttachment attachmentLoc) const;
};
void Delete();
void FramebufferRenderbuffer(GLenum target,
GLenum attachment,
GLenum rbtarget,
void FramebufferRenderbuffer(FBAttachment attachment,
RBTarget rbtarget,
WebGLRenderbuffer* wrb);
void FramebufferTexture2D(GLenum target,
GLenum attachment,
void FramebufferTexture2D(FBAttachment attachment,
TexImageTarget texImageTarget,
WebGLTexture* wtex,
GLint level);
@ -108,14 +106,14 @@ private:
void DetachAttachment(WebGLFramebuffer::Attachment& attachment);
void DetachAllAttachments();
const WebGLRectangleObject& GetAnyRectObject() const;
Attachment* GetAttachmentOrNull(GLenum attachment);
Attachment* GetAttachmentOrNull(FBAttachment attachment);
public:
bool HasDefinedAttachments() const;
bool HasIncompleteAttachments() const;
bool AllImageRectsMatch() const;
GLenum PrecheckFramebufferStatus() const;
GLenum CheckFramebufferStatus() const;
FBStatus PrecheckFramebufferStatus() const;
FBStatus CheckFramebufferStatus() const;
GLenum GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const;
bool HasDepthStencilConflict() const {
@ -143,7 +141,7 @@ public:
return mDepthStencilAttachment;
}
const Attachment& GetAttachment(GLenum attachment) const;
const Attachment& GetAttachment(FBAttachment attachment) const;
void DetachTexture(const WebGLTexture* tex);
@ -167,11 +165,10 @@ public:
bool CheckAndInitializeAttachments();
bool CheckColorAttachmentNumber(GLenum attachment, const char* functionName) const;
bool CheckColorAttachmentNumber(FBAttachment attachment, const char* functionName) const;
void EnsureColorAttachments(size_t colorAttachmentId);
Attachment* AttachmentFor(GLenum attachment);
void NotifyAttachableChanged() const;
private:

View File

@ -12,7 +12,7 @@
using namespace mozilla;
void
WebGLFramebufferAttachable::AttachTo(WebGLFramebuffer* fb, GLenum attachment)
WebGLFramebufferAttachable::AttachTo(WebGLFramebuffer* fb, FBAttachment attachment)
{
MOZ_ASSERT(fb);
if (!fb)
@ -25,7 +25,7 @@ WebGLFramebufferAttachable::AttachTo(WebGLFramebuffer* fb, GLenum attachment)
}
void
WebGLFramebufferAttachable::DetachFrom(WebGLFramebuffer* fb, GLenum attachment)
WebGLFramebufferAttachable::DetachFrom(WebGLFramebuffer* fb, FBAttachment attachment)
{
MOZ_ASSERT(fb);
if (!fb)

View File

@ -10,6 +10,7 @@
#include "nsTArray.h"
#include "mozilla/WeakPtr.h"
#include "WebGLFramebuffer.h"
#include "WebGLStrongTypes.h"
namespace mozilla {
@ -17,13 +18,13 @@ class WebGLFramebufferAttachable
{
struct AttachmentPoint
{
AttachmentPoint(const WebGLFramebuffer* fb, GLenum attachment)
AttachmentPoint(const WebGLFramebuffer* fb, FBAttachment attachment)
: mFB(fb)
, mAttachment(attachment)
{}
WeakPtr<const WebGLFramebuffer> mFB;
GLenum mAttachment;
FBAttachment mAttachment;
bool operator==(const AttachmentPoint& o) const {
return mFB == o.mFB && mAttachment == o.mAttachment;
@ -35,8 +36,8 @@ class WebGLFramebufferAttachable
public:
// Track FBO/Attachment combinations
void AttachTo(WebGLFramebuffer* fb, GLenum attachment);
void DetachFrom(WebGLFramebuffer* fb, GLenum attachment);
void AttachTo(WebGLFramebuffer* fb, FBAttachment attachment);
void DetachFrom(WebGLFramebuffer* fb, FBAttachment attachment);
void NotifyFBsStatusChanged();
};

View File

@ -43,7 +43,7 @@ WebGLRenderbuffer::WrapObject(JSContext *cx) {
}
WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext *context)
: WebGLBindableName<GLenum>()
: WebGLBindableName<RBTarget>()
, WebGLContextBoundObject(context)
, mPrimaryRB(0)
, mSecondaryRB(0)
@ -182,10 +182,10 @@ WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width, GLs
}
void
WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const {
WebGLRenderbuffer::FramebufferRenderbuffer(FBAttachment attachment) const {
GLContext* gl = mContext->gl;
if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment, LOCAL_GL_RENDERBUFFER, mPrimaryRB);
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment.get(), LOCAL_GL_RENDERBUFFER, mPrimaryRB);
return;
}
@ -200,10 +200,10 @@ WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const {
}
GLint
WebGLRenderbuffer::GetRenderbufferParameter(GLenum target, GLenum pname) const {
WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target, RBParam pname) const {
GLContext* gl = mContext->gl;
switch (pname) {
switch (pname.get()) {
case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE: {
if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
if (gl->WorkAroundDriverBugs() &&
@ -215,7 +215,7 @@ WebGLRenderbuffer::GetRenderbufferParameter(GLenum target, GLenum pname) const {
ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
GLint i = 0;
gl->fGetRenderbufferParameteriv(target, pname, &i);
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
return i;
}
// Fall through otherwise.
@ -228,7 +228,7 @@ WebGLRenderbuffer::GetRenderbufferParameter(GLenum target, GLenum pname) const {
case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE: {
GLint i = 0;
gl->fGetRenderbufferParameteriv(target, pname, &i);
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
return i;
}
}

View File

@ -18,7 +18,7 @@ namespace mozilla {
class WebGLRenderbuffer MOZ_FINAL
: public nsWrapperCache
, public WebGLBindableName<GLenum>
, public WebGLBindableName<RBTarget>
, public WebGLRefCountedObject<WebGLRenderbuffer>
, public LinkedListElement<WebGLRenderbuffer>
, public WebGLRectangleObject
@ -52,9 +52,9 @@ public:
void BindRenderbuffer() const;
void RenderbufferStorage(GLenum internalFormat, GLsizei width, GLsizei height) const;
void FramebufferRenderbuffer(GLenum attachment) const;
void FramebufferRenderbuffer(FBAttachment attachment) const;
// Only handles a subset of `pname`s.
GLint GetRenderbufferParameter(GLenum target, GLenum pname) const;
GLint GetRenderbufferParameter(RBTarget target, RBParam pname) const;
virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;

View File

@ -153,6 +153,14 @@ public:
return get() != other.get();
}
bool operator<=(const StrongGLenum& other) const {
return get() <= other.get();
}
bool operator>=(const StrongGLenum& other) const {
return get() >= other.get();
}
static bool IsValueLegal(GLenum value) {
if (value > UINT16_MAX) {
return false;
@ -342,4 +350,59 @@ STRONG_GLENUM_BEGIN(TexInternalFormat)
STRONG_GLENUM_VALUE(RGB10_A2UI),
STRONG_GLENUM_END(TexInternalFormat)
STRONG_GLENUM_BEGIN(FBTarget)
STRONG_GLENUM_VALUE(NONE),
STRONG_GLENUM_VALUE(READ_FRAMEBUFFER),
STRONG_GLENUM_VALUE(DRAW_FRAMEBUFFER),
STRONG_GLENUM_VALUE(FRAMEBUFFER),
STRONG_GLENUM_END(FBTarget)
STRONG_GLENUM_BEGIN(RBTarget)
STRONG_GLENUM_VALUE(NONE),
STRONG_GLENUM_VALUE(RENDERBUFFER),
STRONG_GLENUM_END(RBTarget)
STRONG_GLENUM_BEGIN(FBAttachment)
STRONG_GLENUM_VALUE(DEPTH_STENCIL_ATTACHMENT),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT0),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT1),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT2),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT3),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT4),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT5),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT6),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT7),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT8),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT9),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT10),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT11),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT12),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT13),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT14),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT15),
STRONG_GLENUM_VALUE(DEPTH_ATTACHMENT),
STRONG_GLENUM_VALUE(STENCIL_ATTACHMENT),
STRONG_GLENUM_END(FBAttachment)
STRONG_GLENUM_BEGIN(FBStatus)
STRONG_GLENUM_VALUE(FRAMEBUFFER_COMPLETE),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_DIMENSIONS),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_READ_BUFFER),
STRONG_GLENUM_VALUE(FRAMEBUFFER_UNSUPPORTED),
STRONG_GLENUM_END(FBStatus)
STRONG_GLENUM_BEGIN(RBParam)
STRONG_GLENUM_VALUE(RENDERBUFFER_WIDTH),
STRONG_GLENUM_VALUE(RENDERBUFFER_HEIGHT),
STRONG_GLENUM_VALUE(RENDERBUFFER_RED_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_GREEN_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_BLUE_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_ALPHA_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_DEPTH_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_STENCIL_SIZE),
STRONG_GLENUM_END(RBParam)
#endif

View File

@ -17,7 +17,7 @@ EXPORTS.mozilla.dom += [
'DataStoreService.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'DataStore.cpp',
'DataStoreCursor.cpp',
'DataStoreDB.cpp',

View File

@ -278,8 +278,7 @@ DOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
{
nsRefPtr<EventHandlerNonNull> handler;
JS::Rooted<JSObject*> callable(aCx);
if (aValue.isObject() &&
JS_ObjectIsCallable(aCx, callable = &aValue.toObject())) {
if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) {
handler = new EventHandlerNonNull(callable, dom::GetIncumbentGlobal());
}
SetEventHandler(aType, EmptyString(), handler);

View File

@ -13,7 +13,7 @@ EXPORTS.mozilla.dom += [
'FileSystemUtils.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'CreateDirectoryTask.cpp',
'CreateFileTask.cpp',
'DeviceStorageFileSystem.cpp',

View File

@ -11,7 +11,7 @@ EXPORTS.mozilla.dom += [
'FMRadioRequestParent.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'FMRadioChild.cpp',
'FMRadioParent.cpp',
'FMRadioRequestChild.cpp',

View File

@ -15,7 +15,7 @@ if CONFIG['MOZ_B2G_FM']:
'FMRadioService.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'FMRadio.cpp',
'FMRadioService.cpp',
]

View File

@ -11,7 +11,7 @@ EXPORTS.mozilla.dom += [
'IccManager.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'Icc.cpp',
'IccListener.cpp',
'IccManager.cpp',

View File

@ -217,8 +217,7 @@ nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue,
JS::Rooted<JS::Value> val(cx, aValue);
JS::Rooted<JS::Value> toJSON(cx);
if (JS_GetProperty(cx, obj, "toJSON", &toJSON) &&
toJSON.isObject() &&
JS_ObjectIsCallable(cx, &toJSON.toObject())) {
toJSON.isObject() && JS::IsCallable(&toJSON.toObject())) {
// If toJSON is implemented, it must not throw
if (!JS_CallFunctionValue(cx, obj, toJSON, JS::HandleValueArray::empty(), &val)) {
if (JS_IsExceptionPending(cx))

View File

@ -21,6 +21,9 @@
#include "nsJSUtils.h"
#include "nsServiceManagerUtils.h"
#ifdef CONVERT_STRING_TO_NULLABLE_ENUM
#undef CONVERT_STRING_TO_NULLABLE_ENUM
#endif
#define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum) \
{ \
uint32_t i = 0; \

View File

@ -10,6 +10,9 @@
#include "jsapi.h"
#ifdef CONVERT_STRING_TO_NULLABLE_ENUM
#undef CONVERT_STRING_TO_NULLABLE_ENUM
#endif
#define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum) \
{ \
_enum.SetNull(); \

View File

@ -30,7 +30,7 @@ XPIDL_SOURCES += [
'interfaces/nsINeighboringCellInfo.idl',
]
SOURCES += [
UNIFIED_SOURCES += [
'DOMMMIError.cpp',
'ipc/MobileConnectionChild.cpp',
'ipc/MobileConnectionIPCService.cpp',

View File

@ -10,16 +10,12 @@
namespace {
const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
#define kPrefDefaultServiceId "dom.sms.defaultServiceId"
const char* kObservedPrefs[] = {
kPrefDefaultServiceId,
nullptr
};
uint32_t
getDefaultServiceId()
{
static const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
int32_t id = mozilla::Preferences::GetInt(kPrefDefaultServiceId, 0);
int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1);
@ -46,6 +42,10 @@ SmsService::SmsService()
NS_WARN_IF_FALSE(mRil, "This shouldn't fail!");
// Initialize observer.
static const char* kObservedPrefs[] = {
kPrefDefaultServiceId,
nullptr
};
Preferences::AddStrongObservers(this, kObservedPrefs);
mDefaultServiceId = getDefaultServiceId();
}

View File

@ -19,14 +19,8 @@ using namespace mozilla::dom::mobilemessage;
namespace {
const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
#define kPrefMmsDefaultServiceId "dom.mms.defaultServiceId"
#define kPrefSmsDefaultServiceId "dom.sms.defaultServiceId"
const char* kObservedPrefs[] = {
kPrefMmsDefaultServiceId,
kPrefSmsDefaultServiceId,
nullptr
};
// TODO: Bug 767082 - WebSMS: sSmsChild leaks at shutdown
PSmsChild* gSmsChild;
@ -86,6 +80,7 @@ SendCursorRequest(const IPCMobileMessageCursor& aRequest,
uint32_t
getDefaultServiceId(const char* aPrefKey)
{
static const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
int32_t id = mozilla::Preferences::GetInt(aPrefKey, 0);
int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1);
@ -119,6 +114,11 @@ SmsIPCService::GetSingleton()
SmsIPCService::SmsIPCService()
{
static const char* kObservedPrefs[] = {
kPrefMmsDefaultServiceId,
kPrefSmsDefaultServiceId,
nullptr
};
Preferences::AddStrongObservers(this, kObservedPrefs);
mMmsDefaultServiceId = getDefaultServiceId(kPrefMmsDefaultServiceId);
mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId);

View File

@ -35,7 +35,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
'gonk/MobileMessageDatabaseService.js',
'gonk/MobileMessageDatabaseService.manifest',
]
SOURCES += [
UNIFIED_SOURCES += [
'gonk/SmsService.cpp',
]

View File

@ -14,7 +14,7 @@ if CONFIG['MOZ_NFC']:
EXPORTS.mozilla.dom += [
'MozNDEFRecord.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'MozNDEFRecord.cpp',
]
EXTRA_COMPONENTS += [
@ -24,7 +24,7 @@ if CONFIG['MOZ_NFC']:
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_NFC']:
SOURCES += [
UNIFIED_SOURCES += [
'gonk/NfcMessageHandler.cpp',
'gonk/NfcService.cpp',
]

View File

@ -1609,7 +1609,7 @@ NPObjWrapper_Convert(JSContext *cx, JS::Handle<JSObject*> obj, JSType hint, JS::
JS::Rooted<JS::Value> v(cx, JSVAL_VOID);
if (!JS_GetProperty(cx, obj, "toString", &v))
return false;
if (!v.isPrimitive() && JS_ObjectIsCallable(cx, v.toObjectOrNull())) {
if (!v.isPrimitive() && JS::IsCallable(v.toObjectOrNull())) {
if (!JS_CallFunctionValue(cx, obj, v, JS::HandleValueArray::empty(), vp))
return false;
if (vp.isPrimitive())

View File

@ -1092,7 +1092,7 @@ Promise::ResolveInternal(JSContext* aCx,
return;
}
if (then.isObject() && JS_ObjectIsCallable(aCx, &then.toObject())) {
if (then.isObject() && JS::IsCallable(&then.toObject())) {
// This is the then() function of the thenable aValueObj.
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
nsRefPtr<PromiseInit> thenCallback =

View File

@ -12,7 +12,7 @@ EXPORTS += [
'SpeakerManagerServiceChild.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'SpeakerManager.cpp',
'SpeakerManagerService.cpp',
'SpeakerManagerServiceChild.cpp',

View File

@ -378,7 +378,7 @@ Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer
// The volume name will have already been parsed, and the tokenizer will point
// to the token after the volume name
switch (aResponseCode) {
case ResponseCode::VolumeListResult: {
case ::ResponseCode::VolumeListResult: {
// Each line will look something like:
//
// sdcard /mnt/sdcard 1
@ -397,7 +397,7 @@ Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer
break;
}
case ResponseCode::VolumeStateChange: {
case ::ResponseCode::VolumeStateChange: {
// Format of the line looks something like:
//
// Volume sdcard /mnt/sdcard state changed from 7 (Shared-Unmounted) to 1 (Idle-Unmounted)
@ -415,12 +415,12 @@ Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer
break;
}
case ResponseCode::VolumeDiskInserted:
case ::ResponseCode::VolumeDiskInserted:
SetMediaPresent(true);
break;
case ResponseCode::VolumeDiskRemoved: // fall-thru
case ResponseCode::VolumeBadRemoval:
case ::ResponseCode::VolumeDiskRemoved: // fall-thru
case ::ResponseCode::VolumeBadRemoval:
SetMediaPresent(false);
break;

View File

@ -143,7 +143,7 @@ class VolumeListCallback : public VolumeResponseCallback
virtual void ResponseReceived(const VolumeCommand* aCommand)
{
switch (ResponseCode()) {
case ResponseCode::VolumeListResult: {
case ::ResponseCode::VolumeListResult: {
// Each line will look something like:
//
// sdcard /mnt/sdcard 1
@ -157,7 +157,7 @@ class VolumeListCallback : public VolumeResponseCallback
break;
}
case ResponseCode::CommandOkay: {
case ::ResponseCode::CommandOkay: {
// We've received the list of volumes. Tell anybody who
// is listening that we're open for business.
VolumeManager::SetState(VolumeManager::VOLUMES_READY);
@ -285,7 +285,7 @@ VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
nsDependentCString responseLine(endPtr, aMessage.Length() - (endPtr - aMessage.Data()));
DBG("Rcvd: %d '%s'", responseCode, responseLine.Data());
if (responseCode >= ResponseCode::UnsolicitedInformational) {
if (responseCode >= ::ResponseCode::UnsolicitedInformational) {
// These are unsolicited broadcasts. We intercept these and process
// them ourselves
HandleBroadcast(responseCode, responseLine);
@ -294,7 +294,7 @@ VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
if (mCommands.size() > 0) {
VolumeCommand* cmd = mCommands.front();
cmd->HandleResponse(responseCode, responseLine);
if (responseCode >= ResponseCode::CommandOkay) {
if (responseCode >= ::ResponseCode::CommandOkay) {
// That's a terminating response. We can remove the command.
mCommands.pop();
mCommandPending = false;

View File

@ -35,7 +35,7 @@ EXPORTS += [
'nsVolume.h',
'nsVolumeService.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'AudioChannelManager.cpp',
'AudioManager.cpp',
'AutoMounter.cpp',

View File

@ -31,7 +31,7 @@ var expected = [
{ name: "", message: "uncaught exception: [object Object]" },
{ name: "InvalidStateError", message: "An attempt was made to use an object that is not, or is no longer, usable", filename: location, lineNumber: 60 },
{ name: "ReferenceError", message: "xxx is not defined", filename: location, lineNumber: 64 },
{ name: "ReferenceError", message: "xxx is not defined, did you mean 'x'?", filename: location, lineNumber: 66 }
{ name: "ReferenceError", message: "xxx is not defined", filename: location, lineNumber: 66 }
];
var counter = 0;

View File

@ -30,7 +30,7 @@ EXTRA_JS_MODULES += [
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
SOURCES = [
UNIFIED_SOURCES = [
'WifiCertService.cpp',
'WifiHotspotUtils.cpp',
'WifiProxyService.cpp',

View File

@ -27,13 +27,13 @@ namespace {
class DelayedEventRunnable MOZ_FINAL : public WorkerRunnable
{
nsRefPtr<MessagePort> mMessagePort;
nsRefPtr<mozilla::dom::workers::MessagePort> mMessagePort;
nsTArray<nsCOMPtr<nsIDOMEvent>> mEvents;
public:
DelayedEventRunnable(WorkerPrivate* aWorkerPrivate,
TargetAndBusyBehavior aBehavior,
MessagePort* aMessagePort,
mozilla::dom::workers::MessagePort* aMessagePort,
nsTArray<nsCOMPtr<nsIDOMEvent>>& aEvents)
: WorkerRunnable(aWorkerPrivate, aBehavior), mMessagePort(aMessagePort)
{
@ -72,6 +72,8 @@ public:
} // anonymous namespace
BEGIN_WORKERS_NAMESPACE
MessagePort::MessagePort(nsPIDOMWindow* aWindow, SharedWorker* aSharedWorker,
uint64_t aSerial)
: MessagePortBase(aWindow), mSharedWorker(aSharedWorker),
@ -298,6 +300,8 @@ MessagePort::PreHandleEvent(EventChainPreVisitor& aVisitor)
return DOMEventTargetHelper::PreHandleEvent(aVisitor);
}
END_WORKERS_NAMESPACE
bool
DelayedEventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{

View File

@ -478,69 +478,6 @@ public:
}
};
/*
* Implements the async aspects of the unregister algorithm.
*/
class UnregisterRunnable : public nsRunnable
{
nsCOMPtr<nsIServiceWorkerUnregisterCallback> mCallback;
nsCOMPtr<nsIURI> mScopeURI;
public:
UnregisterRunnable(nsIServiceWorkerUnregisterCallback* aCallback,
nsIURI* aScopeURI)
: mCallback(aCallback), mScopeURI(aScopeURI)
{
AssertIsOnMainThread();
}
NS_IMETHODIMP
Run()
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo =
swm->GetDomainInfo(mScopeURI);
MOZ_ASSERT(domainInfo);
nsCString spec;
nsresult rv = mScopeURI->GetSpecIgnoringRef(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return mCallback->UnregisterFailed();
}
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
if (!domainInfo->mServiceWorkerRegistrationInfos.Get(spec,
getter_AddRefs(registration))) {
return mCallback->UnregisterSucceeded(false);
}
MOZ_ASSERT(registration);
registration->mPendingUninstall = true;
rv = mCallback->UnregisterSucceeded(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// The "Wait until no document is using registration" can actually be
// handled by [[HandleDocumentUnload]] in Bug 1041340, so we simply check
// if the document is currently in use here.
if (!registration->IsControllingDocuments()) {
if (!registration->mPendingUninstall) {
return NS_OK;
}
registration->Clear();
domainInfo->RemoveRegistration(registration);
}
return NS_OK;
}
};
// If we return an error code here, the ServiceWorkerContainer will
// automatically reject the Promise.
NS_IMETHODIMP
@ -1057,6 +994,69 @@ ServiceWorkerManager::Unregister(nsIServiceWorkerUnregisterCallback* aCallback,
return NS_ERROR_DOM_SECURITY_ERR;
}
/*
* Implements the async aspects of the unregister algorithm.
*/
class UnregisterRunnable : public nsRunnable
{
nsCOMPtr<nsIServiceWorkerUnregisterCallback> mCallback;
nsCOMPtr<nsIURI> mScopeURI;
public:
UnregisterRunnable(nsIServiceWorkerUnregisterCallback* aCallback,
nsIURI* aScopeURI)
: mCallback(aCallback), mScopeURI(aScopeURI)
{
AssertIsOnMainThread();
}
NS_IMETHODIMP
Run()
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo =
swm->GetDomainInfo(mScopeURI);
MOZ_ASSERT(domainInfo);
nsCString spec;
nsresult rv = mScopeURI->GetSpecIgnoringRef(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return mCallback->UnregisterFailed();
}
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
if (!domainInfo->mServiceWorkerRegistrationInfos.Get(spec,
getter_AddRefs(registration))) {
return mCallback->UnregisterSucceeded(false);
}
MOZ_ASSERT(registration);
registration->mPendingUninstall = true;
rv = mCallback->UnregisterSucceeded(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// The "Wait until no document is using registration" can actually be
// handled by [[HandleDocumentUnload]] in Bug 1041340, so we simply check
// if the document is currently in use here.
if (!registration->IsControllingDocuments()) {
if (!registration->mPendingUninstall) {
return NS_OK;
}
registration->Clear();
domainInfo->RemoveRegistration(registration);
}
return NS_OK;
}
};
nsRefPtr<nsIRunnable> unregisterRunnable =
new UnregisterRunnable(aCallback, scopeURI);
return NS_DispatchToCurrentThread(unregisterRunnable);

View File

@ -203,7 +203,6 @@ class ServiceWorkerManager MOZ_FINAL : public nsIServiceWorkerManager
friend class GetReadyPromiseRunnable;
friend class GetRegistrationsRunnable;
friend class GetRegistrationRunnable;
friend class UnregisterRunnable;
public:
NS_DECL_ISUPPORTS

View File

@ -75,7 +75,7 @@ SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
return sharedWorker.forget();
}
already_AddRefed<MessagePort>
already_AddRefed<mozilla::dom::workers::MessagePort>
SharedWorker::Port()
{
AssertIsOnMainThread();

View File

@ -45,7 +45,7 @@ public:
const nsAString& aScriptURL, const Optional<nsAString>& aName,
ErrorResult& aRv);
already_AddRefed<MessagePort>
already_AddRefed<mozilla::dom::workers::MessagePort>
Port();
uint64_t

View File

@ -1212,8 +1212,8 @@ EventRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
// Anything subject to GC must be cloned.
JSStructuredCloneCallbacks* callbacks =
aWorkerPrivate->IsChromeWorker() ?
ChromeWorkerStructuredCloneCallbacks(true) :
WorkerStructuredCloneCallbacks(true);
workers::ChromeWorkerStructuredCloneCallbacks(true) :
workers::WorkerStructuredCloneCallbacks(true);
nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
@ -1320,8 +1320,8 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
JSStructuredCloneCallbacks* callbacks =
aWorkerPrivate->IsChromeWorker() ?
ChromeWorkerStructuredCloneCallbacks(false) :
WorkerStructuredCloneCallbacks(false);
workers::ChromeWorkerStructuredCloneCallbacks(false) :
workers::WorkerStructuredCloneCallbacks(false);
nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
clonedObjects.SwapElements(mClonedObjects);
@ -1504,8 +1504,8 @@ SendRunnable::MainThreadRun()
JSStructuredCloneCallbacks* callbacks =
mWorkerPrivate->IsChromeWorker() ?
ChromeWorkerStructuredCloneCallbacks(true) :
WorkerStructuredCloneCallbacks(true);
workers::ChromeWorkerStructuredCloneCallbacks(true) :
workers::WorkerStructuredCloneCallbacks(true);
JS::Rooted<JS::Value> body(cx);
if (mBody.read(cx, &body, callbacks, &mClonedObjects)) {

View File

@ -36,7 +36,7 @@ EXPORTS.mozilla.dom.workers.bindings += [
'XMLHttpRequestUpload.h',
]
SOURCES += [
UNIFIED_SOURCES += [
'ChromeWorkerScope.cpp',
'DataStore.cpp',
'DataStoreCursor.cpp',

View File

@ -52,7 +52,7 @@ Tests of DOM Worker Threads (Bug 437152)
worker.onerror = function(otherEvent) {
otherEvent.preventDefault();
is(otherEvent.target, worker);
ok(otherEvent.message.contains("ReferenceError: Components is not defined"));
is(otherEvent.message, "ReferenceError: Components is not defined");
gotErrors = true;
worker.onerror = function(oneMoreEvent) {

View File

@ -133,14 +133,14 @@ struct AlignedArray
}
#endif
delete [] mStorage;
moz_free(mStorage);
mStorage = nullptr;
mPtr = nullptr;
}
MOZ_ALWAYS_INLINE void Realloc(size_t aCount, bool aZero = false)
{
delete [] mStorage;
moz_free(mStorage);
CheckedInt32 storageByteCount =
CheckedInt32(sizeof(T)) * aCount + (alignment - 1);
if (!storageByteCount.isValid()) {
@ -152,9 +152,11 @@ struct AlignedArray
// We don't create an array of T here, since we don't want ctors to be
// invoked at the wrong places if we realign below.
if (aZero) {
mStorage = static_cast<uint8_t *>(calloc(1, storageByteCount.value()));
// calloc can be more efficient than new[] for large chunks,
// so we use calloc/malloc/free for everything.
mStorage = static_cast<uint8_t *>(moz_calloc(1, storageByteCount.value()));
} else {
mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
mStorage = static_cast<uint8_t *>(moz_malloc(storageByteCount.value()));
}
if (!mStorage) {
mStorage = nullptr;

View File

@ -1,490 +0,0 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
namespace {
// we use macros here instead of function definitions to work around more GLSL
// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
// problematic because if the argument has side-effects they will be repeatedly
// evaluated. This is unlikely to show up in real shaders, but is something to
// consider.
const char* kFunctionEmulationVertexSource[] = {
"#error no emulation for cos(float)",
"#error no emulation for cos(vec2)",
"#error no emulation for cos(vec3)",
"#error no emulation for cos(vec4)",
"#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
"#error no emulation for distance(vec2, vec2)",
"#error no emulation for distance(vec3, vec3)",
"#error no emulation for distance(vec4, vec4)",
"#define webgl_dot_emu(x, y) ((x) * (y))",
"#error no emulation for dot(vec2, vec2)",
"#error no emulation for dot(vec3, vec3)",
"#error no emulation for dot(vec4, vec4)",
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
"#error no emulation for length(vec2)",
"#error no emulation for length(vec3)",
"#error no emulation for length(vec4)",
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
"#error no emulation for normalize(vec2)",
"#error no emulation for normalize(vec3)",
"#error no emulation for normalize(vec4)",
"#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
"#error no emulation for reflect(vec2, vec2)",
"#error no emulation for reflect(vec3, vec3)",
"#error no emulation for reflect(vec4, vec4)",
// |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N|
"#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))",
"#error no emulation for faceforward(vec2, vec2, vec2)",
"#error no emulation for faceforward(vec3, vec3, vec3)",
"#error no emulation for faceforward(vec4, vec4, vec4)"
};
const char* kFunctionEmulationFragmentSource[] = {
"webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
"webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
"webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
"webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
"#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
"#error no emulation for distance(vec2, vec2)",
"#error no emulation for distance(vec3, vec3)",
"#error no emulation for distance(vec4, vec4)",
"#define webgl_dot_emu(x, y) ((x) * (y))",
"#error no emulation for dot(vec2, vec2)",
"#error no emulation for dot(vec3, vec3)",
"#error no emulation for dot(vec4, vec4)",
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
"#error no emulation for length(vec2)",
"#error no emulation for length(vec3)",
"#error no emulation for length(vec4)",
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
"#error no emulation for normalize(vec2)",
"#error no emulation for normalize(vec3)",
"#error no emulation for normalize(vec4)",
"#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
"#error no emulation for reflect(vec2, vec2)",
"#error no emulation for reflect(vec3, vec3)",
"#error no emulation for reflect(vec4, vec4)",
// |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N|
"#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))",
"#error no emulation for faceforward(vec2, vec2, vec2)",
"#error no emulation for faceforward(vec3, vec3, vec3)",
"#error no emulation for faceforward(vec4, vec4, vec4)"
};
const bool kFunctionEmulationVertexMask[] = {
#if defined(__APPLE__)
// Work around ATI driver bugs in Mac.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
true, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
true, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
true, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
true, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
true, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
true, // TFunctionFaceForward1_1_1
false, // TFunctionFaceForward2_2_2
false, // TFunctionFaceForward3_3_3
false, // TFunctionFaceForward4_4_4
#else
// Work around D3D driver bug in Win.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
false, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
false, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
false, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
false, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
false, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
false, // TFunctionFaceForward1_1_1
false, // TFunctionFaceForward2_2_2
false, // TFunctionFaceForward3_3_3
false, // TFunctionFaceForward4_4_4
#endif
false // TFunctionUnknown
};
const bool kFunctionEmulationFragmentMask[] = {
#if defined(__APPLE__)
// Work around ATI driver bugs in Mac.
true, // TFunctionCos1
true, // TFunctionCos2
true, // TFunctionCos3
true, // TFunctionCos4
true, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
true, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
true, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
true, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
true, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
true, // TFunctionFaceForward1_1_1
false, // TFunctionFaceForward2_2_2
false, // TFunctionFaceForward3_3_3
false, // TFunctionFaceForward4_4_4
#else
// Work around D3D driver bug in Win.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
false, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
false, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
false, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
false, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
false, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
false, // TFunctionFaceForward1_1_1
false, // TFunctionFaceForward2_2_2
false, // TFunctionFaceForward3_3_3
false, // TFunctionFaceForward4_4_4
#endif
false // TFunctionUnknown
};
class BuiltInFunctionEmulationMarker : public TIntermTraverser {
public:
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
: mEmulator(emulator)
{
}
virtual bool visitUnary(Visit visit, TIntermUnary* node)
{
if (visit == PreVisit) {
bool needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), node->getOperand()->getType());
if (needToEmulate)
node->setUseEmulatedFunction();
}
return true;
}
virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
{
if (visit == PreVisit) {
// Here we handle all the built-in functions instead of the ones we
// currently identified as problematic.
switch (node->getOp()) {
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
case EOpVectorEqual:
case EOpVectorNotEqual:
case EOpMod:
case EOpPow:
case EOpAtan:
case EOpMin:
case EOpMax:
case EOpClamp:
case EOpMix:
case EOpStep:
case EOpSmoothStep:
case EOpDistance:
case EOpDot:
case EOpCross:
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
case EOpMul:
break;
default:
return true;
};
<<<<<<< HEAD
const TIntermSequence& sequence = *(node->getSequence());
// Right now we only handle built-in functions with two parameters.
if (sequence.size() != 2)
return true;
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
=======
const TIntermSequence& sequence = node->getSequence();
bool needToEmulate = false;
if (sequence.size() == 2) {
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType());
} else if (sequence.size() == 3) {
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
TIntermTyped* param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType(), param3->getType());
} else {
>>>>>>> 700b9c6... Emulate faceforward(float, float, float) when function emulation is enabled
return true;
}
if (needToEmulate)
node->setUseEmulatedFunction();
}
return true;
}
private:
BuiltInFunctionEmulator& mEmulator;
};
} // anonymous namepsace
BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType)
{
if (shaderType == GL_FRAGMENT_SHADER) {
mFunctionMask = kFunctionEmulationFragmentMask;
mFunctionSource = kFunctionEmulationFragmentSource;
} else {
mFunctionMask = kFunctionEmulationVertexMask;
mFunctionSource = kFunctionEmulationVertexSource;
}
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param)
{
TBuiltInFunction function = IdentifyFunction(op, param);
return SetFunctionCalled(function);
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2)
{
TBuiltInFunction function = IdentifyFunction(op, param1, param2);
return SetFunctionCalled(function);
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2, const TType& param3)
{
TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3);
return SetFunctionCalled(function);
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
BuiltInFunctionEmulator::TBuiltInFunction function) {
if (function == TFunctionUnknown || mFunctionMask[function] == false)
return false;
for (size_t i = 0; i < mFunctions.size(); ++i) {
if (mFunctions[i] == function)
return true;
}
mFunctions.push_back(function);
return true;
}
void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
TInfoSinkBase& out, bool withPrecision) const
{
if (mFunctions.size() == 0)
return;
out << "// BEGIN: Generated code for built-in function emulation\n\n";
if (withPrecision) {
out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
<< "#define webgl_emu_precision highp\n"
<< "#else\n"
<< "#define webgl_emu_precision mediump\n"
<< "#endif\n\n";
} else {
out << "#define webgl_emu_precision\n\n";
}
for (size_t i = 0; i < mFunctions.size(); ++i) {
out << mFunctionSource[mFunctions[i]] << "\n\n";
}
out << "// END: Generated code for built-in function emulation\n\n";
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param)
{
if (param.getNominalSize() > 4 || param.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpCos:
function = TFunctionCos1;
break;
case EOpLength:
function = TFunctionLength1;
break;
case EOpNormalize:
function = TFunctionNormalize1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param.isVector())
function += param.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param1, const TType& param2)
{
// Right now for all the emulated functions with two parameters, the two
// parameters have the same type.
if (param1.getNominalSize() != param2.getNominalSize() ||
param1.getSecondarySize() != param2.getSecondarySize() ||
param1.getNominalSize() > 4 || param1.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpDistance:
function = TFunctionDistance1_1;
break;
case EOpDot:
function = TFunctionDot1_1;
break;
case EOpReflect:
function = TFunctionReflect1_1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param1.isVector())
function += param1.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param1, const TType& param2, const TType& param3)
{
// Check that all params have the same type, length,
// and that they're not too large.
if (param1.isVector() != param2.isVector() ||
param2.isVector() != param3.isVector() ||
param1.getNominalSize() != param2.getNominalSize() ||
param2.getNominalSize() != param3.getNominalSize() ||
param1.getNominalSize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpFaceForward:
function = TFunctionFaceForward1_1_1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param1.isVector())
function += param1.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
}
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
TIntermNode* root)
{
ASSERT(root);
BuiltInFunctionEmulationMarker marker(*this);
root->traverse(&marker);
}
void BuiltInFunctionEmulator::Cleanup()
{
mFunctions.clear();
}
//static
TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
const TString& name)
{
ASSERT(name[name.length() - 1] == '(');
return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
}

View File

@ -1,629 +0,0 @@
//
// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// formatutils9.cpp: Queries for GL image formats and their translations to D3D9
// formats.
#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
#include "libGLESv2/renderer/generatemip.h"
#include "libGLESv2/renderer/loadimage.h"
#include "libGLESv2/renderer/copyimage.h"
#include "libGLESv2/renderer/vertexconversion.h"
namespace rx
{
namespace d3d9
{
const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
struct D3D9FastCopyFormat
{
GLenum destFormat;
GLenum destType;
ColorCopyFunction copyFunction;
D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction)
: destFormat(destFormat), destType(destType), copyFunction(copyFunction)
{ }
bool operator<(const D3D9FastCopyFormat& other) const
{
return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0;
}
};
typedef std::multimap<D3DFORMAT, D3D9FastCopyFormat> D3D9FastCopyMap;
static D3D9FastCopyMap BuildFastCopyMap()
{
D3D9FastCopyMap map;
<<<<<<< HEAD
map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8)));
=======
// | Internal format | Texture format | Render format | Load function |
map.insert(D3D9FormatPair(GL_NONE, D3D9FormatInfo(D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad )));
map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT16, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad )));
map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT32_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad )));
map.insert(D3D9FormatPair(GL_DEPTH24_STENCIL8_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad )));
map.insert(D3D9FormatPair(GL_STENCIL_INDEX8, D3D9FormatInfo(D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ))); // TODO: What's the texture format?
map.insert(D3D9FormatPair(GL_RGBA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, loadToNative<GLfloat, 4> )));
map.insert(D3D9FormatPair(GL_RGB32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, loadToNative3To4<GLfloat, gl::Float32One>)));
map.insert(D3D9FormatPair(GL_RG32F_EXT, D3D9FormatInfo(D3DFMT_G32R32F, D3DFMT_G32R32F, loadToNative<GLfloat, 2> )));
map.insert(D3D9FormatPair(GL_R32F_EXT, D3D9FormatInfo(D3DFMT_R32F, D3DFMT_R32F, loadToNative<GLfloat, 1> )));
map.insert(D3D9FormatPair(GL_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, loadAlphaFloatDataToRGBA )));
map.insert(D3D9FormatPair(GL_LUMINANCE32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, loadLuminanceFloatDataToRGBA )));
map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, loadLuminanceAlphaFloatDataToRGBA )));
map.insert(D3D9FormatPair(GL_RGBA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, loadToNative<GLhalf, 4> )));
map.insert(D3D9FormatPair(GL_RGB16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, loadToNative3To4<GLhalf, gl::Float16One> )));
map.insert(D3D9FormatPair(GL_RG16F_EXT, D3D9FormatInfo(D3DFMT_G16R16F, D3DFMT_G16R16F, loadToNative<GLhalf, 2> )));
map.insert(D3D9FormatPair(GL_R16F_EXT, D3D9FormatInfo(D3DFMT_R16F, D3DFMT_R16F, loadToNative<GLhalf, 1> )));
map.insert(D3D9FormatPair(GL_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, loadAlphaHalfFloatDataToRGBA )));
map.insert(D3D9FormatPair(GL_LUMINANCE16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, loadLuminanceHalfFloatDataToRGBA )));
map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, loadLuminanceAlphaHalfFloatDataToRGBA )));
map.insert(D3D9FormatPair(GL_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, loadAlphaDataToBGRASSE2, loadAlphaDataToBGRA>)));
map.insert(D3D9FormatPair(GL_RGB8_OES, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRGBUByteDataToBGRX )));
map.insert(D3D9FormatPair(GL_RGB565, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRGB565DataToBGRA )));
map.insert(D3D9FormatPair(GL_RGBA8_OES, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, loadRGBAUByteDataToBGRASSE2, loadRGBAUByteDataToBGRA>)));
map.insert(D3D9FormatPair(GL_RGBA4, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA4444DataToBGRA )));
map.insert(D3D9FormatPair(GL_RGB5_A1, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA5551DataToBGRA )));
map.insert(D3D9FormatPair(GL_R8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRUByteDataToBGRX )));
map.insert(D3D9FormatPair(GL_RG8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, loadRGUByteDataToBGRX )));
map.insert(D3D9FormatPair(GL_BGRA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadToNative<GLubyte, 4> )));
map.insert(D3D9FormatPair(GL_BGRA4_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA4444DataToRGBA )));
map.insert(D3D9FormatPair(GL_BGR5_A1_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, loadRGBA5551DataToRGBA )));
map.insert(D3D9FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 8> )));
map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 8> )));
map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D9FormatInfo(D3DFMT_DXT3, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 16> )));
map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D9FormatInfo(D3DFMT_DXT5, D3DFMT_UNKNOWN, loadCompressedBlockDataToNative<4, 4, 16> )));
// These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and
// then changing the format and loading function appropriately.
map.insert(D3D9FormatPair(GL_LUMINANCE8_EXT, D3D9FormatInfo(D3DFMT_L8, D3DFMT_L8, loadToNative<GLubyte, 1> )));
map.insert(D3D9FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8L8, D3DFMT_A8L8, loadToNative<GLubyte, 2> )));
>>>>>>> 20c20e0... Fix for Windows XP conformance crash
return map;
}
// A map to determine the pixel size and mip generation function of a given D3D format
typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap;
D3DFormat::D3DFormat()
: pixelBytes(0),
blockWidth(0),
blockHeight(0),
internalFormat(GL_NONE),
mipGenerationFunction(NULL),
colorReadFunction(NULL),
fastCopyFunctions()
{
}
ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const
{
FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type));
return (iter != fastCopyFunctions.end()) ? iter->second : NULL;
}
static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth,
GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc,
ColorReadFunction colorReadFunc)
{
D3DFormat info;
info.pixelBytes = bits / 8;
info.blockWidth = blockWidth;
info.blockHeight = blockHeight;
info.internalFormat = internalFormat;
info.mipGenerationFunction = mipFunc;
info.colorReadFunction = colorReadFunc;
static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap();
std::pair<D3D9FastCopyMap::const_iterator, D3D9FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(format);
for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++)
{
info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction));
}
map->insert(std::make_pair(format, info));
}
static D3D9FormatInfoMap BuildD3D9FormatInfoMap()
{
D3D9FormatInfoMap map;
// | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function |
InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>);
InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> );
InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>);
InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL );
InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL );
return map;
}
const D3DFormat &GetD3DFormatInfo(D3DFORMAT format)
{
static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap();
D3D9FormatInfoMap::const_iterator iter = infoMap.find(format);
if (iter != infoMap.end())
{
return iter->second;
}
else
{
static const D3DFormat defaultInfo;
return defaultInfo;
}
}
typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair;
typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap;
static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
{
InternalFormatInitialzerMap map;
map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>));
map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
return map;
}
// Each GL internal format corresponds to one D3D format and data loading function.
// Due to not all formats being available all the time, some of the function/format types are wrapped
// in templates that perform format support queries on a Renderer9 object which is supplied
// when requesting the function or format.
typedef bool(*FallbackPredicateFunction)();
template <FallbackPredicateFunction pred, LoadImageFunction prefered, LoadImageFunction fallback>
static void FallbackLoad(size_t width, size_t height, size_t depth,
const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
{
if (pred())
{
prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
}
else
{
fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
}
}
static void UnreachableLoad(size_t width, size_t height, size_t depth,
const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
{
UNREACHABLE();
}
typedef std::pair<GLenum, TextureFormat> D3D9FormatPair;
typedef std::map<GLenum, TextureFormat> D3D9FormatMap;
TextureFormat::TextureFormat()
: texFormat(D3DFMT_NULL),
renderFormat(D3DFMT_NULL),
dataInitializerFunction(NULL),
loadFunction(UnreachableLoad)
{
}
static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat,
D3DFORMAT renderFormat, LoadImageFunction loadFunction)
{
TextureFormat info;
info.texFormat = texFormat;
info.renderFormat = renderFormat;
static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap();
InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat);
info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL;
info.loadFunction = loadFunction;
map->insert(std::make_pair(internalFormat, info));
}
static D3D9FormatMap BuildD3D9FormatMap()
{
D3D9FormatMap map;
// | Internal format | Texture format | Render format | Load function |
InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad );
InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad );
InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad );
InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad );
InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format?
InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative<GLfloat, 4> );
InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4<GLfloat, gl::Float32One>);
InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative<GLfloat, 2> );
InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative<GLfloat, 1> );
InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F );
InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F );
InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F );
InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative<GLhalf, 4> );
InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4<GLhalf, gl::Float16One> );
InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative<GLhalf, 2> );
InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative<GLhalf, 1> );
InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F );
InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F );
InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F );
InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, LoadA8ToBGRA8_SSE2, LoadA8ToBGRA8>);
InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 );
InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, LoadRGBA8ToBGRA8_SSE2, LoadRGBA8ToBGRA8>);
InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 );
InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 );
InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative<GLubyte, 4> );
InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> );
InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> );
InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> );
InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> );
// These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and
// then changing the format and loading function appropriately.
InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 1> );
InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> );
return map;
}
const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
{
static const D3D9FormatMap formatMap = BuildD3D9FormatMap();
D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat);
if (iter != formatMap.end())
{
return iter->second;
}
else
{
static const TextureFormat defaultInfo;
return defaultInfo;
}
}
static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType)
{
switch (declType)
{
case D3DDECLTYPE_FLOAT1: return GL_FLOAT;
case D3DDECLTYPE_FLOAT2: return GL_FLOAT;
case D3DDECLTYPE_FLOAT3: return GL_FLOAT;
case D3DDECLTYPE_FLOAT4: return GL_FLOAT;
case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT;
case D3DDECLTYPE_SHORT2: return GL_INT;
case D3DDECLTYPE_SHORT4: return GL_INT;
case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED;
case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED;
case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED;
case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED;
case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED;
default: UNREACHABLE(); return GL_NONE;
}
}
// Attribute format conversion
enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
struct TranslationDescription
{
DWORD capsFlag;
VertexFormat preferredConversion;
VertexFormat fallbackConversion;
};
// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
//
// BYTE SHORT (Cast)
// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
// SHORT SHORT (Identity)
// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
// UNSIGNED_SHORT FLOAT (Cast)
// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
// FIXED (not in WebGL) FLOAT (FixedToFloat)
// FLOAT FLOAT (Identity)
// GLToCType maps from GL type (as GLenum) to the C typedef.
template <GLenum GLType> struct GLToCType { };
template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
enum D3DVertexType
{
D3DVT_FLOAT,
D3DVT_SHORT,
D3DVT_SHORT_NORM,
D3DVT_UBYTE,
D3DVT_UBYTE_NORM,
D3DVT_USHORT_NORM
};
// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
template <unsigned int D3DType> struct D3DToCType { };
template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
template <unsigned int type, int size> struct WidenRule { };
template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { };
template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { };
// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
template <unsigned int _capflag, unsigned int _declflag>
struct VertexTypeFlagsHelper
{
enum { capflag = _capflag };
enum { declflag = _declflag };
};
template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
struct VertexTypeMappingBase
{
enum { preferred = Preferred };
enum { fallback = Fallback };
};
template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
// The conversion rules themselves are defined in vertexconversion.h.
// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
template <GLenum fromType, bool normalized, unsigned int toType>
struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
// All conversions from normalized types to float use the Normalize operator.
template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
// whether it is normalized or not.
template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { };
template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
// Work out the default value rule for a D3D type (expressed as the C type) and
template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
// The fallback conversion produces an output that all D3D9 devices must support.
template <class T> struct UsePreferred { enum { type = T::preferred }; };
template <class T> struct UseFallback { enum { type = T::fallback }; };
// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
struct Converter
: VertexDataConverter<typename GLToCType<fromType>::type,
WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
ConversionRule<fromType,
normalized,
PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
{
private:
enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
public:
enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
};
VertexFormat::VertexFormat()
: conversionType(VERTEX_CONVERT_NONE),
outputElementSize(0),
copyFunction(NULL),
nativeFormat(D3DDECLTYPE_UNUSED),
componentType(GL_NONE)
{
}
// Initialize a TranslationInfo
VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat)
{
VertexFormat formatInfo;
formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU;
formatInfo.outputElementSize = elementSize;
formatInfo.copyFunction = copyFunc;
formatInfo.nativeFormat = nativeFormat;
formatInfo.componentType = GetDeclTypeComponentType(nativeFormat);
return formatInfo;
}
#define TRANSLATION(type, norm, size, preferred) \
CreateVertexFormatInfo \
( \
Converter<type, norm, size, preferred>::identity, \
Converter<type, norm, size, preferred>::finalSize, \
Converter<type, norm, size, preferred>::convertArray, \
static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
)
#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
{ \
Converter<type, norm, size, UsePreferred>::capflag, \
TRANSLATION(type, norm, size, UsePreferred), \
TRANSLATION(type, norm, size, UseFallback) \
}
#define TRANSLATIONS_FOR_TYPE(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
}
#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
}
static inline unsigned int ComputeTypeIndex(GLenum type)
{
switch (type)
{
case GL_BYTE: return 0;
case GL_UNSIGNED_BYTE: return 1;
case GL_SHORT: return 2;
case GL_UNSIGNED_SHORT: return 3;
case GL_FIXED: return 4;
case GL_FLOAT: return 5;
default: UNREACHABLE(); return 5;
}
}
const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat)
{
static bool initialized = false;
static DWORD intializedDeclTypes = 0;
static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
if (!initialized)
{
const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
{
TRANSLATIONS_FOR_TYPE(GL_BYTE),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
TRANSLATIONS_FOR_TYPE(GL_SHORT),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
};
for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
{
for (unsigned int j = 0; j < 2; j++)
{
for (unsigned int k = 0; k < 4; k++)
{
if (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0)
{
formatConverters[i][j][k] = translations[i][j][k].preferredConversion;
}
else
{
formatConverters[i][j][k] = translations[i][j][k].fallbackConversion;
}
}
}
}
initialized = true;
intializedDeclTypes = supportedDeclTypes;
}
ASSERT(intializedDeclTypes == supportedDeclTypes);
// Pure integer attributes only supported in ES3.0
ASSERT(!vertexFormat.mPureInteger);
return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1];
}
}
}

View File

@ -588,6 +588,20 @@ APZCTreeManager::GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
return apzc.forget();
}
{ // In this block we flush repaint requests for the entire APZ tree. We need to do this
// at the start of an input block for a number of reasons. One of the reasons is so that
// after we untransform the event into gecko space, it doesn't end up under something
// else. Another reason is that if we hit-test this event and end up on a layer's
// dispatch-to-content region we cannot be sure we actually got the correct layer. We
// have to fall back to the gecko hit-test to handle this case, but we can't untransform
// the event we send to gecko because we don't know the layer to untransform with
// respect to.
MonitorAutoLock lock(mTreeLock);
for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) {
FlushRepaintsRecursively(apzc);
}
}
apzc = GetTargetAPZC(aEvent.mTouches[0].mScreenPoint, aOutInOverscrolledApzc);
for (size_t i = 1; i < aEvent.mTouches.Length(); i++) {
nsRefPtr<AsyncPanZoomController> apzc2 = GetTargetAPZC(aEvent.mTouches[i].mScreenPoint, aOutInOverscrolledApzc);
@ -836,6 +850,17 @@ APZCTreeManager::UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
}
}
void
APZCTreeManager::FlushRepaintsRecursively(AsyncPanZoomController* aApzc)
{
mTreeLock.AssertCurrentThreadOwns();
aApzc->FlushRepaintForNewInputBlock();
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
FlushRepaintsRecursively(child);
}
}
void
APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
{

View File

@ -380,6 +380,7 @@ private:
ScrollableLayerGuid* aOutTargetGuid);
void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
const ZoomConstraints& aConstraints);
void FlushRepaintsRecursively(AsyncPanZoomController* aApzc);
AsyncPanZoomController* PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer,
const FrameMetrics& aMetrics,

View File

@ -75,7 +75,7 @@
{ std::stringstream ss; \
ss << nsPrintfCString(prefix, __VA_ARGS__).get(); \
AppendToString(ss, fm, ":", "", true); \
APZC_LOG("%s", ss.str().c_str()); \
APZC_LOG("%s\n", ss.str().c_str()); \
}
#else
# define APZC_LOG(...)
@ -2299,6 +2299,22 @@ void AsyncPanZoomController::FlushRepaintForOverscrollHandoff() {
UpdateSharedCompositorFrameMetrics();
}
void AsyncPanZoomController::FlushRepaintForNewInputBlock() {
APZC_LOG("%p flushing repaint for new input block\n", this);
ReentrantMonitorAutoEnter lock(mMonitor);
// We need to send a new repaint request unthrottled, but that
// will obsolete any pending repaint request in the paint throttler.
// Therefore we should clear out the pending task and restore the
// state of mLastPaintRequestMetrics to what it was before the
// pending task was queued.
mPaintThrottler.CancelPendingTask();
mLastPaintRequestMetrics = mLastDispatchedPaintMetrics;
RequestContentRepaint(mFrameMetrics, false /* not throttled */);
UpdateSharedCompositorFrameMetrics();
}
bool AsyncPanZoomController::SnapBackIfOverscrolled() {
ReentrantMonitorAutoEnter lock(mMonitor);
if (IsOverscrolled()) {
@ -2323,7 +2339,7 @@ void AsyncPanZoomController::RequestContentRepaint() {
RequestContentRepaint(mFrameMetrics);
}
void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics) {
void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, bool aThrottled) {
aFrameMetrics.SetDisplayPortMargins(
CalculatePendingDisplayPort(aFrameMetrics,
GetVelocityVector(),
@ -2349,12 +2365,16 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics)
}
SendAsyncScrollEvent();
mPaintThrottler.PostTask(
FROM_HERE,
UniquePtr<CancelableTask>(NewRunnableMethod(this,
&AsyncPanZoomController::DispatchRepaintRequest,
aFrameMetrics)),
GetFrameTime());
if (aThrottled) {
mPaintThrottler.PostTask(
FROM_HERE,
UniquePtr<CancelableTask>(NewRunnableMethod(this,
&AsyncPanZoomController::DispatchRepaintRequest,
aFrameMetrics)),
GetFrameTime());
} else {
DispatchRepaintRequest(aFrameMetrics);
}
aFrameMetrics.SetPresShellId(mLastContentPaintMetrics.GetPresShellId());
mLastPaintRequestMetrics = aFrameMetrics;

View File

@ -545,9 +545,12 @@ protected:
/**
* Tell the paint throttler to request a content repaint with the given
* metrics. (Helper function used by RequestContentRepaint.)
* metrics. (Helper function used by RequestContentRepaint.) If aThrottled
* is set to false, the repaint request is sent directly without going through
* the paint throttler. In particular, the GeckoContentController::RequestContentRepaint
* function will be invoked before this function returns.
*/
void RequestContentRepaint(FrameMetrics& aFrameMetrics);
void RequestContentRepaint(FrameMetrics& aFrameMetrics, bool aThrottled = true);
/**
* Actually send the next pending paint request to gecko.
@ -796,6 +799,12 @@ public:
*/
void SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors);
/**
* Flush a repaint request if one is needed, without throttling it with the
* paint throttler.
*/
void FlushRepaintForNewInputBlock();
private:
void ScheduleContentResponseTimeout();
void ContentResponseTimeout();

View File

@ -59,6 +59,15 @@ TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp)
}
}
void
TaskThrottler::CancelPendingTask()
{
if (mQueuedTask) {
mQueuedTask->Cancel();
mQueuedTask = nullptr;
}
}
TimeDuration
TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp)
{

View File

@ -75,6 +75,11 @@ public:
*/
bool IsOutstanding() { return mOutstanding; }
/**
* Cancel the queued task if there is one.
*/
void CancelPendingTask();
/**
* Return the time elapsed since the last request was processed
*/

View File

@ -1272,7 +1272,9 @@ CompositorOGL::DrawQuad(const Rect& aRect,
// won't pick up the TexturePass2 uniform change below if we don't do
// something to force it. Re-activating the shader seems to be one way
// of achieving that.
program->Activate();
GLint program;
mGLContext->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &program);
mGLContext->fUseProgram(program);
}
#endif

View File

@ -1488,7 +1488,7 @@ protected:
testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
mcc = new NiceMock<MockContentController>();
mcc = new NiceMock<MockContentControllerDelayed>();
manager = new TestAPZCTreeManager();
}
@ -1497,7 +1497,7 @@ protected:
}
TimeStamp testStartTime;
nsRefPtr<MockContentController> mcc;
nsRefPtr<MockContentControllerDelayed> mcc;
nsTArray<nsRefPtr<Layer> > layers;
nsRefPtr<LayerManager> lm;
@ -1525,6 +1525,15 @@ protected:
return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(0);
}
void CreateSimpleScrollingLayer() {
const char* layerTreeSyntax = "t";
nsIntRegion layerVisibleRegion[] = {
nsIntRegion(nsIntRect(0,0,200,200)),
};
root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers);
SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 500, 500));
}
void CreateSimpleMultiLayerTree() {
const char* layerTreeSyntax = "c(tt)";
// LayerID 0 12
@ -1751,9 +1760,6 @@ TEST_F(APZHitTestingTester, HitTesting2) {
// This causes layers[1] to scroll out of view, and an async transform
// of -50 to be set on the root layer.
int time = 0;
// Silence GMock warnings about "uninteresting mock function calls".
EXPECT_CALL(*mcc, PostDelayedTask(_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
// This first pan will move the APZC by 50 pixels, and dispatch a paint request.
@ -1902,6 +1908,76 @@ TEST_F(APZHitTestingTester, ComplexMultiLayerTree) {
EXPECT_EQ(ApzcOf(layers[7]), hit.get());
}
TEST_F(APZHitTestingTester, TestRepaintFlushOnNewInputBlock) {
// The main purpose of this test is to verify that touch-start events (or anything
// that starts a new input block) don't ever get untransformed. This should always
// hold because the APZ code should flush repaints when we start a new input block
// and the transform to gecko space should be empty.
CreateSimpleScrollingLayer();
ScopedLayerTreeRegistration registration(0, root, mcc);
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0);
AsyncPanZoomController* apzcroot = ApzcOf(root);
// At this point, the following holds (all coordinates in screen pixels):
// layers[0] has content from (0,0)-(500,500), clipped by composition bounds (0,0)-(200,200)
MockFunction<void(std::string checkPointName)> check;
{
InSequence s;
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(AtLeast(1));
EXPECT_CALL(check, Call("post-first-touch-start"));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(AtLeast(1));
EXPECT_CALL(check, Call("post-second-fling"));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(AtLeast(1));
EXPECT_CALL(check, Call("post-second-touch-start"));
}
int time = 0;
// This first pan will move the APZC by 50 pixels, and dispatch a paint request.
ApzcPanNoFling(apzcroot, time, 100, 50);
// Verify that a touch start doesn't get untransformed
ScreenIntPoint touchPoint(50, 50);
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0);
mti.mTouches.AppendElement(SingleTouchData(0, touchPoint, ScreenSize(0, 0), 0, 0));
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr));
EXPECT_EQ(touchPoint, mti.mTouches[0].mScreenPoint);
check.Call("post-first-touch-start");
// Send a touchend to clear state
mti.mType = MultiTouchInput::MULTITOUCH_END;
manager->ReceiveInputEvent(mti, nullptr);
AsyncPanZoomController::SetFrameTime(testStartTime + TimeDuration::FromMilliseconds(1000));
// Now do two pans. The first of these will dispatch a repaint request, as above.
// The second will get stuck in the paint throttler because the first one doesn't
// get marked as "completed", so this will result in a non-empty LD transform.
// (Note that any outstanding repaint requests from the first half of this test
// don't impact this half because we advance the time by 1 second, which will trigger
// the max-wait-exceeded codepath in the paint throttler).
ApzcPanNoFling(apzcroot, time, 100, 50);
check.Call("post-second-fling");
ApzcPanNoFling(apzcroot, time, 100, 50);
// Ensure that a touch start again doesn't get untransformed by flushing
// a repaint
mti.mType = MultiTouchInput::MULTITOUCH_START;
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr));
EXPECT_EQ(touchPoint, mti.mTouches[0].mScreenPoint);
check.Call("post-second-touch-start");
mti.mType = MultiTouchInput::MULTITOUCH_END;
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr));
EXPECT_EQ(touchPoint, mti.mTouches[0].mScreenPoint);
mcc->RunThroughDelayedTasks();
}
class APZOverscrollHandoffTester : public APZCTreeManagerTester {
protected:
UniquePtr<ScopedLayerTreeRegistration> registration;

View File

@ -9,6 +9,7 @@
#include "base/message_loop.h"
#include "base/histogram.h"
#include "base/win_util.h"
#include "WinUtils.h"
using base::Time;
@ -263,31 +264,7 @@ void MessagePumpForUI::WaitForWork() {
if (delay < 0) // Negative value means no timers waiting.
delay = INFINITE;
DWORD result;
result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT,
MWMO_INPUTAVAILABLE);
if (WAIT_OBJECT_0 == result) {
// A WM_* message is available.
// If a parent child relationship exists between windows across threads
// then their thread inputs are implicitly attached.
// This causes the MsgWaitForMultipleObjectsEx API to return indicating
// that messages are ready for processing (specifically mouse messages
// intended for the child window. Occurs if the child window has capture)
// The subsequent PeekMessages call fails to return any messages thus
// causing us to enter a tight loop at times.
// The WaitMessage call below is a workaround to give the child window
// sometime to process its input messages.
MSG msg = {0};
DWORD queue_status = GetQueueStatus(QS_MOUSE);
if (HIWORD(queue_status) & QS_MOUSE &&
!PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) {
WaitMessage();
}
return;
}
DCHECK_NE(WAIT_FAILED, result) << GetLastError();
mozilla::widget::WinUtils::WaitForMessage(delay);
}
void MessagePumpForUI::HandleWorkMessage() {

View File

@ -35,165 +35,181 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
/*** IPC handlers ***/
bool AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
return Answer::AnswerPreventExtensions(objId, rs);
bool AnswerPreventExtensions(const uint64_t &objId, ReturnStatus *rs) {
return Answer::AnswerPreventExtensions(ObjectId::deserialize(objId), rs);
}
bool AnswerGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
bool AnswerGetPropertyDescriptor(const uint64_t &objId, const nsString &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Answer::AnswerGetPropertyDescriptor(objId, id, rs, out);
return Answer::AnswerGetPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
}
bool AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
bool AnswerGetOwnPropertyDescriptor(const uint64_t &objId,
const nsString &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Answer::AnswerGetOwnPropertyDescriptor(objId, id, rs, out);
return Answer::AnswerGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
}
bool AnswerDefineProperty(const ObjectId &objId, const nsString &id,
bool AnswerDefineProperty(const uint64_t &objId, const nsString &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) {
return Answer::AnswerDefineProperty(objId, id, flags, rs);
return Answer::AnswerDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
}
bool AnswerDelete(const ObjectId &objId, const nsString &id,
bool AnswerDelete(const uint64_t &objId, const nsString &id,
ReturnStatus *rs, bool *success) {
return Answer::AnswerDelete(objId, id, rs, success);
return Answer::AnswerDelete(ObjectId::deserialize(objId), id, rs, success);
}
bool AnswerHas(const ObjectId &objId, const nsString &id,
bool AnswerHas(const uint64_t &objId, const nsString &id,
ReturnStatus *rs, bool *bp) {
return Answer::AnswerHas(objId, id, rs, bp);
return Answer::AnswerHas(ObjectId::deserialize(objId), id, rs, bp);
}
bool AnswerHasOwn(const ObjectId &objId, const nsString &id,
bool AnswerHasOwn(const uint64_t &objId, const nsString &id,
ReturnStatus *rs, bool *bp) {
return Answer::AnswerHasOwn(objId, id, rs, bp);
return Answer::AnswerHasOwn(ObjectId::deserialize(objId), id, rs, bp);
}
bool AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
bool AnswerGet(const uint64_t &objId, const ObjectVariant &receiverVar,
const nsString &id,
ReturnStatus *rs, JSVariant *result) {
return Answer::AnswerGet(objId, receiverVar, id, rs, result);
return Answer::AnswerGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
}
bool AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
bool AnswerSet(const uint64_t &objId, const ObjectVariant &receiverVar,
const nsString &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
return Answer::AnswerSet(objId, receiverVar, id, strict, value, rs, result);
return Answer::AnswerSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
}
bool AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool AnswerIsExtensible(const uint64_t &objId, ReturnStatus *rs,
bool *result) {
return Answer::AnswerIsExtensible(objId, rs, result);
return Answer::AnswerIsExtensible(ObjectId::deserialize(objId), rs, result);
}
bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
bool AnswerCallOrConstruct(const uint64_t &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams) {
return Answer::AnswerCallOrConstruct(objId, argv, construct, rs, result, outparams);
return Answer::AnswerCallOrConstruct(ObjectId::deserialize(objId), argv, construct, rs, result, outparams);
}
bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Answer::AnswerHasInstance(objId, v, rs, bp);
bool AnswerHasInstance(const uint64_t &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Answer::AnswerHasInstance(ObjectId::deserialize(objId), v, rs, bp);
}
bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool AnswerObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
bool *result) {
return Answer::AnswerObjectClassIs(objId, classValue, result);
return Answer::AnswerObjectClassIs(ObjectId::deserialize(objId), classValue, result);
}
bool AnswerClassName(const ObjectId &objId, nsString *result) {
return Answer::AnswerClassName(objId, result);
bool AnswerClassName(const uint64_t &objId, nsString *result) {
return Answer::AnswerClassName(ObjectId::deserialize(objId), result);
}
bool AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
bool AnswerGetPropertyNames(const uint64_t &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names) {
return Answer::AnswerGetPropertyNames(objId, flags, rs, names);
return Answer::AnswerGetPropertyNames(ObjectId::deserialize(objId), flags, rs, names);
}
bool AnswerInstanceOf(const ObjectId &objId, const JSIID &iid,
bool AnswerInstanceOf(const uint64_t &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof) {
return Answer::AnswerInstanceOf(objId, iid, rs, instanceof);
return Answer::AnswerInstanceOf(ObjectId::deserialize(objId), iid, rs, instanceof);
}
bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
bool AnswerDOMInstanceOf(const uint64_t &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof) {
return Answer::AnswerDOMInstanceOf(objId, prototypeID, depth, rs, instanceof);
return Answer::AnswerDOMInstanceOf(ObjectId::deserialize(objId), prototypeID, depth, rs, instanceof);
}
bool RecvDropObject(const ObjectId &objId) {
return Answer::RecvDropObject(objId);
bool AnswerIsCallable(const uint64_t &objId, bool *result) {
return Answer::AnswerIsCallable(ObjectId::deserialize(objId), result);
}
bool AnswerIsConstructor(const uint64_t &objId, bool *result) {
return Answer::AnswerIsConstructor(ObjectId::deserialize(objId), result);
}
bool RecvDropObject(const uint64_t &objId) {
return Answer::RecvDropObject(ObjectId::deserialize(objId));
}
/*** Dummy call handlers ***/
bool SendDropObject(const ObjectId &objId) {
return Base::SendDropObject(objId);
return Base::SendDropObject(objId.serialize());
}
bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
return Base::CallPreventExtensions(objId, rs);
return Base::CallPreventExtensions(objId.serialize(), rs);
}
bool CallGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Base::CallGetPropertyDescriptor(objId, id, rs, out);
return Base::CallGetPropertyDescriptor(objId.serialize(), id, rs, out);
}
bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
const nsString &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Base::CallGetOwnPropertyDescriptor(objId, id, rs, out);
return Base::CallGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
}
bool CallDefineProperty(const ObjectId &objId, const nsString &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) {
return Base::CallDefineProperty(objId, id, flags, rs);
return Base::CallDefineProperty(objId.serialize(), id, flags, rs);
}
bool CallDelete(const ObjectId &objId, const nsString &id,
ReturnStatus *rs, bool *success) {
return Base::CallDelete(objId, id, rs, success);
return Base::CallDelete(objId.serialize(), id, rs, success);
}
bool CallHas(const ObjectId &objId, const nsString &id,
ReturnStatus *rs, bool *bp) {
return Base::CallHas(objId, id, rs, bp);
return Base::CallHas(objId.serialize(), id, rs, bp);
}
bool CallHasOwn(const ObjectId &objId, const nsString &id,
ReturnStatus *rs, bool *bp) {
return Base::CallHasOwn(objId, id, rs, bp);
return Base::CallHasOwn(objId.serialize(), id, rs, bp);
}
bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const nsString &id,
ReturnStatus *rs, JSVariant *result) {
return Base::CallGet(objId, receiverVar, id, rs, result);
return Base::CallGet(objId.serialize(), receiverVar, id, rs, result);
}
bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const nsString &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
return Base::CallSet(objId, receiverVar, id, strict, value, rs, result);
return Base::CallSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
}
bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result) {
return Base::CallIsExtensible(objId, rs, result);
return Base::CallIsExtensible(objId.serialize(), rs, result);
}
bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams) {
return Base::CallCallOrConstruct(objId, argv, construct, rs, result, outparams);
return Base::CallCallOrConstruct(objId.serialize(), argv, construct, rs, result, outparams);
}
bool CallHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Base::CallHasInstance(objId, v, rs, bp);
return Base::CallHasInstance(objId.serialize(), v, rs, bp);
}
bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) {
return Base::CallObjectClassIs(objId, classValue, result);
return Base::CallObjectClassIs(objId.serialize(), classValue, result);
}
bool CallClassName(const ObjectId &objId, nsString *result) {
return Base::CallClassName(objId, result);
return Base::CallClassName(objId.serialize(), result);
}
bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names) {
return Base::CallGetPropertyNames(objId, flags, rs, names);
return Base::CallGetPropertyNames(objId.serialize(), flags, rs, names);
}
bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof) {
return Base::CallInstanceOf(objId, iid, rs, instanceof);
return Base::CallInstanceOf(objId.serialize(), iid, rs, instanceof);
}
bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof) {
return Base::CallDOMInstanceOf(objId, prototypeID, depth, rs, instanceof);
return Base::CallDOMInstanceOf(objId.serialize(), prototypeID, depth, rs, instanceof);
}
bool CallIsCallable(const ObjectId &objId, bool *result) {
return Base::CallIsCallable(objId.serialize(), result);
}
bool CallIsConstructor(const ObjectId &objId, bool *result) {
return Base::CallIsConstructor(objId.serialize(), result);
}
/* The following code is needed to suppress a bogus MSVC warning (C4250). */

View File

@ -53,7 +53,8 @@ void
JavaScriptChild::updateWeakPointers()
{
objects_.sweep();
objectIds_.sweep();
unwaivedObjectIds_.sweep();
waivedObjectIds_.sweep();
}
JSObject *

View File

@ -96,7 +96,7 @@ class Logging
if (local == incoming) {
JS::RootedObject obj(cx);
obj = shared->findObjectById(id);
obj = shared->objects_.find(id);
if (obj) {
JSAutoCompartment ac(cx, obj);
objDesc = js_ObjectClassName(cx, obj);
@ -160,9 +160,9 @@ class Logging
case JSVariant::TObjectVariant: {
const ObjectVariant &ovar = value.get_ObjectVariant();
if (ovar.type() == ObjectVariant::TLocalObject)
formatObject(incoming, true, ovar.get_LocalObject().id(), out);
formatObject(incoming, true, ObjectId::deserialize(ovar.get_LocalObject().serializedId()), out);
else
formatObject(incoming, false, ovar.get_RemoteObject().id(), out);
formatObject(incoming, false, ObjectId::deserialize(ovar.get_RemoteObject().serializedId()), out);
break;
}
case JSVariant::Tdouble: {

View File

@ -53,7 +53,8 @@ JavaScriptParent::trace(JSTracer *trc)
{
if (active()) {
objects_.trace(trc);
objectIds_.trace(trc);
unwaivedObjectIds_.trace(trc);
waivedObjectIds_.trace(trc);
}
}

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/TabChild.h"
#include "jsfriendapi.h"
#include "xpcprivate.h"
#include "WrapperFactory.h"
#include "mozilla/Preferences.h"
using namespace js;
@ -123,7 +124,7 @@ ObjectToIdMap::find(JSObject *obj)
{
Table::Ptr p = table_->lookup(obj);
if (!p)
return 0;
return ObjectId::nullId();
return p->value();
}
@ -162,7 +163,7 @@ bool JavaScriptShared::sStackLoggingEnabled;
JavaScriptShared::JavaScriptShared(JSRuntime *rt)
: rt_(rt),
refcount_(1),
lastId_(0)
nextSerialNumber_(1)
{
if (!sLoggingInitialized) {
sLoggingInitialized = true;
@ -186,7 +187,9 @@ JavaScriptShared::init()
return false;
if (!cpows_.init())
return false;
if (!objectIds_.init())
if (!unwaivedObjectIds_.init())
return false;
if (!waivedObjectIds_.init())
return false;
return true;
@ -381,9 +384,9 @@ JavaScriptShared::ConvertID(const JSIID &from, nsID *to)
}
JSObject *
JavaScriptShared::findObjectById(JSContext *cx, uint32_t objId)
JavaScriptShared::findObjectById(JSContext *cx, const ObjectId &objId)
{
RootedObject obj(cx, findObjectById(objId));
RootedObject obj(cx, objects_.find(objId));
if (!obj) {
JS_ReportError(cx, "operation not possible on dead CPOW");
return nullptr;
@ -394,8 +397,13 @@ JavaScriptShared::findObjectById(JSContext *cx, uint32_t objId)
// can access objects in other compartments using cross-compartment
// wrappers.
JSAutoCompartment ac(cx, scopeForTargetObjects());
if (!JS_WrapObject(cx, &obj))
return nullptr;
if (objId.hasXrayWaiver()) {
if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, &obj))
return nullptr;
} else {
if (!JS_WrapObject(cx, &obj))
return nullptr;
}
return obj;
}

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