mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c. a=merge
This commit is contained in:
commit
4cf7455ce4
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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; };
|
||||
|
@ -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>
|
10
content/base/test/csp/file_csp_path_matching_redirect.html
Normal file
10
content/base/test/csp/file_csp_path_matching_redirect.html
Normal 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>
|
@ -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);
|
||||
}
|
@ -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)
|
||||
|
@ -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]);
|
||||
|
89
content/base/test/csp/test_csp_path_matching_redirect.html
Normal file
89
content/base/test/csp/test_csp_path_matching_redirect.html
Normal 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>
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -14,7 +14,7 @@ EXPORTS.mozilla.dom += [
|
||||
'AnimationTimeline.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'Animation.cpp',
|
||||
'AnimationEffect.cpp',
|
||||
'AnimationPlayer.cpp',
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -54,6 +54,8 @@ public:
|
||||
|
||||
virtual void Accept(int aFd, BluetoothSocketResultHandler* aRes) = 0;
|
||||
|
||||
virtual void Close(BluetoothSocketResultHandler* aRes) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~BluetoothSocketInterface();
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -36,6 +36,8 @@ public:
|
||||
|
||||
void Accept(int aFd, BluetoothSocketResultHandler* aRes);
|
||||
|
||||
void Close(BluetoothSocketResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothSocketHALInterface(const btsock_interface_t* aInterface);
|
||||
~BluetoothSocketHALInterface();
|
||||
|
@ -54,6 +54,8 @@ public:
|
||||
|
||||
virtual void Accept(int aFd, BluetoothSocketResultHandler* aRes) = 0;
|
||||
|
||||
virtual void Close(BluetoothSocketResultHandler* aRes) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~BluetoothSocketInterface();
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -36,6 +36,8 @@ public:
|
||||
|
||||
void Accept(int aFd, BluetoothSocketResultHandler* aRes);
|
||||
|
||||
void Close(BluetoothSocketResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothSocketHALInterface(const btsock_interface_t* aInterface);
|
||||
~BluetoothSocketHALInterface();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -17,7 +17,7 @@ EXPORTS.mozilla.dom += [
|
||||
'DataStoreService.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'DataStore.cpp',
|
||||
'DataStoreCursor.cpp',
|
||||
'DataStoreDB.cpp',
|
||||
|
@ -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);
|
||||
|
@ -13,7 +13,7 @@ EXPORTS.mozilla.dom += [
|
||||
'FileSystemUtils.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'CreateDirectoryTask.cpp',
|
||||
'CreateFileTask.cpp',
|
||||
'DeviceStorageFileSystem.cpp',
|
||||
|
@ -11,7 +11,7 @@ EXPORTS.mozilla.dom += [
|
||||
'FMRadioRequestParent.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'FMRadioChild.cpp',
|
||||
'FMRadioParent.cpp',
|
||||
'FMRadioRequestChild.cpp',
|
||||
|
@ -15,7 +15,7 @@ if CONFIG['MOZ_B2G_FM']:
|
||||
'FMRadioService.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'FMRadio.cpp',
|
||||
'FMRadioService.cpp',
|
||||
]
|
||||
|
@ -11,7 +11,7 @@ EXPORTS.mozilla.dom += [
|
||||
'IccManager.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'Icc.cpp',
|
||||
'IccListener.cpp',
|
||||
'IccManager.cpp',
|
||||
|
@ -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))
|
||||
|
@ -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; \
|
||||
|
@ -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(); \
|
||||
|
@ -30,7 +30,7 @@ XPIDL_SOURCES += [
|
||||
'interfaces/nsINeighboringCellInfo.idl',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'DOMMMIError.cpp',
|
||||
'ipc/MobileConnectionChild.cpp',
|
||||
'ipc/MobileConnectionIPCService.cpp',
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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',
|
||||
]
|
||||
|
||||
|
@ -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',
|
||||
]
|
||||
|
@ -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())
|
||||
|
@ -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 =
|
||||
|
@ -12,7 +12,7 @@ EXPORTS += [
|
||||
'SpeakerManagerServiceChild.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'SpeakerManager.cpp',
|
||||
'SpeakerManagerService.cpp',
|
||||
'SpeakerManagerServiceChild.cpp',
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -35,7 +35,7 @@ EXPORTS += [
|
||||
'nsVolume.h',
|
||||
'nsVolumeService.h',
|
||||
]
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AudioChannelManager.cpp',
|
||||
'AudioManager.cpp',
|
||||
'AutoMounter.cpp',
|
||||
|
@ -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;
|
||||
|
@ -30,7 +30,7 @@ EXTRA_JS_MODULES += [
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
SOURCES = [
|
||||
UNIFIED_SOURCES = [
|
||||
'WifiCertService.cpp',
|
||||
'WifiHotspotUtils.cpp',
|
||||
'WifiProxyService.cpp',
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -36,7 +36,7 @@ EXPORTS.mozilla.dom.workers.bindings += [
|
||||
'XMLHttpRequestUpload.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'ChromeWorkerScope.cpp',
|
||||
'DataStore.cpp',
|
||||
'DataStoreCursor.cpp',
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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(";
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -59,6 +59,15 @@ TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TaskThrottler::CancelPendingTask()
|
||||
{
|
||||
if (mQueuedTask) {
|
||||
mQueuedTask->Cancel();
|
||||
mQueuedTask = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
TimeDuration
|
||||
TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp)
|
||||
{
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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). */
|
||||
|
@ -53,7 +53,8 @@ void
|
||||
JavaScriptChild::updateWeakPointers()
|
||||
{
|
||||
objects_.sweep();
|
||||
objectIds_.sweep();
|
||||
unwaivedObjectIds_.sweep();
|
||||
waivedObjectIds_.sweep();
|
||||
}
|
||||
|
||||
JSObject *
|
||||
|
@ -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: {
|
||||
|
@ -53,7 +53,8 @@ JavaScriptParent::trace(JSTracer *trc)
|
||||
{
|
||||
if (active()) {
|
||||
objects_.trace(trc);
|
||||
objectIds_.trace(trc);
|
||||
unwaivedObjectIds_.trace(trc);
|
||||
waivedObjectIds_.trace(trc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user