mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge m-i to m-c a=merge
This commit is contained in:
commit
6d0df443bf
@ -239,7 +239,7 @@ function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIf)
|
||||
|
||||
if (!acc) {
|
||||
if (!(aDoNotFailIf & DONOTFAIL_IF_NO_ACC))
|
||||
ok(false, "Can't get accessible for " + aAccOrElmOrID);
|
||||
ok(false, "Can't get accessible for " + prettyName(aAccOrElmOrID));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -59,7 +59,11 @@
|
||||
this.match = function browserReorderChecker_match(aEvent)
|
||||
{
|
||||
// Reorder event might be duped because of temporary document creation.
|
||||
if (aEvent.accessible == getAccessible(currentBrowser())) {
|
||||
var browserAcc = getAccessible(currentBrowser());
|
||||
if (!browserAcc)
|
||||
ok(false, "opa opa sralslasya");
|
||||
|
||||
if (aEvent.accessible == browserAcc) {
|
||||
this.cnt++;
|
||||
return this.cnt != 2;
|
||||
}
|
||||
@ -83,8 +87,11 @@
|
||||
|
||||
this.finalCheck = function loadURI_finalCheck()
|
||||
{
|
||||
testRelation(browserDocument(), RELATION_EMBEDS,
|
||||
getAccessible(currentTabDocument()));
|
||||
var acc = getAccessible(currentTabDocument());
|
||||
if (!acc)
|
||||
ok(false, "ahahahaha");
|
||||
|
||||
testRelation(browserDocument(), RELATION_EMBEDS, acc);
|
||||
}
|
||||
|
||||
this.getID = function loadOneTab_getID()
|
||||
|
@ -186,7 +186,7 @@ skip-if = e10s # Bug ?????? - test doesn't wait for document to be created befor
|
||||
[browser_bug550565.js]
|
||||
skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome (which is how gBrowser.getIcon works)
|
||||
[browser_bug553455.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug ????? - I don't think either popup notifications nor addon install stuff works?
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
|
||||
[browser_bug555224.js]
|
||||
skip-if = e10s # Bug 691614 - no e10s zoom support yet
|
||||
[browser_bug555767.js]
|
||||
|
@ -35,4 +35,6 @@ skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug
|
||||
skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
|
||||
[test_feed_discovery.html]
|
||||
[test_offlineNotification.html]
|
||||
skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
|
||||
[test_offline_gzip.html]
|
||||
skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
|
||||
|
@ -28,10 +28,11 @@ AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
|
||||
esac
|
||||
fi
|
||||
|
||||
# if we are debugging, profiling or using ASAN, we want a frame pointer.
|
||||
# if we are debugging, profiling or using sanitizers, we want a frame pointer.
|
||||
if test -z "$MOZ_OPTIMIZE" -o \
|
||||
-n "$MOZ_PROFILING" -o \
|
||||
-n "$MOZ_DEBUG" -o \
|
||||
-n "$MOZ_MSAN" -o \
|
||||
-n "$MOZ_ASAN"; then
|
||||
MOZ_FRAMEPTR_FLAGS="$MOZ_ENABLE_FRAME_PTR"
|
||||
else
|
||||
|
@ -23,8 +23,6 @@ __all__ = [
|
||||
"dumpLeakLog",
|
||||
"isURL",
|
||||
"processLeakLog",
|
||||
"getDebuggerInfo",
|
||||
"DEBUGGER_INFO",
|
||||
"replaceBackSlashes",
|
||||
'KeyValueParseError',
|
||||
'parseKeyValue',
|
||||
@ -48,54 +46,6 @@ def setAutomationLog(alt_logger):
|
||||
global log
|
||||
log = alt_logger
|
||||
|
||||
# Map of debugging programs to information about them, like default arguments
|
||||
# and whether or not they are interactive.
|
||||
DEBUGGER_INFO = {
|
||||
# gdb requires that you supply the '--args' flag in order to pass arguments
|
||||
# after the executable name to the executable.
|
||||
"gdb": {
|
||||
"interactive": True,
|
||||
"args": "-q --args"
|
||||
},
|
||||
|
||||
"cgdb": {
|
||||
"interactive": True,
|
||||
"args": "-q --args"
|
||||
},
|
||||
|
||||
"lldb": {
|
||||
"interactive": True,
|
||||
"args": "--",
|
||||
"requiresEscapedArgs": True
|
||||
},
|
||||
|
||||
# Visual Studio Debugger Support
|
||||
"devenv.exe": {
|
||||
"interactive": True,
|
||||
"args": "-debugexe"
|
||||
},
|
||||
|
||||
# Visual C++ Express Debugger Support
|
||||
"wdexpress.exe": {
|
||||
"interactive": True,
|
||||
"args": "-debugexe"
|
||||
},
|
||||
|
||||
# valgrind doesn't explain much about leaks unless you set the
|
||||
# '--leak-check=full' flag. But there are a lot of objects that are
|
||||
# semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid
|
||||
# uninteresting output from those objects. We set '--smc-check==all-non-file'
|
||||
# and '--vex-iropt-register-updates=allregs-at-mem-access' so that valgrind
|
||||
# deals properly with JIT'd JavaScript code.
|
||||
"valgrind": {
|
||||
"interactive": False,
|
||||
"args": " ".join(["--leak-check=full",
|
||||
"--show-possibly-lost=no",
|
||||
"--smc-check=all-non-file",
|
||||
"--vex-iropt-register-updates=allregs-at-mem-access"])
|
||||
}
|
||||
}
|
||||
|
||||
class ZipFileReader(object):
|
||||
"""
|
||||
Class to read zip files in Python 2.5 and later. Limited to only what we
|
||||
@ -224,58 +174,6 @@ def addCommonOptions(parser, defaults={}):
|
||||
help = "prevents the test harness from redirecting "
|
||||
"stdout and stderr for interactive debuggers")
|
||||
|
||||
def getFullPath(directory, path):
|
||||
"Get an absolute path relative to 'directory'."
|
||||
return os.path.normpath(os.path.join(directory, os.path.expanduser(path)))
|
||||
|
||||
def searchPath(directory, path):
|
||||
"Go one step beyond getFullPath and try the various folders in PATH"
|
||||
# Try looking in the current working directory first.
|
||||
newpath = getFullPath(directory, path)
|
||||
if os.path.isfile(newpath):
|
||||
return newpath
|
||||
|
||||
# At this point we have to fail if a directory was given (to prevent cases
|
||||
# like './gdb' from matching '/usr/bin/./gdb').
|
||||
if not os.path.dirname(path):
|
||||
for dir in os.environ['PATH'].split(os.pathsep):
|
||||
newpath = os.path.join(dir, path)
|
||||
if os.path.isfile(newpath):
|
||||
return newpath
|
||||
return None
|
||||
|
||||
def getDebuggerInfo(directory, debugger, debuggerArgs, debuggerInteractive = False):
|
||||
|
||||
debuggerInfo = None
|
||||
|
||||
if debugger:
|
||||
debuggerPath = searchPath(directory, debugger)
|
||||
if not debuggerPath:
|
||||
print "Error: Path %s doesn't exist." % debugger
|
||||
sys.exit(1)
|
||||
|
||||
debuggerName = os.path.basename(debuggerPath).lower()
|
||||
|
||||
def getDebuggerInfo(type, default):
|
||||
if debuggerName in DEBUGGER_INFO and type in DEBUGGER_INFO[debuggerName]:
|
||||
return DEBUGGER_INFO[debuggerName][type]
|
||||
return default
|
||||
|
||||
debuggerInfo = {
|
||||
"path": debuggerPath,
|
||||
"interactive" : getDebuggerInfo("interactive", False),
|
||||
"args": getDebuggerInfo("args", "").split(),
|
||||
"requiresEscapedArgs": getDebuggerInfo("requiresEscapedArgs", False)
|
||||
}
|
||||
|
||||
if debuggerArgs:
|
||||
debuggerInfo["args"] = debuggerArgs.split()
|
||||
if debuggerInteractive:
|
||||
debuggerInfo["interactive"] = debuggerInteractive
|
||||
|
||||
return debuggerInfo
|
||||
|
||||
|
||||
def dumpLeakLog(leakLogFile, filter = False):
|
||||
"""Process the leak log, without parsing it.
|
||||
|
||||
|
@ -49,6 +49,7 @@ SEARCH_PATHS = [
|
||||
'testing/marionette/client/marionette',
|
||||
'testing/marionette/transport',
|
||||
'testing/mozbase/mozcrash',
|
||||
'testing/mozbase/mozdebug',
|
||||
'testing/mozbase/mozdevice',
|
||||
'testing/mozbase/mozfile',
|
||||
'testing/mozbase/mozhttpd',
|
||||
|
16
configure.in
16
configure.in
@ -1264,6 +1264,22 @@ if test -n "$MOZ_ASAN"; then
|
||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||
fi
|
||||
AC_SUBST(MOZ_ASAN)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use Memory Sanitizer
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(memory-sanitizer,
|
||||
[ --enable-memory-sanitizer Enable Memory Sanitizer (default=no)],
|
||||
MOZ_MSAN=1,
|
||||
MOZ_MSAN= )
|
||||
if test -n "$MOZ_MSAN"; then
|
||||
MOZ_LLVM_HACKS=1
|
||||
AC_DEFINE(MOZ_MSAN)
|
||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||
fi
|
||||
AC_SUBST(MOZ_MSAN)
|
||||
|
||||
# The LLVM symbolizer is used by all sanitizers
|
||||
AC_SUBST(LLVM_SYMBOLIZER)
|
||||
|
||||
dnl ========================================================
|
||||
|
@ -71,7 +71,7 @@ skip-if = toolkit == 'android'
|
||||
[test_bug677495.html]
|
||||
[test_bug677495-1.html]
|
||||
[test_bug741266.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
|
||||
[test_non-ascii-cookie.html]
|
||||
skip-if = buildapp == 'b2g' || e10s
|
||||
[test_bug765780.html]
|
||||
|
@ -507,6 +507,20 @@ MediaSource::InitializationEvent()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
void
|
||||
MediaSource::Dump(const char* aPath)
|
||||
{
|
||||
char buf[255];
|
||||
PR_snprintf(buf, sizeof(buf), "%s/mediasource-%p", aPath, this);
|
||||
PR_MkDir(buf, 0700);
|
||||
|
||||
if (mSourceBuffers) {
|
||||
mSourceBuffers->Dump(buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsPIDOMWindow*
|
||||
MediaSource::GetParentObject() const
|
||||
{
|
||||
|
@ -98,6 +98,12 @@ public:
|
||||
// initialization.
|
||||
void QueueInitializationEvent();
|
||||
|
||||
#if defined(DEBUG)
|
||||
// Dump the contents of each SourceBuffer to a series of files under aPath.
|
||||
// aPath must exist. Debug only, invoke from your favourite debugger.
|
||||
void Dump(const char* aPath);
|
||||
#endif
|
||||
|
||||
private:
|
||||
~MediaSource();
|
||||
|
||||
|
@ -134,6 +134,23 @@ public:
|
||||
return size;
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Dump(const char* aPath) {
|
||||
for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
|
||||
ResourceItem* item = ResourceAt(i);
|
||||
|
||||
char buf[255];
|
||||
PR_snprintf(buf, sizeof(buf), "%s/%08u.bin", aPath, i);
|
||||
FILE* fp = fopen(buf, "wb");
|
||||
if (!fp) {
|
||||
return;
|
||||
}
|
||||
fwrite(item->mData.Elements(), item->mData.Length(), 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
ResourceItem* ResourceAt(uint32_t aIndex) const {
|
||||
return static_cast<ResourceItem*>(ObjectAt(aIndex));
|
||||
@ -173,6 +190,5 @@ private:
|
||||
uint64_t mOffset;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
#endif /* MOZILLA_RESOURCEQUEUE_H_ */
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -687,6 +688,16 @@ SourceBuffer::Evict(double aStart, double aEnd)
|
||||
mTrackBuffer->EvictBefore(evictTime);
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
void
|
||||
SourceBuffer::Dump(const char* aPath)
|
||||
{
|
||||
if (mTrackBuffer) {
|
||||
mTrackBuffer->Dump(aPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBuffer, DOMEventTargetHelper,
|
||||
mMediaSource)
|
||||
|
||||
|
@ -109,6 +109,10 @@ public:
|
||||
double GetBufferedStart();
|
||||
double GetBufferedEnd();
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Dump(const char* aPath);
|
||||
#endif
|
||||
|
||||
private:
|
||||
~SourceBuffer();
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
@ -167,6 +167,16 @@ SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
void
|
||||
SourceBufferList::Dump(const char* aPath)
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Dump(aPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SourceBufferList::SourceBufferList(MediaSource* aMediaSource)
|
||||
: DOMEventTargetHelper(aMediaSource->GetParentObject())
|
||||
, mMediaSource(aMediaSource)
|
||||
|
@ -79,6 +79,10 @@ public:
|
||||
// Returns the highest end time of any of the Sourcebuffers.
|
||||
double GetHighestBufferedEndTime();
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Dump(const char* aPath);
|
||||
#endif
|
||||
|
||||
private:
|
||||
~SourceBufferList();
|
||||
|
||||
|
@ -120,6 +120,12 @@ public:
|
||||
// Remove data from resource before the given offset.
|
||||
void EvictBefore(uint64_t aOffset);
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Dump(const char* aPath) {
|
||||
mInputBuffer.Dump(aPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
~SourceBufferResource();
|
||||
nsresult SeekInternal(int64_t aOffset);
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -19,6 +20,11 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#if defined(DEBUG)
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
struct JSContext;
|
||||
class JSObject;
|
||||
|
||||
@ -349,4 +355,22 @@ TrackBuffer::Decoders()
|
||||
return mInitializedDecoders;
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
void
|
||||
TrackBuffer::Dump(const char* aPath)
|
||||
{
|
||||
char path[255];
|
||||
PR_snprintf(path, sizeof(path), "%s/trackbuffer-%p", aPath, this);
|
||||
PR_MkDir(path, 0700);
|
||||
|
||||
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
|
||||
char buf[255];
|
||||
PR_snprintf(buf, sizeof(buf), "%s/reader-%p", path, mDecoders[i]->GetReader());
|
||||
PR_MkDir(buf, 0700);
|
||||
|
||||
mDecoders[i]->GetResource()->Dump(buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -82,6 +82,10 @@ public:
|
||||
// TODO: Refactor to a cleaner interface between TrackBuffer and MediaSourceReader.
|
||||
const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Dump(const char* aPath);
|
||||
#endif
|
||||
|
||||
private:
|
||||
~TrackBuffer();
|
||||
|
||||
|
@ -18,6 +18,62 @@
|
||||
#define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll
|
||||
namespace android {
|
||||
|
||||
// General Template: MediaCodec::getOutputGraphicBufferFromIndex(...)
|
||||
template <typename T, bool InterfaceSupported>
|
||||
struct OutputGraphicBufferStub
|
||||
{
|
||||
static status_t GetOutputGraphicBuffer(T *aMediaCodec,
|
||||
size_t aIndex,
|
||||
sp<GraphicBuffer> *aGraphicBuffer)
|
||||
{
|
||||
return ERROR_UNSUPPORTED;
|
||||
}
|
||||
};
|
||||
|
||||
// Class Template Specialization: MediaCodec::getOutputGraphicBufferFromIndex(...)
|
||||
template <typename T>
|
||||
struct OutputGraphicBufferStub<T, true>
|
||||
{
|
||||
static status_t GetOutputGraphicBuffer(T *aMediaCodec,
|
||||
size_t aIndex,
|
||||
sp<GraphicBuffer> *aGraphicBuffer)
|
||||
{
|
||||
if (aMediaCodec == nullptr || aGraphicBuffer == nullptr) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
*aGraphicBuffer = aMediaCodec->getOutputGraphicBufferFromIndex(aIndex);
|
||||
return OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper class to handle interface-difference of MediaCodec.
|
||||
struct MediaCodecInterfaceWrapper
|
||||
{
|
||||
typedef int8_t Supported;
|
||||
typedef int16_t Unsupported;
|
||||
|
||||
template <typename T>
|
||||
static auto TestOutputGraphicBuffer(T *aMediaCodec) -> decltype(aMediaCodec->getOutputGraphicBufferFromIndex(0), Supported());
|
||||
|
||||
template <typename T>
|
||||
static auto TestOutputGraphicBuffer(...) -> Unsupported;
|
||||
|
||||
// SFINAE: Substitution Failure Is Not An Error
|
||||
static const bool OutputGraphicBufferSupported = sizeof(TestOutputGraphicBuffer<MediaCodec>(nullptr)) == sizeof(Supported);
|
||||
|
||||
// Class Template Specialization
|
||||
static OutputGraphicBufferStub<MediaCodec, OutputGraphicBufferSupported> sOutputGraphicBufferStub;
|
||||
|
||||
// Wrapper Function
|
||||
static status_t GetOutputGraphicBuffer(MediaCodec *aMediaCodec,
|
||||
size_t aIndex,
|
||||
sp<GraphicBuffer> *aGraphicBuffer)
|
||||
{
|
||||
return sOutputGraphicBufferStub.GetOutputGraphicBuffer(aMediaCodec, aIndex, aGraphicBuffer);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
sp<MediaCodecProxy>
|
||||
MediaCodecProxy::CreateByType(sp<ALooper> aLooper,
|
||||
const char *aMime,
|
||||
@ -363,6 +419,37 @@ MediaCodecProxy::requestActivityNotification(const sp<AMessage> &aNotify)
|
||||
mCodec->requestActivityNotification(aNotify);
|
||||
}
|
||||
|
||||
status_t
|
||||
MediaCodecProxy::getOutputGraphicBufferFromIndex(size_t aIndex,
|
||||
sp<GraphicBuffer> *aGraphicBuffer)
|
||||
{
|
||||
// Read Lock for mCodec
|
||||
RWLock::AutoRLock arl(mCodecLock);
|
||||
|
||||
if (mCodec == nullptr) {
|
||||
return NO_INIT;
|
||||
}
|
||||
return MediaCodecInterfaceWrapper::GetOutputGraphicBuffer(mCodec.get(), aIndex, aGraphicBuffer);
|
||||
}
|
||||
|
||||
status_t
|
||||
MediaCodecProxy::getCapability(uint32_t *aCapability)
|
||||
{
|
||||
if (aCapability == nullptr) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
uint32_t capability = kEmptyCapability;
|
||||
|
||||
if (MediaCodecInterfaceWrapper::OutputGraphicBufferSupported) {
|
||||
capability |= kCanExposeGraphicBuffer;
|
||||
}
|
||||
|
||||
*aCapability = capability;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
// Called on a Binder thread
|
||||
void
|
||||
MediaCodecProxy::resourceReserved()
|
||||
|
@ -40,9 +40,15 @@ public:
|
||||
virtual void codecCanceled() = 0;
|
||||
};
|
||||
|
||||
enum Capability {
|
||||
kEmptyCapability = 0x00000000,
|
||||
kCanExposeGraphicBuffer = 0x00000001,
|
||||
};
|
||||
|
||||
enum {
|
||||
kKeyBufferIndex = 'bfin',
|
||||
};
|
||||
|
||||
// Check whether MediaCodec has been allocated.
|
||||
bool allocated() const;
|
||||
|
||||
@ -112,6 +118,14 @@ public:
|
||||
// an input/output buffer has become available, a format change is
|
||||
// pending, an error is pending.
|
||||
void requestActivityNotification(const sp<AMessage> &aNotify);
|
||||
|
||||
status_t getOutputGraphicBufferFromIndex(size_t aIndex,
|
||||
sp<GraphicBuffer> *aGraphicBuffer);
|
||||
|
||||
status_t getCapability(uint32_t *aCapability);
|
||||
|
||||
// Utility functions
|
||||
|
||||
// If aData is null, will notify decoder input EOS
|
||||
status_t Input(const uint8_t* aData, uint32_t aDataSize,
|
||||
int64_t aTimestampUsecs, uint64_t flags);
|
||||
@ -120,6 +134,7 @@ public:
|
||||
bool IsWaitingResources();
|
||||
bool IsDormantNeeded();
|
||||
void ReleaseMediaResources();
|
||||
|
||||
protected:
|
||||
virtual ~MediaCodecProxy();
|
||||
|
||||
@ -165,6 +180,7 @@ private:
|
||||
// MediaCodec instance
|
||||
mutable RWLock mCodecLock;
|
||||
sp<MediaCodec> mCodec;
|
||||
|
||||
//MediaCodec buffers to hold input/output data.
|
||||
Vector<sp<ABuffer> > mInputBuffers;
|
||||
Vector<sp<ABuffer> > mOutputBuffers;
|
||||
|
@ -29,7 +29,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_bug279495.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug344861.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s
|
||||
[test_bug386782.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
|
||||
[test_bug430624.html]
|
||||
|
@ -6,6 +6,6 @@ support-files =
|
||||
AudioChannelChromeScript.js
|
||||
|
||||
[test_telephonyPolicy.html]
|
||||
skip-if = buildapp == 'mulet' || (toolkit == 'gonk' || e10s)
|
||||
skip-if = buildapp == 'mulet' || (toolkit == 'gonk' || e10s) || os == "android"
|
||||
[test_audioChannelChange.html]
|
||||
skip-if = (toolkit != 'gonk')
|
||||
|
@ -416,12 +416,11 @@ ImageEncoder::ExtractDataInternal(const nsAString& aType,
|
||||
RefPtr<DataSourceSurface> emptyCanvas =
|
||||
Factory::CreateDataSourceSurfaceWithStride(IntSize(aSize.width, aSize.height),
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
4 * aSize.width);
|
||||
4 * aSize.width, true);
|
||||
if (NS_WARN_IF(!emptyCanvas)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ClearDataSourceSurface(emptyCanvas);
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!emptyCanvas->Map(DataSourceSurface::MapType::WRITE, &map)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -91,6 +91,10 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::Activity',
|
||||
},
|
||||
|
||||
'MozAbortablePromise': {
|
||||
'nativeType': 'mozilla::dom::AbortablePromise',
|
||||
},
|
||||
|
||||
'AbstractWorker': {
|
||||
'concrete': False
|
||||
},
|
||||
|
@ -897,10 +897,13 @@ CanvasRenderingContext2D::CheckSizeForSkiaGL(IntSize size) {
|
||||
// Cache the number of pixels on the primary screen
|
||||
static int32_t gScreenPixels = -1;
|
||||
if (gScreenPixels < 0) {
|
||||
// Default to historical mobile screen size of 980x480. In addition,
|
||||
// allow skia use up to this size even if the screen is smaller. A lot
|
||||
// content expects this size to work well.
|
||||
gScreenPixels = 980 * 480;
|
||||
// Default to historical mobile screen size of 980x480, like FishIEtank.
|
||||
// In addition, allow skia use up to this size even if the screen is smaller.
|
||||
// A lot content expects this size to work well.
|
||||
// See Bug 999841
|
||||
if (gfxPlatform::GetPlatform()->HasEnoughTotalSystemMemoryForSkiaGL()) {
|
||||
gScreenPixels = 980 * 480;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScreenManager> screenManager =
|
||||
do_GetService("@mozilla.org/gfx/screenmanager;1");
|
||||
@ -916,22 +919,8 @@ CanvasRenderingContext2D::CheckSizeForSkiaGL(IntSize size) {
|
||||
}
|
||||
}
|
||||
|
||||
// On high DPI devices the screen pixels may be scaled up. Make
|
||||
// sure to apply that scaling here as well if we are hooked up
|
||||
// to a widget.
|
||||
static double gDefaultScale = 0.0;
|
||||
if (gDefaultScale < 1.0) {
|
||||
nsIPresShell* ps = GetPresShell();
|
||||
if (ps) {
|
||||
nsIFrame* frame = ps->GetRootFrame();
|
||||
if (frame) {
|
||||
nsIWidget* widget = frame->GetNearestWidget();
|
||||
if (widget) {
|
||||
gDefaultScale = widget->GetDefaultScale().scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Just always use a scale of 1.0. It can be changed if a lot of contents need it.
|
||||
static double gDefaultScale = 1.0;
|
||||
|
||||
double scale = gDefaultScale > 0 ? gDefaultScale : 1.0;
|
||||
int32_t threshold = ceil(scale * scale * gScreenPixels);
|
||||
|
@ -1875,6 +1875,9 @@ TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
|
||||
bool
|
||||
TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
TABC_LOG("Handling double tap at %s with %p %p\n",
|
||||
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
|
||||
|
||||
if (!mGlobal || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
@ -1895,6 +1898,9 @@ TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid&
|
||||
bool
|
||||
TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
TABC_LOG("Handling single tap at %s with %p %p %d\n",
|
||||
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get(), mTouchEndCancelled);
|
||||
|
||||
if (!mGlobal || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
@ -1924,6 +1930,8 @@ TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
TABC_LOG("Dispatching single-tap component events to %s\n",
|
||||
Stringify(aPoint).c_str());
|
||||
int time = 0;
|
||||
DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget);
|
||||
DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget);
|
||||
@ -1933,6 +1941,9 @@ TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
|
||||
bool
|
||||
TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
TABC_LOG("Handling long tap at %s with %p %p\n",
|
||||
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
|
||||
|
||||
if (!mGlobal || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
@ -1945,6 +1956,8 @@ TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& a
|
||||
2, 1, 0, true,
|
||||
nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
|
||||
|
||||
TABC_LOG("Contextmenu event handled: %d\n", eventHandled);
|
||||
|
||||
// If no one handle context menu, fire MOZLONGTAP event
|
||||
if (!eventHandled) {
|
||||
LayoutDevicePoint currentPoint =
|
||||
@ -1953,6 +1966,7 @@ TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& a
|
||||
nsEventStatus status =
|
||||
DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
|
||||
eventHandled = (status == nsEventStatus_eConsumeNoDefault);
|
||||
TABC_LOG("MOZLONGTAP event handled: %d\n", eventHandled);
|
||||
}
|
||||
|
||||
SendContentReceivedTouch(aGuid, eventHandled);
|
||||
@ -2226,6 +2240,8 @@ bool
|
||||
TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
TABC_LOG("Receiving touch event of type %d\n", aEvent.message);
|
||||
|
||||
WidgetTouchEvent localEvent(aEvent);
|
||||
localEvent.widget = mWidget;
|
||||
for (size_t i = 0; i < localEvent.touches.Length(); i++) {
|
||||
|
118
dom/promise/AbortablePromise.cpp
Normal file
118
dom/promise/AbortablePromise.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/AbortablePromise.h"
|
||||
|
||||
#include "mozilla/dom/AbortablePromiseBinding.h"
|
||||
#include "mozilla/dom/PromiseNativeAbortCallback.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "PromiseCallback.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseNativeAbortCallback)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseNativeAbortCallback)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseNativeAbortCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTION_0(PromiseNativeAbortCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(AbortablePromise, Promise)
|
||||
NS_IMPL_RELEASE_INHERITED(AbortablePromise, Promise)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AbortablePromise)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Promise)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(AbortablePromise, Promise, mAbortCallback)
|
||||
|
||||
AbortablePromise::AbortablePromise(nsIGlobalObject* aGlobal,
|
||||
PromiseNativeAbortCallback& aAbortCallback)
|
||||
: Promise(aGlobal)
|
||||
, mAbortCallback(&aAbortCallback)
|
||||
{
|
||||
}
|
||||
|
||||
AbortablePromise::AbortablePromise(nsIGlobalObject* aGlobal)
|
||||
: Promise(aGlobal)
|
||||
{
|
||||
}
|
||||
|
||||
AbortablePromise::~AbortablePromise()
|
||||
{
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<AbortablePromise>
|
||||
AbortablePromise::Create(nsIGlobalObject* aGlobal,
|
||||
PromiseNativeAbortCallback& aAbortCallback,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<AbortablePromise> p = new AbortablePromise(aGlobal, aAbortCallback);
|
||||
p->CreateWrapper(aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
AbortablePromise::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MozAbortablePromiseBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<AbortablePromise>
|
||||
AbortablePromise::Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
|
||||
AbortCallback& aAbortCallback, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global;
|
||||
global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<AbortablePromise> promise = new AbortablePromise(global);
|
||||
promise->CreateWrapper(aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
promise->CallInitFunction(aGlobal, aInit, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
promise->mAbortCallback = &aAbortCallback;
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
AbortablePromise::Abort()
|
||||
{
|
||||
if (IsPending()) {
|
||||
return;
|
||||
}
|
||||
MaybeReject(NS_ERROR_ABORT);
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &AbortablePromise::DoAbort);
|
||||
Promise::DispatchToMainOrWorkerThread(runnable);
|
||||
}
|
||||
|
||||
void
|
||||
AbortablePromise::DoAbort()
|
||||
{
|
||||
if (mAbortCallback.HasWebIDLCallback()) {
|
||||
ErrorResult rv;
|
||||
mAbortCallback.GetWebIDLCallback()->Call(rv);
|
||||
return;
|
||||
}
|
||||
mAbortCallback.GetXPCOMCallback()->Call();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
66
dom/promise/AbortablePromise.h
Normal file
66
dom/promise/AbortablePromise.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_AbortablePromise_h__
|
||||
#define mozilla_dom_AbortablePromise_h__
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/CallbackObject.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AbortCallback;
|
||||
class PromiseNativeAbortCallback;
|
||||
|
||||
class AbortablePromise
|
||||
: public Promise
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AbortablePromise, Promise)
|
||||
|
||||
public:
|
||||
// It is the same as Promise::Create except that this takes an extra
|
||||
// aAbortCallback parameter to set the abort callback handler.
|
||||
static already_AddRefed<AbortablePromise>
|
||||
Create(nsIGlobalObject* aGlobal, PromiseNativeAbortCallback& aAbortCallback,
|
||||
ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
// Constructor used to create native AbortablePromise with C++.
|
||||
AbortablePromise(nsIGlobalObject* aGlobal,
|
||||
PromiseNativeAbortCallback& aAbortCallback);
|
||||
|
||||
// Constructor used to create AbortablePromise for JavaScript. It should be
|
||||
// called by the static AbortablePromise::Constructor.
|
||||
AbortablePromise(nsIGlobalObject* aGlobal);
|
||||
|
||||
virtual ~AbortablePromise();
|
||||
|
||||
public:
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<AbortablePromise>
|
||||
Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
|
||||
AbortCallback& aAbortCallback, ErrorResult& aRv);
|
||||
|
||||
void Abort();
|
||||
|
||||
private:
|
||||
void DoAbort();
|
||||
|
||||
// The callback functions to abort the promise.
|
||||
CallbackObjectHolder<AbortCallback,
|
||||
PromiseNativeAbortCallback> mAbortCallback;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AbortablePromise_h__
|
@ -325,26 +325,33 @@ Promise::WrapObject(JSContext* aCx)
|
||||
already_AddRefed<Promise>
|
||||
Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(aGlobal)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
nsRefPtr<Promise> p = new Promise(aGlobal);
|
||||
p->CreateWrapper(aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Promise::CreateWrapper(ErrorResult& aRv)
|
||||
{
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(mGlobal)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
nsRefPtr<Promise> p = new Promise(aGlobal);
|
||||
|
||||
JS::Rooted<JS::Value> ignored(cx);
|
||||
if (!WrapNewBindingObject(cx, p, &ignored)) {
|
||||
if (!WrapNewBindingObject(cx, this, &ignored)) {
|
||||
JS_ClearPendingException(cx);
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Need the .get() bit here to get template deduction working right
|
||||
dom::PreserveWrapper(p.get());
|
||||
|
||||
return p.forget();
|
||||
dom::PreserveWrapper(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -483,8 +490,6 @@ Promise::CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTas
|
||||
Promise::Constructor(const GlobalObject& aGlobal,
|
||||
PromiseInit& aInit, ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global;
|
||||
global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!global) {
|
||||
@ -497,20 +502,34 @@ Promise::Constructor(const GlobalObject& aGlobal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> resolveFunc(cx,
|
||||
CreateFunction(cx, aGlobal.Get(), promise,
|
||||
PromiseCallback::Resolve));
|
||||
if (!resolveFunc) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
promise->CallInitFunction(aGlobal, aInit, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Promise::CallInitFunction(const GlobalObject& aGlobal,
|
||||
PromiseInit& aInit, ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
|
||||
JS::Rooted<JSObject*> resolveFunc(cx,
|
||||
CreateFunction(cx, aGlobal.Get(), this,
|
||||
PromiseCallback::Resolve));
|
||||
if (!resolveFunc) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> rejectFunc(cx,
|
||||
CreateFunction(cx, aGlobal.Get(), promise,
|
||||
CreateFunction(cx, aGlobal.Get(), this,
|
||||
PromiseCallback::Reject));
|
||||
if (!rejectFunc) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
aInit.Call(resolveFunc, rejectFunc, aRv, CallbackObject::eRethrowExceptions);
|
||||
@ -524,13 +543,11 @@ Promise::Constructor(const GlobalObject& aGlobal,
|
||||
// function Promise(arg) { try { arg(a, b); } catch (e) { this.reject(e); }}
|
||||
if (!JS_WrapValue(cx, &value)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
promise->MaybeRejectInternal(cx, value);
|
||||
MaybeRejectInternal(cx, value);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Promise>
|
||||
|
@ -50,9 +50,9 @@ public:
|
||||
Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class Promise MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache,
|
||||
public SupportsWeakPtr<Promise>
|
||||
class Promise : public nsISupports,
|
||||
public nsWrapperCache,
|
||||
public SupportsWeakPtr<Promise>
|
||||
{
|
||||
friend class NativePromiseCallback;
|
||||
friend class PromiseResolverTask;
|
||||
@ -65,8 +65,6 @@ class Promise MOZ_FINAL : public nsISupports,
|
||||
friend class ThenableResolverTask;
|
||||
friend class WrapperPromiseCallback;
|
||||
|
||||
~Promise();
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
|
||||
@ -159,11 +157,32 @@ public:
|
||||
|
||||
void AppendNativeHandler(PromiseNativeHandler* aRunnable);
|
||||
|
||||
private:
|
||||
protected:
|
||||
// Do NOT call this unless you're Promise::Create. I wish we could enforce
|
||||
// that from inside this class too, somehow.
|
||||
explicit Promise(nsIGlobalObject* aGlobal);
|
||||
|
||||
virtual ~Promise();
|
||||
|
||||
// Queue an async task to current main or worker thread.
|
||||
static void
|
||||
DispatchToMainOrWorkerThread(nsIRunnable* aRunnable);
|
||||
|
||||
// Do JS-wrapping after Promise creation.
|
||||
void CreateWrapper(ErrorResult& aRv);
|
||||
|
||||
// Create the JS resolving functions of resolve() and reject(). And provide
|
||||
// references to the two functions by calling PromiseInit passed from Promise
|
||||
// constructor.
|
||||
void CallInitFunction(const GlobalObject& aGlobal, PromiseInit& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool IsPending()
|
||||
{
|
||||
return mResolvePending;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PromiseDebugging;
|
||||
|
||||
enum PromiseState {
|
||||
@ -189,10 +208,6 @@ private:
|
||||
mResult = aValue;
|
||||
}
|
||||
|
||||
// Queue an async task to current main or worker thread.
|
||||
static void
|
||||
DispatchToMainOrWorkerThread(nsIRunnable* aRunnable);
|
||||
|
||||
// This method processes promise's resolve/reject callbacks with promise's
|
||||
// result. It's executed when the resolver.resolve() or resolver.reject() is
|
||||
// called or when the promise already has a result and new callbacks are
|
||||
|
@ -20,13 +20,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(PromiseCallback)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
|
||||
|
||||
PromiseCallback::PromiseCallback()
|
||||
{
|
||||
|
36
dom/promise/PromiseNativeAbortCallback.h
Normal file
36
dom/promise/PromiseNativeAbortCallback.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PromiseNativeAbortCallback_h
|
||||
#define mozilla_dom_PromiseNativeAbortCallback_h
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/*
|
||||
* PromiseNativeAbortCallback allows C++ to react to an AbortablePromise being
|
||||
* aborted.
|
||||
*/
|
||||
class PromiseNativeAbortCallback : public nsISupports
|
||||
{
|
||||
protected:
|
||||
virtual ~PromiseNativeAbortCallback()
|
||||
{ }
|
||||
|
||||
public:
|
||||
// Implemented in AbortablePromise.cpp.
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(PromiseNativeAbortCallback)
|
||||
|
||||
virtual void Call() = 0;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PromiseNativeAbortCallback_h
|
@ -5,13 +5,16 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'AbortablePromise.h',
|
||||
'Promise.h',
|
||||
'PromiseDebugging.h',
|
||||
'PromiseNativeAbortCallback.h',
|
||||
'PromiseNativeHandler.h',
|
||||
'PromiseWorkerProxy.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AbortablePromise.cpp',
|
||||
'Promise.cpp',
|
||||
'PromiseCallback.cpp',
|
||||
'PromiseDebugging.cpp'
|
||||
|
@ -4,3 +4,4 @@
|
||||
[test_promise.html]
|
||||
[test_promise_utils.html]
|
||||
[test_resolve.html]
|
||||
[test_abortable_promise.html]
|
||||
|
115
dom/promise/tests/test_abortable_promise.html
Normal file
115
dom/promise/tests/test_abortable_promise.html
Normal file
@ -0,0 +1,115 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Promise.resolve(anything) Test</title>
|
||||
<script type="application/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="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript"><!--
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.abortablepromise.enabled", true]]},
|
||||
runTest);
|
||||
var gTests = [testPending, testResolved, testRejected];
|
||||
|
||||
function runTest() {
|
||||
if (gTests.length == 0) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
new Promise(gTests.shift()).then(runTest, SimpleTest.finish);
|
||||
}
|
||||
|
||||
// Aborting pending promise should first reject the promise and then call the
|
||||
// abortable callback.
|
||||
// The test succeeds once both the rejection handler and the abort handler have
|
||||
// been called.
|
||||
function testPending(succeed, fail) {
|
||||
var rejected = false;
|
||||
var aborted = false;
|
||||
|
||||
var p = new MozAbortablePromise(function(resolve, reject) {
|
||||
// Wait for a while so that the promise can be aborted before resolved.
|
||||
SimpleTest.executeSoon(function() {
|
||||
resolve(0);
|
||||
});
|
||||
}, function abortable() {
|
||||
aborted = true;
|
||||
ok(true, "Promise aborted.");
|
||||
if (rejected) {
|
||||
succeed();
|
||||
}
|
||||
});
|
||||
|
||||
p.then(function() {
|
||||
ok(false, "Failed to abort pending promise.");
|
||||
fail();
|
||||
}, function(what) {
|
||||
rejected = true;
|
||||
var isAbortException = (what && what.name) == "NS_ERROR_ABORT";
|
||||
ok(isAbortException, "Should have NS_ERROR_ABORT exception");
|
||||
if (!isAbortException) {
|
||||
fail();
|
||||
}
|
||||
if (aborted) {
|
||||
succeed();
|
||||
}
|
||||
});
|
||||
|
||||
// Abort the promise on creation.
|
||||
p.abort();
|
||||
}
|
||||
|
||||
// Do nothing when aborting resolved promise.
|
||||
function testResolved(succeed, fail) {
|
||||
var p = new MozAbortablePromise(function(resolve, reject) {
|
||||
resolve();
|
||||
}, function abortable() {
|
||||
ok(false, "Should not abort a resolved promise.");
|
||||
fail();
|
||||
});
|
||||
p.then(function() {
|
||||
ok(true, "Promise resolved.");
|
||||
// Wait for a while to ensure abort handle won't be called.
|
||||
setTimeout(succeed, 1000);
|
||||
}, function(what) {
|
||||
ok(false, "Failed to resolve promise: " + what);
|
||||
fail();
|
||||
});
|
||||
p.abort();
|
||||
}
|
||||
|
||||
// Do nothing when aborting rejected promise.
|
||||
function testRejected(succeed, fail) {
|
||||
var p = new MozAbortablePromise(function(resolve, reject) {
|
||||
reject(0);
|
||||
}, function abortable() {
|
||||
ok(false, "Should not abort a rejected promise.");
|
||||
fail();
|
||||
});
|
||||
|
||||
p.then(function() {
|
||||
ok(false, "Failed to reject promise.");
|
||||
fail();
|
||||
}, function(what) {
|
||||
is(what, 0, "promise rejected: " + what);
|
||||
// Wait for a while to ensure abort handle won't be called.
|
||||
setTimeout(succeed, 1000);
|
||||
});
|
||||
p.abort();
|
||||
}
|
||||
// -->
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -57,7 +57,7 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug351601.html]
|
||||
[test_bug369306.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(test timed out, can't focus back from popup window to opener?) b2g-desktop(test timed out, can't focus back from popup window to opener?)
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(test timed out, can't focus back from popup window to opener?) b2g-desktop(test timed out, can't focus back from popup window to opener?)
|
||||
[test_bug370098.html]
|
||||
[test_bug377539.html]
|
||||
[test_bug384122.html]
|
||||
@ -163,5 +163,5 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #Windows can't change size on Android # b2g(Windows can't change size on B2G) b2g-debug(Windows can't change size on B2G) b2g-desktop(Windows can't change size on B2G)
|
||||
[test_toJSON.html]
|
||||
[test_window_bar.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s
|
||||
[test_bug1022869.html]
|
||||
|
@ -118,6 +118,8 @@ var legacyMozPrefixedInterfaces =
|
||||
// IMPORTANT: Do not change the list below without review from a DOM peer!
|
||||
var interfaceNamesInGlobalScope =
|
||||
[
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "MozAbortablePromise", pref: "dom.abortablepromise.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AlarmsManager", pref: "dom.mozAlarms.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
19
dom/webidl/AbortablePromise.webidl
Normal file
19
dom/webidl/AbortablePromise.webidl
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
callback AbortCallback = void ();
|
||||
|
||||
[Constructor(PromiseInit init, AbortCallback abortCallback),
|
||||
Pref="dom.abortablepromise.enabled"]
|
||||
interface MozAbortablePromise : _Promise {
|
||||
/*
|
||||
* Aborts the promise.
|
||||
* If the promise has not been resolved or rejected, it should be rejected
|
||||
* with an Exception of type abort and then AbortCallback is called
|
||||
* asynchronously. Otherwise, nothing should be done.
|
||||
*/
|
||||
void abort();
|
||||
};
|
@ -16,6 +16,7 @@ PREPROCESSED_WEBIDL_FILES = [
|
||||
]
|
||||
|
||||
WEBIDL_FILES = [
|
||||
'AbortablePromise.webidl',
|
||||
'AbstractWorker.webidl',
|
||||
'ActivityRequestHandler.webidl',
|
||||
'AlarmsManager.webidl',
|
||||
|
@ -108,7 +108,7 @@ class UnregisterCallback MOZ_FINAL : public nsIServiceWorkerUnregisterCallback
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
UnregisterCallback(Promise* aPromise)
|
||||
explicit UnregisterCallback(Promise* aPromise)
|
||||
: mPromise(aPromise)
|
||||
{
|
||||
MOZ_ASSERT(mPromise);
|
||||
|
@ -1117,20 +1117,20 @@ public:
|
||||
* This creates a simple data source surface for a certain size. It allocates
|
||||
* new memory for the surface. This memory is freed when the surface is
|
||||
* destroyed. The caller is responsible for handing the case where nullptr
|
||||
* is returned.
|
||||
* is returned. The surface is not zeroed unless requested.
|
||||
*/
|
||||
static TemporaryRef<DataSourceSurface>
|
||||
CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat);
|
||||
CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat, bool aZero = false);
|
||||
|
||||
/**
|
||||
* This creates a simple data source surface for a certain size with a
|
||||
* specific stride, which must be large enough to fit all pixels.
|
||||
* It allocates new memory for the surface. This memory is freed when
|
||||
* the surface is destroyed. The caller is responsible for handling the case
|
||||
* where nullptr is returned.
|
||||
* where nullptr is returned. The surface is not zeroed unless requested.
|
||||
*/
|
||||
static TemporaryRef<DataSourceSurface>
|
||||
CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride);
|
||||
CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride, bool aZero = false);
|
||||
|
||||
/**
|
||||
* This creates a simple data source surface for some existing data. It will
|
||||
|
@ -48,6 +48,8 @@ SurfaceToPackedBGR(DataSourceSurface *aSurface);
|
||||
/**
|
||||
* Clears all the bytes in a DataSourceSurface's data array to zero (so to
|
||||
* transparent black for SurfaceFormat::B8G8R8A8, for example).
|
||||
* Note that DataSourceSurfaces can be initialized to zero, which is
|
||||
* more efficient than zeroing the surface after initialization.
|
||||
*/
|
||||
void
|
||||
ClearDataSourceSurface(DataSourceSurface *aSurface);
|
||||
|
@ -1358,9 +1358,8 @@ DrawTargetCG::Init(BackendType aType,
|
||||
}
|
||||
static_assert(sizeof(decltype(mData[0])) == 1,
|
||||
"mData.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
|
||||
mData.Realloc(/* actually an object count */ bufLen);
|
||||
mData.Realloc(/* actually an object count */ bufLen, true);
|
||||
aData = static_cast<unsigned char*>(mData);
|
||||
memset(aData, 0, bufLen);
|
||||
}
|
||||
|
||||
mSize = aSize;
|
||||
|
@ -700,7 +700,8 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
|
||||
|
||||
TemporaryRef<DataSourceSurface>
|
||||
Factory::CreateDataSourceSurface(const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
SurfaceFormat aFormat,
|
||||
bool aZero)
|
||||
{
|
||||
if (!CheckSurfaceSize(aSize)) {
|
||||
gfxWarning() << "CreateDataSourceSurface failed with bad size";
|
||||
@ -708,7 +709,7 @@ Factory::CreateDataSourceSurface(const IntSize &aSize,
|
||||
}
|
||||
|
||||
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
|
||||
if (newSurf->Init(aSize, aFormat)) {
|
||||
if (newSurf->Init(aSize, aFormat, aZero)) {
|
||||
return newSurf.forget();
|
||||
}
|
||||
|
||||
@ -719,7 +720,8 @@ Factory::CreateDataSourceSurface(const IntSize &aSize,
|
||||
TemporaryRef<DataSourceSurface>
|
||||
Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
|
||||
SurfaceFormat aFormat,
|
||||
int32_t aStride)
|
||||
int32_t aStride,
|
||||
bool aZero)
|
||||
{
|
||||
if (aStride < aSize.width * BytesPerPixel(aFormat)) {
|
||||
gfxWarning() << "CreateDataSourceSurfaceWithStride failed with bad stride";
|
||||
@ -727,7 +729,7 @@ Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
|
||||
}
|
||||
|
||||
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
|
||||
if (newSurf->InitWithStride(aSize, aFormat, aStride)) {
|
||||
if (newSurf->InitWithStride(aSize, aFormat, aStride, aZero)) {
|
||||
return newSurf.forget();
|
||||
}
|
||||
|
||||
|
@ -492,16 +492,13 @@ GetDataSurfaceInRect(SourceSurface *aSurface,
|
||||
IntRect intersectInDestSpace = intersect - aDestRect.TopLeft();
|
||||
SurfaceFormat format = aSurface ? aSurface->GetFormat() : SurfaceFormat(SurfaceFormat::B8G8R8A8);
|
||||
|
||||
bool clear = aEdgeMode == EDGE_MODE_NONE && !aSurfaceRect.Contains(aDestRect);
|
||||
RefPtr<DataSourceSurface> target =
|
||||
Factory::CreateDataSourceSurface(aDestRect.Size(), format);
|
||||
Factory::CreateDataSourceSurface(aDestRect.Size(), format, clear);
|
||||
if (MOZ2D_WARN_IF(!target)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aEdgeMode == EDGE_MODE_NONE && !aSurfaceRect.Contains(aDestRect)) {
|
||||
ClearDataSourceSurface(target);
|
||||
}
|
||||
|
||||
if (!aSurface) {
|
||||
return target.forget();
|
||||
}
|
||||
@ -2371,11 +2368,10 @@ FilterNodeConvolveMatrixSoftware::DoRender(const IntRect& aRect,
|
||||
DebugOnlyAutoColorSamplingAccessControl accessControl(input);
|
||||
|
||||
RefPtr<DataSourceSurface> target =
|
||||
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, true);
|
||||
if (MOZ2D_WARN_IF(!target)) {
|
||||
return nullptr;
|
||||
}
|
||||
ClearDataSourceSurface(target);
|
||||
|
||||
IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
|
||||
|
||||
@ -2776,15 +2772,13 @@ FilterNodeCompositeSoftware::Render(const IntRect& aRect)
|
||||
RefPtr<DataSourceSurface> start =
|
||||
GetInputDataSourceSurface(IN_COMPOSITE_IN_START, aRect, NEED_COLOR_CHANNELS);
|
||||
RefPtr<DataSourceSurface> dest =
|
||||
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, !start);
|
||||
if (MOZ2D_WARN_IF(!dest)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (start) {
|
||||
CopyRect(start, dest, aRect - aRect.TopLeft(), IntPoint());
|
||||
} else {
|
||||
ClearDataSourceSurface(dest);
|
||||
}
|
||||
|
||||
for (size_t inputIndex = 1; inputIndex < NumberOfSetInputs(); inputIndex++) {
|
||||
|
@ -44,7 +44,8 @@ SourceSurfaceRawData::GuaranteePersistance()
|
||||
|
||||
bool
|
||||
SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
SurfaceFormat aFormat,
|
||||
bool aZero)
|
||||
{
|
||||
mFormat = aFormat;
|
||||
mStride = GetAlignedStride<16>(aSize.width * BytesPerPixel(aFormat));
|
||||
@ -53,7 +54,7 @@ SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
|
||||
if (bufLen > 0) {
|
||||
static_assert(sizeof(decltype(mArray[0])) == 1,
|
||||
"mArray.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
|
||||
mArray.Realloc(/* actually an object count */ bufLen);
|
||||
mArray.Realloc(/* actually an object count */ bufLen, aZero);
|
||||
mSize = aSize;
|
||||
} else {
|
||||
mArray.Dealloc();
|
||||
@ -66,7 +67,8 @@ SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
|
||||
bool
|
||||
SourceSurfaceAlignedRawData::InitWithStride(const IntSize &aSize,
|
||||
SurfaceFormat aFormat,
|
||||
int32_t aStride)
|
||||
int32_t aStride,
|
||||
bool aZero)
|
||||
{
|
||||
mFormat = aFormat;
|
||||
mStride = aStride;
|
||||
@ -75,7 +77,7 @@ SourceSurfaceAlignedRawData::InitWithStride(const IntSize &aSize,
|
||||
if (bufLen > 0) {
|
||||
static_assert(sizeof(decltype(mArray[0])) == 1,
|
||||
"mArray.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
|
||||
mArray.Realloc(/* actually an object count */ bufLen);
|
||||
mArray.Realloc(/* actually an object count */ bufLen, aZero);
|
||||
mSize = aSize;
|
||||
} else {
|
||||
mArray.Dealloc();
|
||||
|
@ -56,10 +56,12 @@ public:
|
||||
virtual SurfaceFormat GetFormat() const { return mFormat; }
|
||||
|
||||
bool Init(const IntSize &aSize,
|
||||
SurfaceFormat aFormat);
|
||||
SurfaceFormat aFormat,
|
||||
bool aZero);
|
||||
bool InitWithStride(const IntSize &aSize,
|
||||
SurfaceFormat aFormat,
|
||||
int32_t aStride);
|
||||
int32_t aStride,
|
||||
bool aZero);
|
||||
|
||||
private:
|
||||
AlignedArray<uint8_t> mArray;
|
||||
|
@ -103,11 +103,11 @@ struct AlignedArray
|
||||
{
|
||||
}
|
||||
|
||||
explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount)
|
||||
explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount, bool aZero = false)
|
||||
: mStorage(nullptr)
|
||||
, mCount(0)
|
||||
{
|
||||
Realloc(aCount);
|
||||
Realloc(aCount, aZero);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE ~AlignedArray()
|
||||
@ -138,7 +138,7 @@ struct AlignedArray
|
||||
mPtr = nullptr;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void Realloc(size_t aCount)
|
||||
MOZ_ALWAYS_INLINE void Realloc(size_t aCount, bool aZero = false)
|
||||
{
|
||||
delete [] mStorage;
|
||||
CheckedInt32 storageByteCount =
|
||||
@ -151,7 +151,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.
|
||||
mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
|
||||
if (aZero) {
|
||||
mStorage = static_cast<uint8_t *>(calloc(1, storageByteCount.value()));
|
||||
} else {
|
||||
mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
|
||||
}
|
||||
if (!mStorage) {
|
||||
mStorage = nullptr;
|
||||
mPtr = nullptr;
|
||||
|
@ -814,6 +814,14 @@ AsyncPanZoomController::AssertOnControllerThread() {
|
||||
MOZ_ASSERT(sControllerThread == PR_GetCurrentThread());
|
||||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::AssertOnCompositorThread()
|
||||
{
|
||||
if (GetThreadAssertionsEnabled()) {
|
||||
Compositor::AssertOnCompositorThread();
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
AsyncPanZoomController::InitializeGlobalState()
|
||||
{
|
||||
@ -870,9 +878,7 @@ AsyncPanZoomController::~AsyncPanZoomController() {
|
||||
PCompositorParent*
|
||||
AsyncPanZoomController::GetSharedFrameMetricsCompositor()
|
||||
{
|
||||
if (GetThreadAssertionsEnabled()) {
|
||||
Compositor::AssertOnCompositorThread();
|
||||
}
|
||||
AssertOnCompositorThread();
|
||||
|
||||
if (mSharingFrameMetricsAcrossProcesses) {
|
||||
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(mLayersId);
|
||||
@ -899,6 +905,8 @@ AsyncPanZoomController::GetGestureEventListener() const {
|
||||
void
|
||||
AsyncPanZoomController::Destroy()
|
||||
{
|
||||
AssertOnCompositorThread();
|
||||
|
||||
CancelAnimation();
|
||||
|
||||
mTouchBlockQueue.Clear();
|
||||
@ -2357,6 +2365,8 @@ AsyncPanZoomController::FireAsyncScrollOnTimeout()
|
||||
bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
|
||||
Vector<Task*>* aOutDeferredTasks)
|
||||
{
|
||||
AssertOnCompositorThread();
|
||||
|
||||
// This function may get called multiple with the same sample time, because
|
||||
// there may be multiple layers with this APZC, and each layer invokes this
|
||||
// function during composition. However we only want to do one animation step
|
||||
@ -2429,6 +2439,8 @@ void AsyncPanZoomController::GetOverscrollTransform(Matrix4x4* aTransform) const
|
||||
|
||||
bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
|
||||
{
|
||||
AssertOnCompositorThread();
|
||||
|
||||
// The eventual return value of this function. The compositor needs to know
|
||||
// whether or not to advance by a frame as soon as it can. For example, if a
|
||||
// fling is happening, it has to keep compositing so that the animation is
|
||||
@ -2574,6 +2586,8 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) {
|
||||
AssertOnCompositorThread();
|
||||
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
bool isDefault = mFrameMetrics.IsDefault();
|
||||
|
||||
|
@ -1105,10 +1105,16 @@ public:
|
||||
static bool GetThreadAssertionsEnabled();
|
||||
/**
|
||||
* This can be used to assert that the current thread is the
|
||||
* controller/UI thread (on which input events are received.
|
||||
* controller/UI thread (on which input events are received).
|
||||
* This does nothing if thread assertions are disabled.
|
||||
*/
|
||||
static void AssertOnControllerThread();
|
||||
/**
|
||||
* This can be used to assert that the current thread is the
|
||||
* compositor thread (which applies the async transform).
|
||||
* This does nothing if thread assertions are disabled.
|
||||
*/
|
||||
static void AssertOnCompositorThread();
|
||||
/**
|
||||
* Set an extra offset for testing async scrolling.
|
||||
*/
|
||||
|
@ -149,6 +149,12 @@ CompositorThreadHolder::CreateCompositorThread()
|
||||
* Compositor hangs seen in the wild, but is short enough to not miss getting
|
||||
* native hang stacks. */
|
||||
options.permanent_hang_timeout = 2048; // milliseconds
|
||||
#if defined(_WIN32)
|
||||
/* With d3d9 the compositor thread creates native ui, see DeviceManagerD3D9. As
|
||||
* such the thread is a gui thread, and must process a windows message queue or
|
||||
* risk deadlocks. Chromium message loop TYPE_UI does exactly what we need. */
|
||||
options.message_loop_type = MessageLoop::TYPE_UI;
|
||||
#endif
|
||||
|
||||
if (!compositorThread->StartWithOptions(options)) {
|
||||
delete compositorThread;
|
||||
|
@ -278,6 +278,7 @@ gfxPlatform::gfxPlatform()
|
||||
uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
|
||||
InitBackendPrefs(canvasMask, BackendType::CAIRO,
|
||||
contentMask, BackendType::CAIRO);
|
||||
mTotalSystemMemory = mozilla::hal::GetTotalSystemMemory();
|
||||
}
|
||||
|
||||
gfxPlatform*
|
||||
@ -852,14 +853,12 @@ gfxPlatform::InitializeSkiaCacheLimits()
|
||||
cacheSizeLimit *= 1024*1024;
|
||||
|
||||
if (usingDynamicCache) {
|
||||
uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory();
|
||||
|
||||
if (totalMemory < 512*1024*1024) {
|
||||
if (mTotalSystemMemory < 512*1024*1024) {
|
||||
// We need a very minimal cache on anything smaller than 512mb.
|
||||
// Note the large jump as we cross 512mb (from 2mb to 32mb).
|
||||
cacheSizeLimit = 2*1024*1024;
|
||||
} else if (totalMemory > 0) {
|
||||
cacheSizeLimit = totalMemory / 16;
|
||||
} else if (mTotalSystemMemory > 0) {
|
||||
cacheSizeLimit = mTotalSystemMemory / 16;
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,6 +911,17 @@ gfxPlatform::PurgeSkiaCache()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (mTotalSystemMemory < 250*1024*1024) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
|
||||
{
|
||||
|
@ -547,6 +547,7 @@ public:
|
||||
|
||||
static bool UsesOffMainThreadCompositing();
|
||||
|
||||
bool HasEnoughTotalSystemMemoryForSkiaGL();
|
||||
protected:
|
||||
gfxPlatform();
|
||||
virtual ~gfxPlatform();
|
||||
@ -616,6 +617,8 @@ protected:
|
||||
// max number of entries in word cache
|
||||
int32_t mWordCacheMaxEntries;
|
||||
|
||||
uint32_t mTotalSystemMemory;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Start up Thebes.
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -188,21 +189,21 @@ class ScaleRequest
|
||||
public:
|
||||
ScaleRequest(RasterImage* aImage,
|
||||
const nsIntSize& aSize,
|
||||
imgFrame* aSrcFrame)
|
||||
: dstSize(aSize)
|
||||
, dstLocked(false)
|
||||
RawAccessFrameRef&& aSrcRef)
|
||||
: weakImage(aImage)
|
||||
, srcRef(Move(aSrcRef))
|
||||
, srcRect(srcRef->GetRect())
|
||||
, dstSize(aSize)
|
||||
, done(false)
|
||||
, stopped(false)
|
||||
{
|
||||
MOZ_ASSERT(!aSrcFrame->GetIsPaletted());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!srcRef->GetIsPaletted());
|
||||
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
|
||||
|
||||
weakImage = aImage;
|
||||
srcRect = aSrcFrame->GetRect();
|
||||
}
|
||||
|
||||
// This can only be called on the main thread.
|
||||
bool GetSurfaces(imgFrame* srcFrame)
|
||||
bool AcquireResources()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -211,80 +212,68 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (!dstLocked) {
|
||||
if (!dstFrame) {
|
||||
// We need to hold a lock onto the RasterImage object itself so that
|
||||
// it (and its associated imgFrames) aren't marked as discardable.
|
||||
bool imgLocked = NS_SUCCEEDED(image->LockImage());
|
||||
bool srcLocked = NS_SUCCEEDED(srcFrame->LockImageData());
|
||||
srcSurface = srcFrame->GetSurface();
|
||||
|
||||
dstLocked = NS_SUCCEEDED(dstFrame->LockImageData());
|
||||
dstSurface = dstFrame->GetSurface();
|
||||
|
||||
success = imgLocked && srcLocked && dstLocked && srcSurface && dstSurface;
|
||||
|
||||
if (success) {
|
||||
srcData = srcFrame->GetImageData();
|
||||
dstData = dstFrame->GetImageData();
|
||||
srcStride = srcFrame->GetImageBytesPerRow();
|
||||
dstStride = dstFrame->GetImageBytesPerRow();
|
||||
srcFormat = srcFrame->GetFormat();
|
||||
if (NS_FAILED(image->LockImage())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have references to the surfaces, so we don't need to leave
|
||||
// the source frame (that we don't own) locked. We'll unlock the
|
||||
// destination frame in ReleaseSurfaces(), below.
|
||||
if (srcLocked) {
|
||||
success = NS_SUCCEEDED(srcFrame->UnlockImageData()) && success;
|
||||
// We'll need a destination frame. It's unconditionally ARGB32 because
|
||||
// that's what the scaler outputs.
|
||||
nsRefPtr<imgFrame> tentativeDstFrame = new imgFrame();
|
||||
nsresult rv =
|
||||
tentativeDstFrame->Init(0, 0, dstSize.width, dstSize.height,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need a strong reference to the raw data for the destination frame.
|
||||
// (We already got one for the source frame in the constructor.)
|
||||
RawAccessFrameRef tentativeDstRef = tentativeDstFrame->RawAccessRef();
|
||||
if (!tentativeDstRef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dstFrame = tentativeDstFrame.forget();
|
||||
dstRef = Move(tentativeDstRef);
|
||||
}
|
||||
|
||||
return success;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This can only be called on the main thread.
|
||||
bool ReleaseSurfaces()
|
||||
void ReleaseResources()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsRefPtr<RasterImage> image = weakImage.get();
|
||||
if (!image) {
|
||||
return false;
|
||||
if (image) {
|
||||
image->UnlockImage();
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (dstLocked) {
|
||||
if (DiscardingEnabled())
|
||||
dstFrame->SetDiscardable();
|
||||
success = NS_SUCCEEDED(dstFrame->UnlockImageData());
|
||||
success = success && NS_SUCCEEDED(image->UnlockImage());
|
||||
|
||||
dstLocked = false;
|
||||
srcData = nullptr;
|
||||
dstData = nullptr;
|
||||
srcSurface = nullptr;
|
||||
dstSurface = nullptr;
|
||||
if (DiscardingEnabled() && dstFrame) {
|
||||
dstFrame->SetDiscardable();
|
||||
}
|
||||
return success;
|
||||
|
||||
// Release everything except dstFrame, which we keep around for RasterImage
|
||||
// to retrieve.
|
||||
srcRef.reset();
|
||||
dstRef.reset();
|
||||
}
|
||||
|
||||
// These values may only be touched on the main thread.
|
||||
// These values may only be modified on the main thread.
|
||||
WeakPtr<RasterImage> weakImage;
|
||||
nsRefPtr<imgFrame> dstFrame;
|
||||
RefPtr<SourceSurface> srcSurface;
|
||||
RefPtr<SourceSurface> dstSurface;
|
||||
RawAccessFrameRef srcRef;
|
||||
RawAccessFrameRef dstRef;
|
||||
|
||||
// Below are the values that may be touched on the scaling thread.
|
||||
uint8_t* srcData;
|
||||
uint8_t* dstData;
|
||||
// Below are the values that may be modified on the scaling thread.
|
||||
nsIntRect srcRect;
|
||||
nsIntSize dstSize;
|
||||
uint32_t srcStride;
|
||||
uint32_t dstStride;
|
||||
SurfaceFormat srcFormat;
|
||||
bool dstLocked;
|
||||
bool done;
|
||||
|
||||
// This boolean is accessed from both threads simultaneously without locking.
|
||||
// That's safe because stopping a ScaleRequest is strictly an optimization;
|
||||
// if we're not cache-coherent, at worst we'll do extra work.
|
||||
@ -300,11 +289,13 @@ public:
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// ScaleWorker is finished with this request, so we can unlock the data now.
|
||||
mScaleRequest->ReleaseSurfaces();
|
||||
|
||||
// Grab the weak image pointer before the request releases it.
|
||||
nsRefPtr<RasterImage> image = mScaleRequest->weakImage.get();
|
||||
|
||||
// ScaleWorker is finished with this request, so release everything that we
|
||||
// don't need anymore.
|
||||
mScaleRequest->ReleaseResources();
|
||||
|
||||
if (image) {
|
||||
RasterImage::ScaleStatus status;
|
||||
if (mScaleRequest->done) {
|
||||
@ -328,36 +319,36 @@ class ScaleRunner : public nsRunnable
|
||||
public:
|
||||
ScaleRunner(RasterImage* aImage,
|
||||
const nsIntSize& aSize,
|
||||
imgFrame* aSrcFrame)
|
||||
RawAccessFrameRef&& aSrcRef)
|
||||
{
|
||||
nsAutoPtr<ScaleRequest> request(new ScaleRequest(aImage, aSize, aSrcFrame));
|
||||
|
||||
// Destination is unconditionally ARGB32 because that's what the scaler
|
||||
// outputs.
|
||||
request->dstFrame = new imgFrame();
|
||||
nsresult rv = request->dstFrame->Init(0, 0, request->dstSize.width, request->dstSize.height,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
|
||||
if (NS_FAILED(rv) || !request->GetSurfaces(aSrcFrame)) {
|
||||
nsAutoPtr<ScaleRequest> req(new ScaleRequest(aImage, aSize, Move(aSrcRef)));
|
||||
if (!req->AcquireResources()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aImage->ScalingStart(request);
|
||||
|
||||
mScaleRequest = request;
|
||||
aImage->ScalingStart(req);
|
||||
mScaleRequest = req;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// An alias just for ease of typing
|
||||
ScaleRequest* request = mScaleRequest;
|
||||
ScaleRequest* req = mScaleRequest.get();
|
||||
|
||||
if (!request->stopped) {
|
||||
request->done = gfx::Scale(request->srcData, request->srcRect.width, request->srcRect.height, request->srcStride,
|
||||
request->dstData, request->dstSize.width, request->dstSize.height, request->dstStride,
|
||||
request->srcFormat);
|
||||
if (!req->stopped) {
|
||||
// Collect information from the frames that we need to scale.
|
||||
uint8_t* srcData = req->srcRef->GetImageData();
|
||||
uint8_t* dstData = req->dstRef->GetImageData();
|
||||
uint32_t srcStride = req->srcRef->GetImageBytesPerRow();
|
||||
uint32_t dstStride = req->dstRef->GetImageBytesPerRow();
|
||||
SurfaceFormat srcFormat = req->srcRef->GetFormat();
|
||||
|
||||
// Actually do the scaling.
|
||||
req->done =
|
||||
gfx::Scale(srcData, req->srcRect.width, req->srcRect.height, srcStride,
|
||||
dstData, req->dstSize.width, req->dstSize.height, dstStride,
|
||||
srcFormat);
|
||||
} else {
|
||||
request->done = false;
|
||||
req->done = false;
|
||||
}
|
||||
|
||||
// OK, we've got a new scaled image. Let's get the main thread to unlock and
|
||||
@ -863,7 +854,9 @@ RasterImage::CopyFrame(uint32_t aWhichFrame,
|
||||
|
||||
IntSize size(mSize.width, mSize.height);
|
||||
RefPtr<DataSourceSurface> surf =
|
||||
Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
|
||||
Factory::CreateDataSourceSurface(size,
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
/* aZero = */ true);
|
||||
if (NS_WARN_IF(!surf)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2622,8 +2615,8 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
|
||||
}
|
||||
|
||||
// We also can't scale if we can't lock the image data for this frame.
|
||||
if (NS_FAILED(aFrame->LockImageData())) {
|
||||
aFrame->UnlockImageData();
|
||||
RawAccessFrameRef frameRef = aFrame->RawAccessRef();
|
||||
if (!frameRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2632,7 +2625,7 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
|
||||
mScaleRequest->stopped = true;
|
||||
}
|
||||
|
||||
nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aSize, aFrame);
|
||||
nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aSize, Move(frameRef));
|
||||
if (runner->IsOK()) {
|
||||
if (!sScaleWorkerThread) {
|
||||
NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread));
|
||||
@ -2641,8 +2634,6 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
|
||||
|
||||
sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
aFrame->UnlockImageData();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -742,15 +742,17 @@ bool imgFrame::ImageComplete() const
|
||||
}
|
||||
|
||||
// A hint from the image decoders that this image has no alpha, even
|
||||
// though we created is ARGB32. This changes our format to RGB24,
|
||||
// which in turn will cause us to Optimize() to RGB24. Has no effect
|
||||
// after Optimize() is called, though in all cases it will be just a
|
||||
// performance win -- the pixels are still correct and have the A byte
|
||||
// set to 0xff.
|
||||
// though we're decoding it as B8G8R8A8.
|
||||
// Since this is only called during decoding, there is a mImageSurface
|
||||
// that should be updated to use B8G8R8X8. This doesn't change the
|
||||
// underlying data at all, but allows DrawTargets to avoid blending
|
||||
// when drawing known opaque images.
|
||||
void imgFrame::SetHasNoAlpha()
|
||||
{
|
||||
if (mFormat == SurfaceFormat::B8G8R8A8) {
|
||||
mFormat = SurfaceFormat::B8G8R8X8;
|
||||
MOZ_ASSERT(mImageSurface);
|
||||
mImageSurface = CreateLockedSurface(mVBuf, mSize, mFormat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,8 @@ NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer,
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface =
|
||||
Factory::CreateDataSourceSurface(IntSize(aWidth, aHeight),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
/* aZero = */ true);
|
||||
if (NS_WARN_IF(!dataSurface)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1077,6 +1077,22 @@ if test -n "$MOZ_ASAN"; then
|
||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||
fi
|
||||
AC_SUBST(MOZ_ASAN)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use Memory Sanitizer
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(memory-sanitizer,
|
||||
[ --enable-memory-sanitizer Enable Memory Sanitizer (default=no)],
|
||||
MOZ_MSAN=1,
|
||||
MOZ_MSAN= )
|
||||
if test -n "$MOZ_MSAN"; then
|
||||
MOZ_LLVM_HACKS=1
|
||||
AC_DEFINE(MOZ_MSAN)
|
||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||
fi
|
||||
AC_SUBST(MOZ_MSAN)
|
||||
|
||||
# The LLVM symbolizer is used by all sanitizers
|
||||
AC_SUBST(LLVM_SYMBOLIZER)
|
||||
|
||||
dnl ========================================================
|
||||
@ -1968,7 +1984,7 @@ case "$target" in
|
||||
;;
|
||||
*-solaris*)
|
||||
if test -z "$GNU_CC"; then
|
||||
eOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-M $(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
|
||||
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-M $(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
|
||||
else
|
||||
if test -z "$GCC_USE_GNU_LD"; then
|
||||
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,-M -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
|
||||
|
@ -2034,7 +2034,8 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(optimizationLevel);
|
||||
const JitCompileOptions options(cx);
|
||||
|
||||
IonBuilder *builder = alloc->new_<IonBuilder>(CompileCompartment::get(cx->compartment()),
|
||||
IonBuilder *builder = alloc->new_<IonBuilder>((JSContext *) nullptr,
|
||||
CompileCompartment::get(cx->compartment()),
|
||||
options, temp, graph, constraints,
|
||||
inspector, info, optimizationInfo,
|
||||
baselineFrameInspector);
|
||||
|
@ -2792,7 +2792,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
BaselineInspector inspector(script);
|
||||
const JitCompileOptions options(cx);
|
||||
|
||||
IonBuilder builder(CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
|
||||
IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
|
||||
&inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
|
||||
|
||||
if (!builder.build()) {
|
||||
@ -3019,7 +3019,7 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
BaselineInspector inspector(script);
|
||||
const JitCompileOptions options(cx);
|
||||
|
||||
IonBuilder builder(CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
|
||||
IonBuilder builder(nullptr, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
|
||||
&inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
|
||||
|
||||
if (!builder.build()) {
|
||||
|
@ -106,7 +106,7 @@ jit::NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame, Compil
|
||||
return inspector;
|
||||
}
|
||||
|
||||
IonBuilder::IonBuilder(CompileCompartment *comp,
|
||||
IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
|
||||
const JitCompileOptions &options, TempAllocator *temp,
|
||||
MIRGraph *graph, types::CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, CompileInfo *info,
|
||||
@ -115,6 +115,7 @@ IonBuilder::IonBuilder(CompileCompartment *comp,
|
||||
uint32_t loopDepth)
|
||||
: MIRGenerator(comp, options, temp, graph, info, optimizationInfo),
|
||||
backgroundCodegen_(nullptr),
|
||||
analysisContext(analysisContext),
|
||||
baselineFrame_(baselineFrame),
|
||||
constraints_(constraints),
|
||||
analysis_(*temp, info->script()),
|
||||
@ -146,6 +147,7 @@ IonBuilder::IonBuilder(CompileCompartment *comp,
|
||||
abortReason_ = AbortReason_Disable;
|
||||
|
||||
JS_ASSERT(script()->hasBaselineScript() == (info->executionMode() != ArgumentsUsageAnalysis));
|
||||
JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis));
|
||||
|
||||
if (!info->executionModeIsAnalysis())
|
||||
script()->baselineScript()->setIonCompiledOrInlined();
|
||||
@ -154,6 +156,7 @@ IonBuilder::IonBuilder(CompileCompartment *comp,
|
||||
void
|
||||
IonBuilder::clearForBackEnd()
|
||||
{
|
||||
JS_ASSERT(!analysisContext);
|
||||
baselineFrame_ = nullptr;
|
||||
|
||||
// The caches below allocate data from the malloc heap. Release this before
|
||||
@ -346,6 +349,22 @@ IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
|
||||
if (!target->isInterpreted())
|
||||
return DontInline(nullptr, "Non-interpreted target");
|
||||
|
||||
// Allow constructing lazy scripts when performing the definite properties
|
||||
// analysis, as baseline has not been used to warm the caller up yet.
|
||||
if (target->isInterpreted() && info().executionMode() == DefinitePropertiesAnalysis) {
|
||||
RootedScript script(analysisContext, target->getOrCreateScript(analysisContext));
|
||||
if (!script)
|
||||
return InliningDecision_Error;
|
||||
|
||||
if (!script->hasBaselineScript() && script->canBaselineCompile()) {
|
||||
MethodStatus status = BaselineCompile(analysisContext, script);
|
||||
if (status == Method_Error)
|
||||
return InliningDecision_Error;
|
||||
if (status != Method_Compiled)
|
||||
return InliningDecision_DontInline;
|
||||
}
|
||||
}
|
||||
|
||||
if (!target->hasScript())
|
||||
return DontInline(nullptr, "Lazy script");
|
||||
|
||||
@ -4184,10 +4203,16 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
AutoAccumulateReturns aar(graph(), returns);
|
||||
|
||||
// Build the graph.
|
||||
IonBuilder inlineBuilder(compartment, options, &alloc(), &graph(), constraints(),
|
||||
IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
|
||||
&inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
|
||||
loopDepth_);
|
||||
if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
|
||||
if (analysisContext && analysisContext->isExceptionPending()) {
|
||||
JitSpew(JitSpew_Abort, "Inline builder raised exception.");
|
||||
abortReason_ = AbortReason_Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inlining the callee failed. Mark the callee as uninlineable only if
|
||||
// the inlining was aborted for a non-exception reason.
|
||||
if (inlineBuilder.abortReason_ == AbortReason_Disable) {
|
||||
@ -6418,6 +6443,8 @@ IonBuilder::testSingletonProperty(JSObject *obj, PropertyName *name)
|
||||
return nullptr;
|
||||
|
||||
types::TypeObjectKey *objType = types::TypeObjectKey::get(obj);
|
||||
if (analysisContext)
|
||||
objType->ensureTrackedProperty(analysisContext, NameToId(name));
|
||||
|
||||
if (objType->unknownProperties())
|
||||
return nullptr;
|
||||
@ -6499,6 +6526,8 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr
|
||||
types::TypeObjectKey *object = types->getObject(i);
|
||||
if (!object)
|
||||
continue;
|
||||
if (analysisContext)
|
||||
object->ensureTrackedProperty(analysisContext, NameToId(name));
|
||||
|
||||
const Class *clasp = object->clasp();
|
||||
if (!ClassHasEffectlessLookup(clasp, name) || ClassHasResolveHook(compartment, clasp, name))
|
||||
@ -6706,6 +6735,8 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
|
||||
}
|
||||
|
||||
types::TypeObjectKey *staticType = types::TypeObjectKey::get(staticObject);
|
||||
if (analysisContext)
|
||||
staticType->ensureTrackedProperty(analysisContext, NameToId(name));
|
||||
|
||||
if (staticType->unknownProperties()) {
|
||||
*psucceeded = false;
|
||||
@ -6724,7 +6755,7 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *types = bytecodeTypes(pc);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), staticType,
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), staticType,
|
||||
name, types, /* updateObserved = */ true);
|
||||
|
||||
JSObject *singleton = types->getSingleton();
|
||||
@ -7540,7 +7571,8 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
|
||||
// Emit GetElementCache.
|
||||
|
||||
types::TemporaryTypeSet *types = bytecodeTypes(pc);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, types);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
|
||||
nullptr, types);
|
||||
|
||||
// Always add a barrier if the index might be a string or symbol, so that
|
||||
// the cache can attach stubs for particular properties.
|
||||
@ -7588,7 +7620,8 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
|
||||
AddObjectsForPropertyRead(obj, nullptr, types);
|
||||
}
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, types);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
|
||||
nullptr, types);
|
||||
bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
|
||||
|
||||
// Reads which are on holes in the object do not have to bail out if
|
||||
@ -8904,7 +8937,8 @@ IonBuilder::jsop_getprop(PropertyName *name)
|
||||
if (!getPropTryArgumentsCallee(&emitted, obj, name) || emitted)
|
||||
return emitted;
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, name, types);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, name, types);
|
||||
|
||||
// Always use a call if we are performing analysis and
|
||||
// not actually emitting code, to simplify later analysis. Also skip deeper
|
||||
@ -9586,7 +9620,8 @@ IonBuilder::getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *na
|
||||
|
||||
// Passing the inner object to GetProperty IC is safe, see the
|
||||
// needsOuterizedThisObject check in IsCacheableGetPropCallNative.
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), inner, name, types);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
inner, name, types);
|
||||
if (!getPropTryCache(emitted, inner, name, barrier, types) || *emitted)
|
||||
return *emitted;
|
||||
|
||||
|
@ -214,7 +214,7 @@ class IonBuilder
|
||||
static int CmpSuccessors(const void *a, const void *b);
|
||||
|
||||
public:
|
||||
IonBuilder(CompileCompartment *comp,
|
||||
IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
|
||||
const JitCompileOptions &options, TempAllocator *temp,
|
||||
MIRGraph *graph, types::CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, CompileInfo *info,
|
||||
@ -865,6 +865,7 @@ class IonBuilder
|
||||
private:
|
||||
bool init();
|
||||
|
||||
JSContext *analysisContext;
|
||||
BaselineFrameInspector *baselineFrame_;
|
||||
|
||||
// Constraints for recording dependencies on type information.
|
||||
|
@ -433,7 +433,8 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
||||
bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), types::OBJECT_FLAG_NON_PACKED);
|
||||
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, returnTypes);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, nullptr, returnTypes);
|
||||
if (barrier != BarrierKind::NoBarrier)
|
||||
returnType = MIRType_Value;
|
||||
|
||||
|
@ -3667,7 +3667,8 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
}
|
||||
|
||||
BarrierKind
|
||||
jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
types::TypeObjectKey *object, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed, bool updateObserved)
|
||||
{
|
||||
@ -3687,6 +3688,8 @@ jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
break;
|
||||
|
||||
types::TypeObjectKey *typeObj = types::TypeObjectKey::get(obj);
|
||||
if (propertycx)
|
||||
typeObj->ensureTrackedProperty(propertycx, NameToId(name));
|
||||
|
||||
if (!typeObj->unknownProperties()) {
|
||||
types::HeapTypeSetKey property = typeObj->property(NameToId(name));
|
||||
@ -3712,7 +3715,8 @@ jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
}
|
||||
|
||||
BarrierKind
|
||||
jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
{
|
||||
@ -3729,7 +3733,7 @@ jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObjectKey *object = types->getObject(i);
|
||||
if (object) {
|
||||
BarrierKind kind = PropertyReadNeedsTypeBarrier(constraints, object, name,
|
||||
BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, object, name,
|
||||
observed, updateObserved);
|
||||
if (kind == BarrierKind::TypeSet)
|
||||
return BarrierKind::TypeSet;
|
||||
|
@ -11772,10 +11772,12 @@ bool ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
|
||||
MDefinition *obj);
|
||||
MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
types::TypeObjectKey *object, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed, bool updateObserved);
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
|
@ -1091,6 +1091,21 @@ TypeObjectKey::property(jsid id)
|
||||
return property;
|
||||
}
|
||||
|
||||
void
|
||||
TypeObjectKey::ensureTrackedProperty(JSContext *cx, jsid id)
|
||||
{
|
||||
// If we are accessing a lazily defined property which actually exists in
|
||||
// the VM and has not been instantiated yet, instantiate it now if we are
|
||||
// on the main thread and able to do so.
|
||||
if (!JSID_IS_VOID(id) && !JSID_IS_EMPTY(id)) {
|
||||
JS_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
if (JSObject *obj = singleton()) {
|
||||
if (obj->isNative() && obj->nativeLookupPure(id))
|
||||
EnsureTrackPropertyTypes(cx, obj, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HeapTypeSetKey::instantiate(JSContext *cx)
|
||||
{
|
||||
|
@ -1465,6 +1465,7 @@ struct TypeObjectKey
|
||||
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
|
||||
HeapTypeSetKey property(jsid id);
|
||||
void ensureTrackedProperty(JSContext *cx, jsid id);
|
||||
|
||||
TypeObject *maybeType();
|
||||
};
|
||||
|
@ -106,6 +106,12 @@ bool
|
||||
js::DecompressString(const unsigned char *inp, size_t inplen, unsigned char *out, size_t outlen)
|
||||
{
|
||||
JS_ASSERT(inplen <= UINT32_MAX);
|
||||
|
||||
// Mark the memory we pass to zlib as initialized for MSan.
|
||||
#ifdef MOZ_MSAN
|
||||
__msan_unpoison(out, outlen);
|
||||
#endif
|
||||
|
||||
z_stream zs;
|
||||
zs.zalloc = zlib_alloc;
|
||||
zs.zfree = zlib_free;
|
||||
|
@ -2235,7 +2235,7 @@ nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
|
||||
clipRect = frame->GetPaddingRect() - frame->GetPosition() + aItem->ToReferenceFrame();
|
||||
break;
|
||||
case NS_STYLE_BG_CLIP_CONTENT:
|
||||
clipRect = frame->GetContentRect() - frame->GetPosition() + aItem->ToReferenceFrame();
|
||||
clipRect = frame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Unknown clip type");
|
||||
|
@ -23,7 +23,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(needs copy support) b2
|
||||
[test_bug477531.html]
|
||||
[test_bug477700.html]
|
||||
[test_bug478219.xhtml]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795)
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795)
|
||||
[test_bug534785.html]
|
||||
[test_bug542914.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
@ -31,7 +31,7 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_bug562447.html]
|
||||
[test_bug563642.html]
|
||||
[test_bug564115.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(times out on window.open and focus event) b2g-desktop(times out on window.open and focus event)
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(times out on window.open and focus event) b2g-desktop(times out on window.open and focus event)
|
||||
[test_bug571352.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(shift-click multi-select not working?) b2g-debug(shift-click multi-select not working?) b2g-desktop(shift-click multi-select not working?)
|
||||
[test_bug572406.html]
|
||||
|
@ -215,7 +215,7 @@ public:
|
||||
friend struct AutoApplyUserSelectStyle;
|
||||
struct MOZ_STACK_CLASS AutoApplyUserSelectStyle
|
||||
{
|
||||
AutoApplyUserSelectStyle(Selection* aSelection
|
||||
explicit AutoApplyUserSelectStyle(Selection* aSelection
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mSavedValue(aSelection->mApplyUserSelectStyle)
|
||||
{
|
||||
|
@ -5873,7 +5873,7 @@ nsresult
|
||||
nsFrame::GetPointFromOffset(int32_t inOffset, nsPoint* outPoint)
|
||||
{
|
||||
NS_PRECONDITION(outPoint != nullptr, "Null parameter");
|
||||
nsRect contentRect = GetContentRect() - GetPosition();
|
||||
nsRect contentRect = GetContentRectRelativeToSelf();
|
||||
nsPoint pt = contentRect.TopLeft();
|
||||
if (mContent)
|
||||
{
|
||||
|
@ -241,6 +241,8 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
// FIXME taken from nsImageFrame, but then had splittable frame stuff
|
||||
// removed. That needs to be fixed.
|
||||
// XXXdholbert As in nsImageFrame, this function's clients should probably
|
||||
// just be calling GetContentRectRelativeToSelf().
|
||||
nsRect
|
||||
nsHTMLCanvasFrame::GetInnerArea() const
|
||||
{
|
||||
@ -259,7 +261,7 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
const ContainerLayerParameters& aContainerParameters)
|
||||
{
|
||||
nsRect area = GetContentRect() - GetPosition() + aItem->ToReferenceFrame();
|
||||
nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
|
||||
HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
|
||||
nsIntSize canvasSize = GetCanvasSize();
|
||||
|
||||
|
@ -812,10 +812,12 @@ nsImageFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
||||
aPadding);
|
||||
}
|
||||
|
||||
// XXXdholbert This function's clients should probably just be calling
|
||||
// GetContentRectRelativeToSelf() directly.
|
||||
nsRect
|
||||
nsImageFrame::GetInnerArea() const
|
||||
{
|
||||
return GetContentRect() - GetPosition();
|
||||
return GetContentRectRelativeToSelf();
|
||||
}
|
||||
|
||||
Element*
|
||||
|
@ -174,7 +174,7 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
const ContainerLayerParameters& aContainerParameters)
|
||||
{
|
||||
nsRect area = GetContentRect() - GetPosition() + aItem->ToReferenceFrame();
|
||||
nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
|
||||
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
nsIntSize videoSize;
|
||||
if (NS_FAILED(element->GetVideoSize(&videoSize)) || area.IsEmpty()) {
|
||||
@ -393,7 +393,7 @@ public:
|
||||
{
|
||||
*aSnap = true;
|
||||
nsIFrame* f = Frame();
|
||||
return f->GetContentRect() - f->GetPosition() + ToReferenceFrame();
|
||||
return f->GetContentRectRelativeToSelf() + ToReferenceFrame();
|
||||
}
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
@ -53,7 +53,7 @@ GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuil
|
||||
// we need to be careful here to ensure that we call ToReferenceFrame
|
||||
// on aContainerFrame and not its parent.
|
||||
nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) +
|
||||
(aContainerFrame->GetContentRect().TopLeft() - aContainerFrame->GetPosition());
|
||||
aContainerFrame->GetContentRectRelativeToSelf().TopLeft();
|
||||
|
||||
return frameOffset.ToNearestPixels(auPerDevPixel);
|
||||
}
|
||||
|
@ -55,18 +55,11 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::ScrollbarsSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
if (!gStyleCache->mScrollbarsSheet) {
|
||||
nsCOMPtr<nsIURI> sheetURI;
|
||||
NS_NewURI(getter_AddRefs(sheetURI),
|
||||
NS_LITERAL_CSTRING("chrome://global/skin/scrollbars.css"));
|
||||
|
||||
// Scrollbars don't need access to unsafe rules
|
||||
if (sheetURI)
|
||||
LoadSheet(sheetURI, gStyleCache->mScrollbarsSheet, false);
|
||||
NS_ASSERTION(gStyleCache->mScrollbarsSheet, "Could not load scrollbars.css.");
|
||||
LoadSheetURL("chrome://global/skin/scrollbars.css",
|
||||
gStyleCache->mScrollbarsSheet, false);
|
||||
}
|
||||
|
||||
return gStyleCache->mScrollbarsSheet;
|
||||
@ -76,19 +69,11 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::FormsSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
if (!gStyleCache->mFormsSheet) {
|
||||
nsCOMPtr<nsIURI> sheetURI;
|
||||
NS_NewURI(getter_AddRefs(sheetURI),
|
||||
NS_LITERAL_CSTRING("resource://gre-resources/forms.css"));
|
||||
|
||||
// forms.css needs access to unsafe rules
|
||||
if (sheetURI)
|
||||
LoadSheet(sheetURI, gStyleCache->mFormsSheet, true);
|
||||
|
||||
NS_ASSERTION(gStyleCache->mFormsSheet, "Could not load forms.css.");
|
||||
LoadSheetURL("resource://gre-resources/forms.css",
|
||||
gStyleCache->mFormsSheet, true);
|
||||
}
|
||||
|
||||
return gStyleCache->mFormsSheet;
|
||||
@ -98,22 +83,14 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::NumberControlSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
if (!sNumberControlEnabled) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gStyleCache->mNumberControlSheet) {
|
||||
nsCOMPtr<nsIURI> sheetURI;
|
||||
NS_NewURI(getter_AddRefs(sheetURI),
|
||||
NS_LITERAL_CSTRING("resource://gre-resources/number-control.css"));
|
||||
|
||||
if (sheetURI)
|
||||
LoadSheet(sheetURI, gStyleCache->mNumberControlSheet, false);
|
||||
|
||||
NS_ASSERTION(gStyleCache->mNumberControlSheet, "Could not load number-control.css");
|
||||
LoadSheetURL("resource://gre-resources/number-control.css",
|
||||
gStyleCache->mNumberControlSheet, false);
|
||||
}
|
||||
|
||||
return gStyleCache->mNumberControlSheet;
|
||||
@ -123,9 +100,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::UserContentSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mUserContentSheet;
|
||||
}
|
||||
|
||||
@ -133,9 +107,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::UserChromeSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mUserChromeSheet;
|
||||
}
|
||||
|
||||
@ -143,9 +114,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::UASheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mUASheet;
|
||||
}
|
||||
|
||||
@ -153,9 +121,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::HTMLSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mHTMLSheet;
|
||||
}
|
||||
|
||||
@ -163,9 +128,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::MinimalXULSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mMinimalXULSheet;
|
||||
}
|
||||
|
||||
@ -173,9 +135,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::XULSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mXULSheet;
|
||||
}
|
||||
|
||||
@ -183,9 +142,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::QuirkSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mQuirkSheet;
|
||||
}
|
||||
|
||||
@ -193,9 +149,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::FullScreenOverrideSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mFullScreenOverrideSheet;
|
||||
}
|
||||
|
||||
@ -203,9 +156,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::SVGSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mSVGSheet;
|
||||
}
|
||||
|
||||
@ -213,16 +163,10 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::MathMLSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
if (!gStyleCache->mMathMLSheet) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/mathml.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, gStyleCache->mMathMLSheet, true);
|
||||
}
|
||||
NS_ASSERTION(gStyleCache->mMathMLSheet, "Could not load mathml.css");
|
||||
LoadSheetURL("resource://gre-resources/mathml.css",
|
||||
gStyleCache->mMathMLSheet, true);
|
||||
}
|
||||
|
||||
return gStyleCache->mMathMLSheet;
|
||||
@ -232,8 +176,6 @@ CSSStyleSheet*
|
||||
nsLayoutStylesheetCache::CounterStylesSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nullptr;
|
||||
|
||||
return gStyleCache->mCounterStylesSheet;
|
||||
}
|
||||
@ -265,22 +207,20 @@ nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
|
||||
|
||||
#define MEASURE(s) n += s ? s->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||
|
||||
MEASURE(mScrollbarsSheet);
|
||||
MEASURE(mFormsSheet);
|
||||
MEASURE(mNumberControlSheet);
|
||||
MEASURE(mUserContentSheet);
|
||||
MEASURE(mUserChromeSheet);
|
||||
MEASURE(mUASheet);
|
||||
MEASURE(mHTMLSheet);
|
||||
MEASURE(mMinimalXULSheet);
|
||||
MEASURE(mXULSheet);
|
||||
MEASURE(mQuirkSheet);
|
||||
MEASURE(mFullScreenOverrideSheet);
|
||||
MEASURE(mSVGSheet);
|
||||
MEASURE(mCounterStylesSheet);
|
||||
if (mMathMLSheet) {
|
||||
MEASURE(mMathMLSheet);
|
||||
}
|
||||
MEASURE(mFormsSheet);
|
||||
MEASURE(mFullScreenOverrideSheet);
|
||||
MEASURE(mHTMLSheet);
|
||||
MEASURE(mMathMLSheet);
|
||||
MEASURE(mMinimalXULSheet);
|
||||
MEASURE(mNumberControlSheet);
|
||||
MEASURE(mQuirkSheet);
|
||||
MEASURE(mSVGSheet);
|
||||
MEASURE(mScrollbarsSheet);
|
||||
MEASURE(mUASheet);
|
||||
MEASURE(mUserChromeSheet);
|
||||
MEASURE(mUserContentSheet);
|
||||
MEASURE(mXULSheet);
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it is
|
||||
// worthwhile:
|
||||
@ -306,57 +246,25 @@ nsLayoutStylesheetCache::nsLayoutStylesheetCache()
|
||||
|
||||
// And make sure that we load our UA sheets. No need to do this
|
||||
// per-profile, since they're profile-invariant.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/ua.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mUASheet, true);
|
||||
}
|
||||
NS_ASSERTION(mUASheet, "Could not load ua.css");
|
||||
LoadSheetURL("resource://gre-resources/counterstyles.css",
|
||||
mCounterStylesSheet, true);
|
||||
LoadSheetURL("resource://gre-resources/full-screen-override.css",
|
||||
mFullScreenOverrideSheet, true);
|
||||
LoadSheetURL("resource://gre-resources/html.css",
|
||||
mHTMLSheet, true);
|
||||
LoadSheetURL("chrome://global/content/minimal-xul.css",
|
||||
mMinimalXULSheet, true);
|
||||
LoadSheetURL("resource://gre-resources/quirk.css",
|
||||
mQuirkSheet, true);
|
||||
LoadSheetURL("resource://gre/res/svg.css",
|
||||
mSVGSheet, true);
|
||||
LoadSheetURL("resource://gre-resources/ua.css",
|
||||
mUASheet, true);
|
||||
LoadSheetURL("chrome://global/content/xul.css",
|
||||
mXULSheet, true);
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/html.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mHTMLSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mHTMLSheet, "Could not load xul.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "chrome://global/content/minimal-xul.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mMinimalXULSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mMinimalXULSheet, "Could not load minimal-xul.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "chrome://global/content/xul.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mXULSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mXULSheet, "Could not load xul.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/quirk.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mQuirkSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mQuirkSheet, "Could not load quirk.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/full-screen-override.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mFullScreenOverrideSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mFullScreenOverrideSheet, "Could not load full-screen-override.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre/res/svg.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mSVGSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mSVGSheet, "Could not load svg.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/counterstyles.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mCounterStylesSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mCounterStylesSheet, "Could not load counterstyles.css");
|
||||
|
||||
// mMathMLSheet is created on-demand since its use is rare. This helps save
|
||||
// memory for Firefox OS apps.
|
||||
// The remaining sheets are created on-demand since their use is rarer. This
|
||||
// helps save memory for Firefox OS apps.
|
||||
}
|
||||
|
||||
nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
|
||||
@ -374,10 +282,11 @@ nsLayoutStylesheetCache::InitMemoryReporter()
|
||||
void
|
||||
nsLayoutStylesheetCache::EnsureGlobal()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (gStyleCache) return;
|
||||
|
||||
gStyleCache = new nsLayoutStylesheetCache();
|
||||
if (!gStyleCache) return;
|
||||
|
||||
gStyleCache->InitMemoryReporter();
|
||||
|
||||
@ -415,6 +324,19 @@ nsLayoutStylesheetCache::InitFromProfile()
|
||||
LoadSheetFile(chromeFile, mUserChromeSheet);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,
|
||||
nsRefPtr<CSSStyleSheet>& aSheet,
|
||||
bool aEnableUnsafeRules)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), aURL);
|
||||
LoadSheet(uri, aSheet, aEnableUnsafeRules);
|
||||
if (!aSheet) {
|
||||
NS_ERROR(nsPrintfCString("Could not load %s", aURL).get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile, nsRefPtr<CSSStyleSheet>& aSheet)
|
||||
{
|
||||
|
@ -60,6 +60,9 @@ private:
|
||||
static void EnsureGlobal();
|
||||
void InitFromProfile();
|
||||
void InitMemoryReporter();
|
||||
static void LoadSheetURL(const char* aURL,
|
||||
nsRefPtr<mozilla::CSSStyleSheet>& aSheet,
|
||||
bool aEnableUnsafeRules);
|
||||
static void LoadSheetFile(nsIFile* aFile,
|
||||
nsRefPtr<mozilla::CSSStyleSheet>& aSheet);
|
||||
static void LoadSheet(nsIURI* aURI, nsRefPtr<mozilla::CSSStyleSheet>& aSheet,
|
||||
@ -67,20 +70,20 @@ private:
|
||||
|
||||
static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache;
|
||||
static mozilla::css::Loader* gCSSLoader;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mScrollbarsSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mFormsSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mNumberControlSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mUserContentSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mUserChromeSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mUASheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mHTMLSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mMinimalXULSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mXULSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mQuirkSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mFullScreenOverrideSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mSVGSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mMathMLSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mCounterStylesSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mFormsSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mFullScreenOverrideSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mHTMLSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mMathMLSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mMinimalXULSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mNumberControlSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mQuirkSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mSVGSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mScrollbarsSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mUASheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mUserChromeSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mUserContentSheet;
|
||||
nsRefPtr<mozilla::CSSStyleSheet> mXULSheet;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -148,7 +148,7 @@ protected:
|
||||
|
||||
struct nsSVGFrameReferenceFromProperty
|
||||
{
|
||||
nsSVGFrameReferenceFromProperty(nsIFrame* aFrame)
|
||||
explicit nsSVGFrameReferenceFromProperty(nsIFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mFramePresShell(aFrame->PresContext()->PresShell())
|
||||
{}
|
||||
|
@ -724,7 +724,7 @@ nsTableCellFrame::GetCellBaseline() const
|
||||
nscoord result;
|
||||
if (nsLayoutUtils::GetFirstLineBaseline(GetWritingMode(), inner, &result))
|
||||
return result + borderPadding;
|
||||
return inner->GetContentRect().YMost() - inner->GetPosition().y +
|
||||
return inner->GetContentRectRelativeToSelf().YMost() +
|
||||
borderPadding;
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,10 @@ sys.path.insert(0, SCRIPT_DIRECTORY)
|
||||
from automation import Automation
|
||||
from automationutils import (
|
||||
addCommonOptions,
|
||||
getDebuggerInfo,
|
||||
isURL,
|
||||
processLeakLog
|
||||
)
|
||||
import mozdebug
|
||||
import mozprofile
|
||||
|
||||
def categoriesToRegex(categoryList):
|
||||
@ -320,7 +320,7 @@ class RefTest(object):
|
||||
return int(any(t.retcode != 0 for t in threads))
|
||||
|
||||
def runSerialTests(self, testPath, options, cmdlineArgs = None):
|
||||
debuggerInfo = getDebuggerInfo(self.oldcwd, options.debugger, options.debuggerArgs,
|
||||
debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs,
|
||||
options.debuggerInteractive);
|
||||
|
||||
profileDir = None
|
||||
|
@ -54,6 +54,29 @@ __asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
||||
#define MOZ_MAKE_MEM_DEFINED(addr, size) \
|
||||
__asan_unpoison_memory_region((addr), (size))
|
||||
}
|
||||
#elif defined(MOZ_MSAN)
|
||||
#include <stddef.h>
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
extern "C" {
|
||||
/* These definitions are usually provided through the
|
||||
* sanitizer/msan_interface.h header installed by MSan.
|
||||
*/
|
||||
void MOZ_EXPORT
|
||||
__msan_poison(void const volatile *addr, size_t size);
|
||||
void MOZ_EXPORT
|
||||
__msan_unpoison(void const volatile *addr, size_t size);
|
||||
|
||||
#define MOZ_MAKE_MEM_NOACCESS(addr, size) \
|
||||
__msan_poison((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
|
||||
__msan_poison((addr), (size))
|
||||
|
||||
#define MOZ_MAKE_MEM_DEFINED(addr, size) \
|
||||
__msan_unpoison((addr), (size))
|
||||
}
|
||||
#elif defined(MOZ_VALGRIND)
|
||||
#define MOZ_MAKE_MEM_NOACCESS(addr, size) \
|
||||
VALGRIND_MAKE_MEM_NOACCESS((addr), (size))
|
||||
|
@ -12,6 +12,7 @@ import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSContainer;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -227,12 +228,18 @@ public final class EventDispatcher {
|
||||
@Deprecated
|
||||
private static void sendResponseHelper(String status, JSONObject message, Object response) {
|
||||
try {
|
||||
final String topic = message.getString("type") + ":Response";
|
||||
final JSONObject wrapper = new JSONObject();
|
||||
wrapper.put(GUID, message.getString(GUID));
|
||||
wrapper.put("status", status);
|
||||
wrapper.put("response", response);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
|
||||
message.getString("type") + ":Response", wrapper.toString()));
|
||||
|
||||
if (ThreadUtils.isOnGeckoThread()) {
|
||||
GeckoAppShell.notifyGeckoObservers(topic, wrapper.toString());
|
||||
} else {
|
||||
GeckoAppShell.sendEventToGecko(
|
||||
GeckoEvent.createBroadcastEvent(topic, wrapper.toString()));
|
||||
}
|
||||
} catch (final JSONException e) {
|
||||
Log.e(LOGTAG, "Unable to send response", e);
|
||||
}
|
||||
@ -265,12 +272,18 @@ public final class EventDispatcher {
|
||||
sent = true;
|
||||
|
||||
try {
|
||||
final String topic = type + ":Response";
|
||||
final JSONObject wrapper = new JSONObject();
|
||||
wrapper.put(GUID, guid);
|
||||
wrapper.put("status", status);
|
||||
wrapper.put("response", response);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(type + ":Response",
|
||||
wrapper.toString()));
|
||||
|
||||
if (ThreadUtils.isOnGeckoThread()) {
|
||||
GeckoAppShell.notifyGeckoObservers(topic, wrapper.toString());
|
||||
} else {
|
||||
GeckoAppShell.sendEventToGecko(
|
||||
GeckoEvent.createBroadcastEvent(topic, wrapper.toString()));
|
||||
}
|
||||
} catch (final JSONException e) {
|
||||
Log.e(LOGTAG, "Unable to send response for: " + type, e);
|
||||
}
|
||||
|
@ -298,7 +298,12 @@ public class GeckoAppShell
|
||||
private static LayerView sLayerView;
|
||||
|
||||
public static void setLayerView(LayerView lv) {
|
||||
if (sLayerView == lv) {
|
||||
return;
|
||||
}
|
||||
sLayerView = lv;
|
||||
// Install new Gecko-to-Java editable listener.
|
||||
editableListener = new GeckoEditable();
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
@ -349,13 +354,6 @@ public class GeckoAppShell
|
||||
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
|
||||
combinedArgs += " -width " + metrics.widthPixels + " -height " + metrics.heightPixels;
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
geckoLoaded();
|
||||
}
|
||||
});
|
||||
|
||||
if (!AppConstants.MOZILLA_OFFICIAL) {
|
||||
Log.d(LOGTAG, "GeckoLoader.nativeRun " + combinedArgs);
|
||||
}
|
||||
@ -366,13 +364,6 @@ public class GeckoAppShell
|
||||
Looper.myQueue().removeIdleHandler(idleHandler);
|
||||
}
|
||||
|
||||
// Called on the UI thread after Gecko loads.
|
||||
private static void geckoLoaded() {
|
||||
GeckoEditable editable = new GeckoEditable();
|
||||
// install the gecko => editable listener
|
||||
editableListener = editable;
|
||||
}
|
||||
|
||||
static void sendPendingEventsToGecko() {
|
||||
try {
|
||||
while (!PENDING_EVENTS.isEmpty()) {
|
||||
@ -447,6 +438,9 @@ public class GeckoAppShell
|
||||
// Tell the Gecko event loop that an event is available.
|
||||
public static native void notifyGeckoOfEvent(GeckoEvent event);
|
||||
|
||||
// Synchronously notify a Gecko observer; must be called from Gecko thread.
|
||||
public static native void notifyGeckoObservers(String subject, String data);
|
||||
|
||||
/*
|
||||
* The Gecko-side API: API methods that Gecko calls
|
||||
*/
|
||||
|
@ -182,6 +182,13 @@ public final class ThreadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isOnGeckoThread() {
|
||||
if (sGeckoThread != null) {
|
||||
return isOnThread(sGeckoThread);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isOnUiThread() {
|
||||
return isOnThread(getUiThread());
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ struct PRFileDesc;
|
||||
interface nsIUTF8StringEnumerator;
|
||||
interface nsIInputStream;
|
||||
interface nsIFile;
|
||||
interface nsICertificatePrincipal;
|
||||
interface nsIX509Cert;
|
||||
|
||||
[scriptable, uuid(fad6f72f-13d8-4e26-9173-53007a4afe71)]
|
||||
interface nsIZipEntry : nsISupports
|
||||
@ -63,7 +63,7 @@ interface nsIZipEntry : nsISupports
|
||||
readonly attribute unsigned long permissions;
|
||||
};
|
||||
|
||||
[scriptable, uuid(38d6d07a-8a58-4fe7-be8b-ef6472fa83ff)]
|
||||
[scriptable, uuid(894c8dc0-37c8-11e4-916c-0800200c9a66)]
|
||||
interface nsIZipReader : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -190,8 +190,8 @@ interface nsIZipReader : nsISupports
|
||||
* stored in the jar, verifyExternalFile (not yet implemented) must
|
||||
* be called before getPrincipal.
|
||||
*/
|
||||
nsICertificatePrincipal getCertificatePrincipal(in AUTF8String aEntryName);
|
||||
|
||||
nsIX509Cert getSigningCert(in AUTF8String aEntryName);
|
||||
|
||||
readonly attribute uint32_t manifestEntriesCount;
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "nsJARInputStream.h"
|
||||
#include "nsJAR.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsICertificatePrincipal.h"
|
||||
#include "nsIX509Cert.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsIDataSignatureVerifier.h"
|
||||
@ -323,12 +323,13 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJAR::GetCertificatePrincipal(const nsACString &aFilename, nsICertificatePrincipal** aPrincipal)
|
||||
nsJAR::GetSigningCert(const nsACString& aFilename, nsIX509Cert** aSigningCert)
|
||||
{
|
||||
//-- Parameter check
|
||||
if (!aPrincipal)
|
||||
if (!aSigningCert) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aPrincipal = nullptr;
|
||||
}
|
||||
*aSigningCert = nullptr;
|
||||
|
||||
// Don't check signatures in the omnijar - this is only
|
||||
// interesting for extensions/XPIs.
|
||||
@ -366,12 +367,11 @@ nsJAR::GetCertificatePrincipal(const nsACString &aFilename, nsICertificatePrinci
|
||||
else // User wants identity of signer w/o verifying any entries
|
||||
requestedStatus = mGlobalStatus;
|
||||
|
||||
if (requestedStatus != JAR_VALID_MANIFEST)
|
||||
if (requestedStatus != JAR_VALID_MANIFEST) {
|
||||
ReportError(aFilename, requestedStatus);
|
||||
else // Valid signature
|
||||
{
|
||||
*aPrincipal = mPrincipal;
|
||||
NS_IF_ADDREF(*aPrincipal);
|
||||
} else { // Valid signature
|
||||
*aSigningCert = mSigningCert;
|
||||
NS_IF_ADDREF(*aSigningCert);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -589,14 +589,15 @@ nsJAR::ParseManifest()
|
||||
//-- Verify that the signature file is a valid signature of the SF file
|
||||
int32_t verifyError;
|
||||
rv = verifier->VerifySignature(sigBuffer, sigLen, manifestBuffer, manifestLen,
|
||||
&verifyError, getter_AddRefs(mPrincipal));
|
||||
&verifyError, getter_AddRefs(mSigningCert));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (mPrincipal && verifyError == nsIDataSignatureVerifier::VERIFY_OK)
|
||||
if (mSigningCert && verifyError == nsIDataSignatureVerifier::VERIFY_OK) {
|
||||
mGlobalStatus = JAR_VALID_MANIFEST;
|
||||
else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER)
|
||||
} else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER) {
|
||||
mGlobalStatus = JAR_INVALID_UNKNOWN_CA;
|
||||
else
|
||||
} else {
|
||||
mGlobalStatus = JAR_INVALID_SIG;
|
||||
}
|
||||
|
||||
//-- Parse the SF file. If the verification above failed, principal
|
||||
// is null, and ParseOneFile will mark the relevant entries as invalid.
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsICertificatePrincipal;
|
||||
class nsIX509Cert;
|
||||
class nsIInputStream;
|
||||
class nsJARManifestItem;
|
||||
class nsZipReaderCache;
|
||||
@ -106,7 +106,7 @@ class nsJAR MOZ_FINAL : public nsIZipReader
|
||||
nsRefPtr<nsZipArchive> mZip; // The underlying zip archive
|
||||
ManifestDataHashtable mManifestData; // Stores metadata for each entry
|
||||
bool mParsedManifest; // True if manifest has been parsed
|
||||
nsCOMPtr<nsICertificatePrincipal> mPrincipal; // The entity which signed this file
|
||||
nsCOMPtr<nsIX509Cert> mSigningCert; // The entity which signed this file
|
||||
int16_t mGlobalStatus; // Global signature verification status
|
||||
PRIntervalTime mReleaseTime; // used by nsZipReaderCache for flushing entries
|
||||
nsZipReaderCache* mCache; // if cached, this points to the cache it's contained in
|
||||
|
@ -45,14 +45,15 @@ function openZip(path) {
|
||||
|
||||
// Gets the pretty name from the signing cert or null if the zip is unsigned.
|
||||
function getSigner(zip) {
|
||||
var principal = zip.getCertificatePrincipal(null);
|
||||
if (principal && principal.hasCertificate)
|
||||
return principal.prettyName;
|
||||
var signingCert = zip.getSigningCert(null);
|
||||
if (signingCert) {
|
||||
return signingCert.organization;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function verifySigning(zip) {
|
||||
var principal = zip.getCertificatePrincipal(null);
|
||||
var signingCert = zip.getSigningCert(null);
|
||||
var count = 0;
|
||||
var entries = zip.findEntries(null);
|
||||
while (entries.hasMore()) {
|
||||
@ -64,9 +65,10 @@ function verifySigning(zip) {
|
||||
if (entry.substr(-1) == "/")
|
||||
continue;
|
||||
count++;
|
||||
var entryPrincipal = zip.getCertificatePrincipal(entry);
|
||||
if (!entryPrincipal || !principal.equals(entryPrincipal))
|
||||
var entryCert = zip.getSigningCert(entry);
|
||||
if (!entryCert || !signingCert.equals(entryCert)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return zip.manifestEntriesCount == count;
|
||||
}
|
||||
|
@ -107,6 +107,9 @@ pref("offline-apps.quota.warn", 51200);
|
||||
// cache compression turned off for now - see bug #715198
|
||||
pref("browser.cache.compression_level", 0);
|
||||
|
||||
// Whether or not MozAbortablePromise is enabled.
|
||||
pref("dom.abortablepromise.enabled", false);
|
||||
|
||||
// Whether or not testing features are enabled.
|
||||
pref("dom.quotaManager.testing", false);
|
||||
|
||||
|
@ -362,6 +362,25 @@ Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv * arg0, jclass ar
|
||||
|
||||
#ifdef JNI_STUBS
|
||||
|
||||
typedef void (*Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers_t)(JNIEnv *, jclass, jstring, jstring);
|
||||
static Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers_t f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers;
|
||||
extern "C" NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers(JNIEnv * arg0, jclass arg1, jstring arg2, jstring arg3) {
|
||||
if (!f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers) {
|
||||
arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
|
||||
"JNI Function called before it was loaded");
|
||||
return ;
|
||||
}
|
||||
f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JNI_BINDINGS
|
||||
xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers", &f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers);
|
||||
#endif
|
||||
|
||||
#ifdef JNI_STUBS
|
||||
|
||||
typedef jlong (*Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback_t)(JNIEnv *, jclass);
|
||||
static Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback_t f_Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback;
|
||||
extern "C" NS_EXPORT jlong JNICALL
|
||||
|
@ -824,7 +824,7 @@ class DebugProgram(MachCommandBase):
|
||||
@CommandArgument('+debugger', default=None, type=str,
|
||||
help='Name of debugger to launch')
|
||||
@CommandArgument('+debugparams', default=None, metavar='params', type=str,
|
||||
help='Command-line arguments to pass to GDB or LLDB itself; split as the Bourne shell would.')
|
||||
help='Command-line arguments to pass to the debugger itself; split as the Bourne shell would.')
|
||||
# Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
|
||||
# segfaults induced by the slow-script-detecting logic for Ion/Odin JITted
|
||||
# code. If we don't pass this, the user will need to periodically type
|
||||
@ -833,26 +833,7 @@ class DebugProgram(MachCommandBase):
|
||||
@CommandArgument('+slowscript', action='store_true',
|
||||
help='Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; when not set, recoverable but misleading SIGSEGV instances may occur in Ion/Odin JIT code')
|
||||
def debug(self, params, remote, background, debugger, debugparams, slowscript):
|
||||
import which
|
||||
if debugger:
|
||||
try:
|
||||
debugger = which.which(debugger)
|
||||
except Exception as e:
|
||||
print("You don't have %s in your PATH" % (debugger))
|
||||
print(e)
|
||||
return 1
|
||||
else:
|
||||
try:
|
||||
debugger = which.which('gdb')
|
||||
except Exception:
|
||||
try:
|
||||
debugger = which.which('lldb')
|
||||
except Exception as e:
|
||||
print("You don't have gdb or lldb in your PATH")
|
||||
print(e)
|
||||
return 1
|
||||
args = [debugger]
|
||||
extra_env = { 'MOZ_CRASHREPORTER_DISABLE' : '1' }
|
||||
# Parameters come from the CLI. We need to convert them before their use.
|
||||
if debugparams:
|
||||
import pymake.process
|
||||
argv, badchar = pymake.process.clinetoargv(debugparams, os.getcwd())
|
||||
@ -860,7 +841,22 @@ class DebugProgram(MachCommandBase):
|
||||
print("The +debugparams you passed require a real shell to parse them.")
|
||||
print("(We can't handle the %r character.)" % (badchar,))
|
||||
return 1
|
||||
args.extend(argv)
|
||||
debugparams = argv;
|
||||
|
||||
import mozdebug
|
||||
|
||||
if not debugger:
|
||||
# No debugger name was provided. Look for the default ones on current OS.
|
||||
debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking)
|
||||
|
||||
self.debuggerInfo = mozdebug.get_debugger_info(debugger, debugparams)
|
||||
|
||||
# We could not find the information about the desired debugger.
|
||||
if not self.debuggerInfo:
|
||||
print("Could not find a suitable debugger in your PATH.")
|
||||
return 1
|
||||
|
||||
extra_env = { 'MOZ_CRASHREPORTER_DISABLE' : '1' }
|
||||
|
||||
binpath = None
|
||||
|
||||
@ -872,17 +868,8 @@ class DebugProgram(MachCommandBase):
|
||||
print(e)
|
||||
return 1
|
||||
|
||||
# args added to separate the debugger and process arguments.
|
||||
args_separator = {
|
||||
'gdb': '--args',
|
||||
'ddd': '--args',
|
||||
'cgdb': '--args',
|
||||
'lldb': '--'
|
||||
}
|
||||
|
||||
debugger_name = os.path.basename(debugger)
|
||||
if debugger_name in args_separator:
|
||||
args.append(args_separator[debugger_name])
|
||||
# Build the list of arguments to pass to run_process
|
||||
args = [self.debuggerInfo.path] + self.debuggerInfo.args
|
||||
args.append(binpath)
|
||||
|
||||
if not remote:
|
||||
|
@ -11,7 +11,6 @@ XPIDL_SOURCES += [
|
||||
'nsIAssociatedContentSecurity.idl',
|
||||
'nsIBadCertListener2.idl',
|
||||
'nsICertificateDialogs.idl',
|
||||
'nsICertificatePrincipal.idl',
|
||||
'nsICertOverrideService.idl',
|
||||
'nsICertPickDialogs.idl',
|
||||
'nsIClientAuthDialogs.idl',
|
||||
|
@ -1,33 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/*
|
||||
* Historically, principals, certificates, and signed JARs were all linked
|
||||
* together in one big mess. When that mess was cleaned up, it turned out that
|
||||
* the principals used to store certificate information didn't overlap at all
|
||||
* with the principals used for security policy. So this interface was created
|
||||
* so that real principals wouldn't have to carry around all that baggage.
|
||||
*
|
||||
* The name here is totally a misnomer. This isn't a principal at all, and would
|
||||
* better be called nsICertificateHolder or something. But that would require
|
||||
* renaming some APIs, so let's just let this be for now.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(7cd4af5a-64d3-44a8-9700-804a42a6109a)]
|
||||
interface nsICertificatePrincipal : nsISupports
|
||||
{
|
||||
readonly attribute AUTF8String fingerprint;
|
||||
readonly attribute AUTF8String prettyName;
|
||||
readonly attribute AUTF8String subjectName;
|
||||
readonly attribute nsISupports certificate;
|
||||
readonly attribute boolean hasCertificate; // For compat; always true.
|
||||
|
||||
bool equals(in nsICertificatePrincipal aOther);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
@ -5,14 +5,13 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
// NB: This isn't actually a principal at all. The naming is just historical.
|
||||
interface nsICertificatePrincipal;
|
||||
interface nsIX509Cert;
|
||||
|
||||
/**
|
||||
* An interface for verifying that a given string of data was signed by the
|
||||
* private key matching the given public key.
|
||||
*/
|
||||
[scriptable, uuid(577f097f-15e4-4043-bc0e-6d2fadcacae2)]
|
||||
[scriptable, uuid(94066a00-37c9-11e4-916c-0800200c9a66)]
|
||||
interface nsIDataSignatureVerifier : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -32,10 +31,10 @@ interface nsIDataSignatureVerifier : nsISupports
|
||||
const long VERIFY_ERROR_UNKNOWN_ISSUER = 1;
|
||||
const long VERIFY_ERROR_OTHER = 2;
|
||||
|
||||
nsICertificatePrincipal verifySignature(in string aSignature,
|
||||
in unsigned long aSignatureLen,
|
||||
in string plaintext,
|
||||
in unsigned long plaintextLen,
|
||||
out long errorCode);
|
||||
nsIX509Cert verifySignature(in string aSignature,
|
||||
in unsigned long aSignatureLen,
|
||||
in string plaintext,
|
||||
in unsigned long plaintextLen,
|
||||
out long errorCode);
|
||||
|
||||
};
|
||||
|
@ -19,7 +19,6 @@ EXPORTS.mozilla += [
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'CryptoTask.cpp',
|
||||
'nsCertificatePrincipal.cpp',
|
||||
'nsCertOverrideService.cpp',
|
||||
'nsCertPicker.cpp',
|
||||
'nsCertVerificationThread.cpp',
|
||||
|
@ -1,67 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCertificatePrincipal.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsCertificatePrincipal, nsICertificatePrincipal)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCertificatePrincipal::GetFingerprint(nsACString& aFingerprint)
|
||||
{
|
||||
aFingerprint = mFingerprint;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCertificatePrincipal::GetSubjectName(nsACString& aSubjectName)
|
||||
{
|
||||
aSubjectName = mSubjectName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCertificatePrincipal::GetPrettyName(nsACString& aPrettyName)
|
||||
{
|
||||
aPrettyName = mPrettyName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCertificatePrincipal::GetCertificate(nsISupports** aCert)
|
||||
{
|
||||
nsCOMPtr<nsISupports> cert = mCert;
|
||||
cert.forget(aCert);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCertificatePrincipal::GetHasCertificate(bool* rv)
|
||||
{
|
||||
*rv = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCertificatePrincipal::Equals(nsICertificatePrincipal* aOther, bool* rv)
|
||||
{
|
||||
nsAutoCString str;
|
||||
aOther->GetFingerprint(str);
|
||||
if (!str.Equals(mFingerprint)) {
|
||||
*rv = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If either subject name is empty, just let the result stand, but if they're
|
||||
// both non-empty, only claim equality if they're equal.
|
||||
if (!mSubjectName.IsEmpty()) {
|
||||
// Check the other principal's subject name
|
||||
aOther->GetSubjectName(str);
|
||||
*rv = str.Equals(mSubjectName) || str.IsEmpty();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*rv = true;
|
||||
return NS_OK;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __NS_CERTIFICATEPRINCIPAL_H
|
||||
#define __NS_CERTIFICATEPRINCIPAL_H
|
||||
|
||||
#include "nsICertificatePrincipal.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsCertificatePrincipal : public nsICertificatePrincipal
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICERTIFICATEPRINCIPAL
|
||||
|
||||
nsCertificatePrincipal(const nsACString& aFingerprint,
|
||||
const nsACString& aSubjectName,
|
||||
const nsACString& aPrettyName,
|
||||
nsISupports* aCert)
|
||||
: mFingerprint(aFingerprint)
|
||||
, mSubjectName(aSubjectName)
|
||||
, mPrettyName(aPrettyName)
|
||||
, mCert(aCert)
|
||||
{}
|
||||
|
||||
protected:
|
||||
virtual ~nsCertificatePrincipal() {}
|
||||
|
||||
private:
|
||||
nsCString mFingerprint;
|
||||
nsCString mSubjectName;
|
||||
nsCString mPrettyName;
|
||||
nsCOMPtr<nsISupports> mCert;
|
||||
};
|
||||
|
||||
#endif /* __NS_CERTIFICATEPRINCIPAL_H */
|
@ -7,7 +7,6 @@
|
||||
#include "cms.h"
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "nsCertificatePrincipal.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nssb64.h"
|
||||
@ -222,7 +221,7 @@ namespace {
|
||||
|
||||
struct VerifyCertificateContext
|
||||
{
|
||||
nsCOMPtr<nsICertificatePrincipal> principal;
|
||||
nsCOMPtr<nsIX509Cert> signingCert;
|
||||
ScopedCERTCertList builtChain;
|
||||
};
|
||||
|
||||
@ -242,27 +241,7 @@ VerifyCertificate(CERTCertificate* cert, void* voidContext, void* pinArg)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoString fingerprint;
|
||||
nsresult rv = xpcomCert->GetSha1Fingerprint(fingerprint);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoString orgName;
|
||||
rv = xpcomCert->GetOrganization(orgName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoString subjectName;
|
||||
rv = xpcomCert->GetSubjectName(subjectName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
context->principal =
|
||||
new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
|
||||
NS_ConvertUTF16toUTF8(subjectName),
|
||||
NS_ConvertUTF16toUTF8(orgName),
|
||||
xpcomCert);
|
||||
context->signingCert = xpcomCert;
|
||||
|
||||
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
||||
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
|
||||
@ -284,14 +263,14 @@ nsDataSignatureVerifier::VerifySignature(const char* aRSABuf,
|
||||
const char* aPlaintext,
|
||||
uint32_t aPlaintextLen,
|
||||
int32_t* aErrorCode,
|
||||
nsICertificatePrincipal** aPrincipal)
|
||||
nsIX509Cert** aSigningCert)
|
||||
{
|
||||
if (!aPlaintext || !aPrincipal || !aErrorCode) {
|
||||
if (!aPlaintext || !aSigningCert || !aErrorCode) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aErrorCode = VERIFY_ERROR_OTHER;
|
||||
*aPrincipal = nullptr;
|
||||
*aSigningCert = nullptr;
|
||||
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
|
||||
@ -325,7 +304,7 @@ nsDataSignatureVerifier::VerifySignature(const char* aRSABuf,
|
||||
rv = NS_OK;
|
||||
}
|
||||
if (rv == NS_OK) {
|
||||
context.principal.forget(aPrincipal);
|
||||
context.signingCert.forget(aSigningCert);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user