Merge pull request #7 from classilla/master

merge from head
This commit is contained in:
Riccardo 2018-03-01 16:51:17 +01:00 committed by GitHub
commit 8413c728bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 3852 additions and 1540 deletions

View File

@ -1013,7 +1013,7 @@ pref("browser.sessionstore.resume_from_crash", true);
pref("browser.sessionstore.resume_session_once", false);
// minimal interval between two save operations in milliseconds
pref("browser.sessionstore.interval", 30000);
pref("browser.sessionstore.interval", 60000);
// on which sites to save text data, POSTDATA and cookies
// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
pref("browser.sessionstore.privacy_level", 0);

View File

@ -693,7 +693,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
if (mIsTenFourFoxAdBlockEnabled &&
(targetScheme.EqualsLiteral("http") || targetScheme.EqualsLiteral("https"))) {
nsAutoCString hostname;
if (NS_SUCCEEDED(targetBaseURI->GetHost(hostname))) {
if (MOZ_LIKELY(NS_SUCCEEDED(targetBaseURI->GetHost(hostname)))) {
ToLowerCase(hostname);
#define BLOK(q) hostname.EqualsLiteral(q)
if (0 ||
@ -786,6 +786,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("cdn.viglink.com") ||
BLOK("xcp.go.sonobi.com") ||
BLOK("apex.go.sonobi.com") ||
BLOK("s.ntv.io") ||
@ -826,6 +827,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("cdn.engine.4dsply.com") ||
BLOK("as.casalemedia.com") ||
BLOK("as-sec.casalemedia.com") ||
BLOK("loadm.exelator.com") ||
@ -899,6 +901,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("sb.monetate.net") ||
BLOK("se.monetate.net") ||
BLOK("ad.crwdcntrl.net") ||
BLOK("tags.crwdcntrl.net") ||
BLOK("cdn.nsstatic.net") ||
@ -972,6 +975,28 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("tags.mathtag.com") ||
BLOK("pixel.mathtag.com") ||
BLOK("a.teads.tv") ||
BLOK("cdn.teads.tv") ||
BLOK("cdata.carambo.la") ||
BLOK("route.carambo.la") ||
BLOK("us-ads.openx.net") ||
BLOK("s-static.innovid.com") ||
// This is controversial, but I'm pretty sure we
// don't want this.
BLOK("coinhive.com") ||
BLOK("ustatik.com") ||
BLOK("cdn.ustatik.com") ||
BLOK("adx.adform.net") ||
BLOK("s.spoutable.com") ||
BLOK("cdn.spoutable.com") ||
0) {
#undef BLOK
// Yup.

View File

@ -4109,9 +4109,10 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
// content associated with our subdocument.
EnsureDocument(mPresContext);
if (nsIDocument *parentDoc = mDocument->GetParentDocument()) {
if (nsIContent *docContent = parentDoc->FindContentForSubDocument(mDocument)) {
if (nsCOMPtr<nsIContent> docContent =
parentDoc->FindContentForSubDocument(mDocument)) {
if (nsIPresShell *parentShell = parentDoc->GetShell()) {
EventStateManager* parentESM =
RefPtr<EventStateManager> parentESM =
parentShell->GetPresContext()->EventStateManager();
parentESM->NotifyMouseOver(aMouseEvent, docContent);
}

View File

@ -178,8 +178,8 @@ static int64_t DurationToUsecs(TimeDuration aDuration) {
return static_cast<int64_t>(aDuration.ToSeconds() * USECS_PER_S);
}
static const uint32_t MIN_VIDEO_QUEUE_SIZE = 500;
static const uint32_t MAX_VIDEO_QUEUE_SIZE = 500;
static const uint32_t MIN_VIDEO_QUEUE_SIZE = 600;
static const uint32_t MAX_VIDEO_QUEUE_SIZE = 600;
static const uint32_t VIDEO_QUEUE_SEND_TO_COMPOSITOR_SIZE = 45;
static uint32_t sVideoQueueDefaultSize = MAX_VIDEO_QUEUE_SIZE;
@ -1185,7 +1185,7 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
mState == DECODER_STATE_COMPLETED);
if (IsPlaying()) {
if (MOZ_LIKELY(IsPlaying())) {
// Logging this case is really spammy - don't do it.
return;
}
@ -2443,7 +2443,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
}
case DECODER_STATE_DECODING: {
if (IsDecodingFirstFrame()) {
if (MOZ_UNLIKELY(IsDecodingFirstFrame())) {
// We haven't completed decoding our first frames, we can't start
// playback yet.
return NS_OK;
@ -2623,7 +2623,7 @@ MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData)
MOZ_ASSERT(OnTaskQueue());
// Update corrupt-frames statistics
if (aData->mImage && !aData->mImage->IsValid()) {
if (aData->mImage && MOZ_UNLIKELY(!aData->mImage->IsValid())) {
FrameStatistics& frameStats = *mFrameStats;
frameStats.NotifyCorruptFrame();
// If more than 10% of the last 30 frames have been corrupted, then try disabling
@ -2792,7 +2792,7 @@ MediaDecoderStateMachine::DropAudioUpToSeekTarget(MediaData* aSample)
audio->mAudioData.get() + (framesToPrune.value() * channels),
frames * channels * sizeof(AudioDataValue));
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
if (!duration.isValid()) {
if (MOZ_UNLIKELY(!duration.isValid())) {
return NS_ERROR_FAILURE;
}
RefPtr<AudioData> data(new AudioData(audio->mOffset,

View File

@ -88,24 +88,24 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
AbstractMediaDecoder::AutoNotifyDecoded a(mReader->GetDecoder());
RefPtr<NesteggPacketHolder> holder(mReader->NextPacket(WebMReader::VIDEO));
if (!holder) {
if (MOZ_UNLIKELY(!holder)) {
return false;
}
nestegg_packet* packet = holder->Packet();
unsigned int track = 0;
int r = nestegg_packet_track(packet, &track);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return false;
}
unsigned int count = 0;
r = nestegg_packet_count(packet, &count);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return false;
}
if (count > 1) {
if (MOZ_UNLIKELY(count > 1)) {
NS_WARNING("Packet contains more than one video frame");
return false;
}
@ -130,7 +130,7 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
unsigned char* data;
size_t length;
r = nestegg_packet_data(packet, 0, &data, &length);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return false;
}
@ -153,7 +153,7 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
aKeyframeSkip = false;
}
if (vpx_codec_decode(&mVPX, data, length, nullptr, 0)) {
if (MOZ_UNLIKELY(vpx_codec_decode(&mVPX, data, length, nullptr, 0))) {
return false;
}
@ -217,7 +217,7 @@ SoftwareWebMVideoDecoder::DecodeVideoFrame(bool &aKeyframeSkip,
si.is_kf,
-1,
picture);
if (!v) {
if (MOZ_UNLIKELY(!v)) {
return false;
}
a.mParsed++;

View File

@ -417,7 +417,7 @@ bool WebMReader::DecodeAudioPacket(NesteggPacketHolder* aHolder)
int r = 0;
unsigned int count = 0;
r = nestegg_packet_count(aHolder->Packet(), &count);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return false;
}
@ -439,7 +439,7 @@ bool WebMReader::DecodeAudioPacket(NesteggPacketHolder* aHolder)
return false;
}
decoded_frames += mAudioFrames;
if (!decoded_frames.isValid()) {
if (MOZ_UNLIKELY(!decoded_frames.isValid())) {
NS_WARNING("Int overflow adding decoded_frames");
return false;
}
@ -460,7 +460,7 @@ bool WebMReader::DecodeAudioPacket(NesteggPacketHolder* aHolder)
unsigned char* data;
size_t length;
r = nestegg_packet_data(aHolder->Packet(), i, &data, &length);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return false;
}
int64_t discardPadding = 0;
@ -508,7 +508,7 @@ RefPtr<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType)
do {
RefPtr<NesteggPacketHolder> holder = DemuxPacket();
if (!holder) {
if (MOZ_UNLIKELY(!holder)) {
return nullptr;
}
@ -530,13 +530,13 @@ WebMReader::DemuxPacket()
{
nestegg_packet* packet;
int r = nestegg_read_packet(mContext, &packet);
if (r <= 0) {
if (MOZ_UNLIKELY(r <= 0)) {
return nullptr;
}
unsigned int track = 0;
r = nestegg_packet_track(packet, &track);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return nullptr;
}
@ -548,7 +548,7 @@ WebMReader::DemuxPacket()
unsigned char* data;
size_t length;
r = nestegg_packet_data(packet, 0, &data, &length);
if (r == -1) {
if (MOZ_UNLIKELY(r == -1)) {
return nullptr;
}
vpx_codec_stream_info_t si;
@ -576,7 +576,7 @@ bool WebMReader::DecodeAudioData()
MOZ_ASSERT(OnTaskQueue());
RefPtr<NesteggPacketHolder> holder(NextPacket(AUDIO));
if (!holder) {
if (MOZ_UNLIKELY(!holder)) {
return false;
}
@ -589,7 +589,7 @@ bool WebMReader::FilterPacketByTime(int64_t aEndTime, WebMPacketQueue& aOutput)
// than aEndTime.
while (true) {
RefPtr<NesteggPacketHolder> holder(NextPacket(VIDEO));
if (!holder) {
if (MOZ_UNLIKELY(!holder)) {
break;
}
int64_t tstamp = holder->Timestamp();
@ -622,7 +622,7 @@ int64_t WebMReader::GetNextKeyframeTime(int64_t aTimeThreshold)
int64_t keyframeTime = -1;
while (!foundKeyframe) {
RefPtr<NesteggPacketHolder> holder(NextPacket(VIDEO));
if (!holder) {
if (MOZ_UNLIKELY(!holder)) {
break;
}

View File

@ -224,18 +224,30 @@ gfxPlatformMac::MakePlatformFont(const nsAString& aFontName,
// Since HTTPS is becoming more common, check that first.
#define HTTP_OR_HTTPS_SUBDIR(x) \
{ \
if (!failed) { \
NS_NAMED_LITERAL_CSTRING(https_, "https://" x); \
spec.Left(loc, https_.Length()); \
if (loc.Equals(https_)) { \
failed = true; \
goto halt_font; \
} else { \
NS_NAMED_LITERAL_CSTRING(http_, "http://" x); \
spec.Left(loc, http_.Length()); \
if (loc.Equals(http_)) \
if (loc.Equals(http_)) { \
failed = true; \
goto halt_font; \
} \
} \
} \
}
// TenFourFox issue 477: deal with changing infix version URLs, such as latimes.com
#define HOST_AND_KEY(x, y) \
{ \
if (hostname.Equals(x)) { \
if (spec.Find(y) != kNotFound) { \
failed = true; \
goto halt_font; \
} \
} \
}
bool
@ -246,40 +258,52 @@ gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
"strange font format hint set");
// TenFourFox issue 261. Prevent loading certain known bad font URIs.
// Our checks only know about HTTP, though, so don't check others (issue 477).
nsAutoCString spec, loc;
nsresult rv = aFontURI->GetAsciiSpec(spec);
bool failed = false;
if (MOZ_LIKELY(NS_SUCCEEDED(rv))) {
nsAutoCString scheme;
if (MOZ_LIKELY(NS_SUCCEEDED(aFontURI->GetScheme(scheme)))) {
if (scheme.Equals("http") || scheme.Equals("https")) {
#if DEBUG
fprintf(stderr, "Font blacklist checking: %s\n", spec.get());
fprintf(stderr, "Font blacklist checking: %s\n", spec.get());
#endif
HTTP_OR_HTTPS_SUBDIR("www.apple.com/wss/fonts/SF-Pro-Text/v1/");
HTTP_OR_HTTPS_SUBDIR("www.apple.com/wss/fonts/SF-Pro-Display/v1/");
// Do left-most URL checks first.
HTTP_OR_HTTPS_SUBDIR("fonts.gstatic.com/ea/notosansjapanese/v6/NotoSansJP-");
HTTP_OR_HTTPS_SUBDIR("www.icloud.com/fonts/SFNSText-");
HTTP_OR_HTTPS_SUBDIR("typeface.nyt.com/fonts/nyt-cheltenham-");
HTTP_OR_HTTPS_SUBDIR("typeface.nytimes.com/fonts/nyt-cheltenham-");
// Don't cut to SF-Pro-; there are some dingbat fonts that DO work.
HTTP_OR_HTTPS_SUBDIR("www.apple.com/wss/fonts/SF-Pro-Text/v1/");
HTTP_OR_HTTPS_SUBDIR("www.apple.com/wss/fonts/SF-Pro-Display/v1/");
HTTP_OR_HTTPS_SUBDIR("lib.intuitcdn.net/fonts/AvenirNext/1.0/");
// Check hostname and subpatterns (TenFourFox issue 477).
nsAutoCString hostname;
if (MOZ_LIKELY(NS_SUCCEEDED(aFontURI->GetHost(hostname)))) {
ToLowerCase(hostname);
HOST_AND_KEY("www.latimes.com", "/fonts/KisFBDisplay-");
} else
failed = true; // Didn't get hostname, should have.
} // Must not be HTTP(S). We could catch others below.
} else
failed = true; // Didn't get scheme, should have.
} else
failed = true;
failed = true; // Didn't get URL, should have.
halt_font:
if (failed ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4dcd1b9d7833fcec708a/fonts/KisFBDisplay-Bold.woff") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4dcd1b9d7833fcec708a/fonts/KisFBDisplay-Bold.woff2") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4dcd1b9d7833fcec708a/fonts/KisFBDisplay-Roman.woff") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4dcd1b9d7833fcec708a/fonts/KisFBDisplay-Roman.woff2") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4b58868f482c8c9570aa/fonts/KisFBDisplay-Bold.woff") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4b58868f482c8c9570aa/fonts/KisFBDisplay-Bold.woff2") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4b58868f482c8c9570aa/fonts/KisFBDisplay-Roman.woff") ||
spec.Equals("http://www.latimes.com/pb/resources/dist/la/latest/4b58868f482c8c9570aa/fonts/KisFBDisplay-Roman.woff2") ||
// XXX: Reserve listing things here for one-offs that are too expensive to check otherwise,
// or if there is a non-HTTP(S) URL we need to block (!!).
// spec.Equals("URL") ||
spec.Equals("https://cdn-static-1.medium.com/_/fp/fonts/charter-nonlatin.b-nw7PXlIqmGHGmHvkDiTw.woff") ||
spec.Equals("http://typeface.nytimes.com/fonts/nyt-cheltenham-200-normal.woff") ||
spec.Equals("https://typeface.nyt.com/fonts/nyt-cheltenham-200-normal.woff") ||
spec.Equals("http://typeface.nytimes.com/fonts/nyt-cheltenham-300-normal.woff") ||
spec.Equals("https://typeface.nyt.com/fonts/nyt-cheltenham-300-normal.woff") ||
spec.Equals("http://typeface.nytimes.com/fonts/nyt-cheltenham-400-normal.woff") ||
spec.Equals("https://typeface.nyt.com/fonts/nyt-cheltenham-400-normal.woff") ||
spec.Equals("http://fonts.gstatic.com/ea/notosansjapanese/v6/NotoSansJP-Regular.woff") ||
spec.Equals("http://fonts.gstatic.com/ea/notosansjapanese/v6/NotoSansJP-Bold.woff") ||
spec.Equals("http://fonts.gstatic.com/ea/notosansjapanese/v6/NotoSansJP-Regular.otf") ||
spec.Equals("http://fonts.gstatic.com/ea/notosansjapanese/v6/NotoSansJP-Bold.otf") ||
spec.Equals("https://www.icloud.com/fonts/SFNSText-Light.woff") ||
spec.Equals("https://www.icloud.com/fonts/SFNSText-Medium.woff") ||
0) {
if (MOZ_LIKELY(NS_SUCCEEDED(rv))) // Don't print if we couldn't get the URL.
fprintf(stderr, "Warning: TenFourFox blocking ATSUI-incompatible webfont %s.\n", spec.get());

View File

@ -189,7 +189,7 @@ GCRuntime::tryNewTenuredObject(ExclusiveContext* cx, AllocKind kind, size_t thin
JSObject* obj = tryNewTenuredThing<JSObject, allowGC>(cx, kind, thingSize);
if (obj)
if (MOZ_LIKELY(obj))
obj->setInitialSlotsMaybeNonNative(slots);
else
js_free(slots);
@ -262,7 +262,7 @@ GCRuntime::tryNewTenuredThing(ExclusiveContext* cx, AllocKind kind, size_t thing
rt->gc.waitBackgroundSweepOrAllocEnd();
t = tryNewTenuredThing<T, NoGC>(cx, kind, thingSize);
if (!t)
if (MOZ_UNLIKELY(!t))
ReportOutOfMemory(cx);
}
}

View File

@ -215,7 +215,7 @@ js::Nursery::allocateObject(JSContext* cx, size_t size, size_t numDynamic, const
/* Make the object allocation. */
JSObject* obj = static_cast<JSObject*>(allocate(size));
if (!obj)
if (MOZ_UNLIKELY(!obj))
return nullptr;
/* If we want external slots, add them. */
@ -223,7 +223,7 @@ js::Nursery::allocateObject(JSContext* cx, size_t size, size_t numDynamic, const
if (numDynamic) {
MOZ_ASSERT(clasp->isNative());
slots = static_cast<HeapSlot*>(allocateBuffer(cx->zone(), numDynamic * sizeof(HeapSlot)));
if (!slots) {
if (MOZ_UNLIKELY(!slots)) {
/*
* It is safe to leave the allocated object uninitialized, since we
* do not visit unallocated things in the nursery.

View File

@ -2095,7 +2095,7 @@ AllocRelocatedCell(Zone* zone, AllocKind thingKind, size_t thingSize)
void* dstAlloc = zone->arenas.allocateFromFreeList(thingKind, thingSize);
if (!dstAlloc)
dstAlloc = GCRuntime::refillFreeListInGC(zone, thingKind);
if (!dstAlloc) {
if (MOZ_UNLIKELY(!dstAlloc)) {
// This can only happen in zeal mode or debug builds as we don't
// otherwise relocate more cells than we have existing free space
// for.
@ -4313,7 +4313,7 @@ js::gc::MarkingValidator::nonIncrementalMark()
for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
ChunkBitmap* bitmap = &chunk->bitmap;
ChunkBitmap* entry = js_new<ChunkBitmap>();
if (!entry)
if (MOZ_UNLIKELY(!entry))
return;
memcpy((void*)entry->bitmap, (void*)bitmap->bitmap, sizeof(bitmap->bitmap));

View File

@ -233,7 +233,7 @@ js::Throw(JSContext* cx, jsid id, unsigned errorNumber)
if (!idstr)
return false;
JSAutoByteString bytes(cx, idstr);
if (!bytes)
if (MOZ_UNLIKELY(!bytes))
return false;
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, errorNumber, bytes.ptr());
return false;
@ -661,12 +661,12 @@ NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed,
initialShapeFlags));
if (!shape)
if (MOZ_UNLIKELY(!shape))
return nullptr;
gc::InitialHeap heap = GetInitialHeap(newKind, clasp);
JSObject* obj = JSObject::create(cx, kind, heap, shape, group);
if (!obj)
if (MOZ_UNLIKELY(!obj))
return nullptr;
if (newKind == SingletonObject) {
@ -723,11 +723,11 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
}
RootedObjectGroup group(cxArg, ObjectGroup::defaultNewGroup(cxArg, clasp, proto, nullptr));
if (!group)
if (MOZ_UNLIKELY(!group))
return nullptr;
RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind, initialShapeFlags));
if (!obj)
if (MOZ_UNLIKELY(!obj))
return nullptr;
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
@ -790,11 +790,11 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext* cxArg, const Class* clasp,
Rooted<TaggedProto> taggedProto(cxArg, TaggedProto(proto));
RootedObjectGroup group(cxArg, ObjectGroup::defaultNewGroup(cxArg, clasp, taggedProto));
if (!group)
if (MOZ_UNLIKELY(!group))
return nullptr;
JSObject* obj = NewObject(cxArg, group, allocKind, newKind);
if (!obj)
if (MOZ_UNLIKELY(!obj))
return nullptr;
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
@ -844,7 +844,7 @@ js::NewObjectWithGroupCommon(ExclusiveContext* cx, HandleObjectGroup group,
}
JSObject* obj = NewObject(cx, group, allocKind, newKind);
if (!obj)
if (MOZ_UNLIKELY(!obj))
return nullptr;
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
@ -957,7 +957,7 @@ js::CreateThisForFunctionWithProto(JSContext* cx, HandleObject callee, HandleObj
if (proto) {
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, nullptr, TaggedProto(proto),
newTarget));
if (!group)
if (MOZ_UNLIKELY(!group))
return nullptr;
if (group->newScript() && !group->newScript()->analyzed()) {
@ -980,7 +980,7 @@ js::CreateThisForFunctionWithProto(JSContext* cx, HandleObject callee, HandleObj
if (res) {
JSScript* script = callee->as<JSFunction>().getOrCreateScript(cx);
if (!script)
if (MOZ_UNLIKELY(!script))
return nullptr;
TypeScript::SetThis(cx, script, TypeSet::ObjectType(res));
}
@ -1145,7 +1145,7 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
RootedObject clone(cx);
if (obj->isNative()) {
clone = NewObjectWithGivenTaggedProto(cx, obj->getClass(), proto);
if (!clone)
if (MOZ_UNLIKELY(!clone))
return nullptr;
if (clone->is<JSFunction>() && (obj->compartment() != clone->compartment())) {
@ -1161,7 +1161,7 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
options.setClass(obj->getClass());
clone = ProxyObject::New(cx, GetProxyHandler(obj), JS::NullHandleValue, proto, options);
if (!clone)
if (MOZ_UNLIKELY(!clone))
return nullptr;
if (!CopyProxyObject(cx, obj.as<ProxyObject>(), clone.as<ProxyObject>()))
@ -1345,13 +1345,13 @@ InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
// dst's object flags are 0.
shape = EmptyShape::getInitialShape(cx, dst->getClass(), dst->getTaggedProto(),
dst->numFixedSlots(), 0);
if (!shape)
if (MOZ_UNLIKELY(!shape))
return false;
// Get an in-order list of the shapes in the src object.
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
for (Shape::Range<NoGC> r(src->lastProperty()); !r.empty(); r.popFront()) {
if (!shapes.append(&r.front()))
if (MOZ_UNLIKELY(!shapes.append(&r.front())))
return false;
}
Reverse(shapes.begin(), shapes.end());
@ -1442,7 +1442,7 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
: ObjectGroup::NewArrayKind::Normal;
obj.set(ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
TenuredObject, arrayKind));
if (!obj)
if (MOZ_UNLIKELY(!obj))
return false;
}
@ -1551,18 +1551,20 @@ JSObject::fixDictionaryShapeAfterSwap()
bool
JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
{
#if(0) // See TenFourFox issue 479 for why we can get away with this.
// Ensure swap doesn't cause a finalizer to not be run.
MOZ_ASSERT(IsBackgroundFinalized(a->asTenured().getAllocKind()) ==
IsBackgroundFinalized(b->asTenured().getAllocKind()));
#endif
MOZ_ASSERT(a->compartment() == b->compartment());
AutoEnterOOMUnsafeRegion oomUnsafe;
AutoCompartment ac(cx, a);
if (!a->getGroup(cx))
if (MOZ_UNLIKELY(!a->getGroup(cx)))
oomUnsafe.crash("JSObject::swap");
if (!b->getGroup(cx))
if (MOZ_UNLIKELY(!b->getGroup(cx)))
oomUnsafe.crash("JSObject::swap");
/*
@ -1644,9 +1646,9 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
a->fixDictionaryShapeAfterSwap();
b->fixDictionaryShapeAfterSwap();
if (na && !b->as<NativeObject>().fillInAfterSwap(cx, avals, apriv))
if (MOZ_UNLIKELY(na && !b->as<NativeObject>().fillInAfterSwap(cx, avals, apriv)))
oomUnsafe.crash("fillInAfterSwap");
if (nb && !a->as<NativeObject>().fillInAfterSwap(cx, bvals, bpriv))
if (MOZ_UNLIKELY(nb && !a->as<NativeObject>().fillInAfterSwap(cx, bvals, bpriv)))
oomUnsafe.crash("fillInAfterSwap");
}
@ -1758,7 +1760,7 @@ DefineConstructorAndPrototype(JSContext* cx, HandleObject obj, JSProtoKey key, H
* used because it won't let us use protoProto as the proto.
*/
RootedNativeObject proto(cx, NewNativeObjectWithClassProto(cx, clasp, protoProto, SingletonObject));
if (!proto)
if (MOZ_UNLIKELY(!proto))
return nullptr;
/* After this point, control must exit via label bad or out. */
@ -1786,7 +1788,7 @@ DefineConstructorAndPrototype(JSContext* cx, HandleObject obj, JSProtoKey key, H
ctor = proto;
} else {
RootedFunction fun(cx, NewNativeConstructor(cx, constructor, nargs, atom, ctorKind));
if (!fun)
if (MOZ_UNLIKELY(!fun))
goto bad;
/*
@ -1960,7 +1962,7 @@ js::SetClassAndProto(JSContext* cx, HandleObject obj,
}
ObjectGroup* group = ObjectGroup::defaultNewGroup(cx, clasp, proto);
if (!group)
if (MOZ_UNLIKELY(!group))
return false;
/*
@ -1987,7 +1989,7 @@ JSObject::changeToSingleton(JSContext* cx, HandleObject obj)
ObjectGroup* group = ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
obj->getTaggedProto());
if (!group)
if (MOZ_UNLIKELY(!group))
return false;
obj->group_ = group;
@ -3656,12 +3658,12 @@ JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassIn
}
// Other things may be measured in the future if DMD indicates it is worthwhile.
if (is<JSFunction>() ||
if (MOZ_LIKELY((is<JSFunction>() ||
is<PlainObject>() ||
is<ArrayObject>() ||
is<CallObject>() ||
is<RegExpObject>() ||
is<ProxyObject>())
is<ProxyObject>())))
{
// Do nothing. But this function is hot, and we win by getting the
// common cases out of the way early. Some stats on the most common

View File

@ -149,6 +149,6 @@ bool Wrapper::finalizeInBackground(Value priv) const
*/
if (IsInsideNursery(&priv.toObject()))
return true;
return false; // speculative fix
return IsBackgroundFinalized(priv.toObject().asTenured().getAllocKind());
return false; // See TenFourFox issue 479.
//return IsBackgroundFinalized(priv.toObject().asTenured().getAllocKind());
}

View File

@ -54,7 +54,7 @@ js::RegExpAlloc(ExclusiveContext* cx, HandleObject proto /* = nullptr */)
regexp->initPrivate(nullptr);
if (!EmptyShape::ensureInitialCustomShape<RegExpObject>(cx, regexp))
if (MOZ_UNLIKELY(!EmptyShape::ensureInitialCustomShape<RegExpObject>(cx, regexp)))
return nullptr;
MOZ_ASSERT(regexp->lookupPure(cx->names().lastIndex)->slot() ==
@ -70,7 +70,7 @@ MatchPairs::initArrayFrom(MatchPairs& copyFrom)
{
MOZ_ASSERT(copyFrom.pairCount() > 0);
if (!allocOrExpandArray(copyFrom.pairCount()))
if (MOZ_UNLIKELY(!allocOrExpandArray(copyFrom.pairCount())))
return false;
PodCopy(pairs_, copyFrom.pairs_, pairCount_);
@ -90,7 +90,7 @@ ScopedMatchPairs::allocOrExpandArray(size_t pairCount)
MOZ_ASSERT(!pairs_);
pairs_ = (MatchPair*)lifoScope_.alloc().alloc(sizeof(MatchPair) * pairCount);
if (!pairs_)
if (MOZ_UNLIKELY(!pairs_))
return false;
pairCount_ = pairCount;
@ -224,7 +224,7 @@ RegExpObject::createNoStatics(ExclusiveContext* cx, HandleAtom source, RegExpFla
return nullptr;
Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx));
if (!regexp)
if (MOZ_UNLIKELY(!regexp))
return nullptr;
regexp->initAndZeroLastIndex(source, flags, cx);
@ -341,7 +341,7 @@ SetupBuffer(StringBuffer& sb, const CharT* oldChars, size_t oldLen, const CharT*
if (mozilla::IsSame<CharT, char16_t>::value && !sb.ensureTwoByteChars())
return false;
if (!sb.reserve(oldLen + 1))
if (MOZ_UNLIKELY(!sb.reserve(oldLen + 1)))
return false;
sb.infallibleAppend(oldChars, size_t(it - oldChars));
@ -837,10 +837,10 @@ RegExpCompartment::get(JSContext* cx, JSAtom* source, RegExpFlag flags, RegExpGu
}
ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(source, flags));
if (!shared)
if (MOZ_UNLIKELY(!shared))
return false;
if (!set_.add(p, shared)) {
if (MOZ_UNLIKELY(!set_.add(p, shared))) {
ReportOutOfMemory(cx);
return false;
}
@ -885,18 +885,18 @@ js::CloneRegExpObject(JSContext* cx, JSObject* obj_)
// in the tenured heap to simplify embedding them in JIT code.
RootedObjectGroup group(cx, regex->group());
Rooted<RegExpObject*> clone(cx, NewObjectWithGroup<RegExpObject>(cx, group, TenuredObject));
if (!clone)
if (MOZ_UNLIKELY(!clone))
return nullptr;
clone->initPrivate(nullptr);
if (!EmptyShape::ensureInitialCustomShape<RegExpObject>(cx, clone))
if (MOZ_UNLIKELY(!EmptyShape::ensureInitialCustomShape<RegExpObject>(cx, clone)))
return nullptr;
Rooted<JSAtom*> source(cx, regex->getSource());
// Check that the RegExpShared for |regex| is okay to reuse in the clone.
RegExpStatics* currentStatics = regex->getProto()->global().getRegExpStatics(cx);
if (!currentStatics)
if (MOZ_UNLIKELY(!currentStatics))
return nullptr;
RegExpFlag origFlags = regex->getFlags();
@ -969,7 +969,7 @@ bool
js::ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut)
{
JSLinearString* linear = flagStr->ensureLinear(cx);
if (!linear)
if (MOZ_UNLIKELY(!linear))
return false;
size_t len = linear->length();

View File

@ -517,6 +517,12 @@ nsDocumentViewer::~nsDocumentViewer()
mDocument->Destroy();
}
if (mPrintEngine) {
mPrintEngine->Destroy();
mPrintEngine = nullptr;
}
MOZ_RELEASE_ASSERT(mDestroyRefCount == 0);
NS_ASSERTION(!mPresShell && !mPresContext,
"User did not call nsIContentViewer::Destroy");
if (mPresShell || mPresContext) {
@ -1564,7 +1570,6 @@ nsDocumentViewer::Destroy()
// We also keep the viewer from being cached in session history, since
// we require all documents there to be sanitized.
if (mDestroyRefCount != 0) {
--mDestroyRefCount;
return NS_OK;
}
@ -4209,6 +4214,12 @@ nsDocumentViewer::IncrementDestroyRefCount()
++mDestroyRefCount;
}
void
nsDocumentViewer::DecrementDestroyRefCount()
{
--mDestroyRefCount;
}
//------------------------------------------------------------
#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)

View File

@ -39,6 +39,7 @@ public:
virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet) = 0;
virtual void IncrementDestroyRefCount() = 0;
virtual void DecrementDestroyRefCount() = 0;
virtual void ReturnToGalleyPresentation() = 0;
@ -73,6 +74,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint,
virtual bool GetIsPrintPreview() override; \
virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet) override; \
virtual void IncrementDestroyRefCount() override; \
virtual void DecrementDestroyRefCount() override; \
virtual void ReturnToGalleyPresentation() override; \
virtual void OnDonePrinting() override; \
virtual bool IsInitializedForPrintPreview() override; \

View File

@ -12,14 +12,8 @@ NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, nsRunnable, nsITimerCallback)
nsPagePrintTimer::~nsPagePrintTimer()
{
// "Destroy" the document viewer; this normally doesn't actually
// destroy it because of the IncrementDestroyRefCount call below
// XXX This is messy; the document viewer should use a single approach
// to keep itself alive during printing
nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint));
if (cv) {
cv->Destroy();
}
// This matches the IncrementDestroyRefCount call in the constructor.
mDocViewerPrint->DecrementDestroyRefCount();
}
nsresult

View File

@ -13,8 +13,11 @@
* \brief Provides the high level interface to wrap encoder algorithms.
*
*/
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "vp8/common/blockd.h"
#include "vpx_config.h"
#include "vpx/internal/vpx_codec_internal.h"
@ -89,6 +92,8 @@ vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
int i;
void *mem_loc = NULL;
if (iface->enc.mr_get_mem_loc == NULL) return VPX_CODEC_INCAPABLE;
if (!(res = iface->enc.mr_get_mem_loc(cfg, &mem_loc))) {
for (i = 0; i < num_enc; i++) {
vpx_codec_priv_enc_mr_cfg_t mr_cfg;
@ -98,28 +103,29 @@ vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
dsf->den > dsf->num) {
res = VPX_CODEC_INVALID_PARAM;
break;
} else {
mr_cfg.mr_low_res_mode_info = mem_loc;
mr_cfg.mr_total_resolutions = num_enc;
mr_cfg.mr_encoder_id = num_enc - 1 - i;
mr_cfg.mr_down_sampling_factor.num = dsf->num;
mr_cfg.mr_down_sampling_factor.den = dsf->den;
/* Force Key-frame synchronization. Namely, encoder at higher
* resolution always use the same frame_type chosen by the
* lowest-resolution encoder.
*/
if (mr_cfg.mr_encoder_id)
cfg->kf_mode = VPX_KF_DISABLED;
ctx->iface = iface;
ctx->name = iface->name;
ctx->priv = NULL;
ctx->init_flags = flags;
ctx->config.enc = cfg;
res = ctx->iface->init(ctx, &mr_cfg);
}
mr_cfg.mr_low_res_mode_info = mem_loc;
mr_cfg.mr_total_resolutions = num_enc;
mr_cfg.mr_encoder_id = num_enc - 1 - i;
mr_cfg.mr_down_sampling_factor.num = dsf->num;
mr_cfg.mr_down_sampling_factor.den = dsf->den;
/* Force Key-frame synchronization. Namely, encoder at higher
* resolution always use the same frame_type chosen by the
* lowest-resolution encoder.
*/
if (mr_cfg.mr_encoder_id)
cfg->kf_mode = VPX_KF_DISABLED;
ctx->iface = iface;
ctx->name = iface->name;
ctx->priv = NULL;
ctx->init_flags = flags;
ctx->config.enc = cfg;
res = ctx->iface->init(ctx, &mr_cfg);
if (res) {
const char *error_detail =
ctx->priv ? ctx->priv->err_detail : NULL;
@ -134,11 +140,14 @@ vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
vpx_codec_destroy(ctx);
i--;
}
#if CONFIG_MULTI_RES_ENCODING
assert(mem_loc);
free(((LOWER_RES_FRAME_INFO *)mem_loc)->mb_info);
free(mem_loc);
#endif
return SAVE_STATUS(ctx, res);
}
if (res)
break;
ctx++;
cfg++;
dsf++;

View File

@ -731,6 +731,7 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
{ "business.twitter.com", true, false, false, -1, &kPinset_twitterCom },
{ "ca.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
{ "cd.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
{ "cdn.ampproject.org", true, false, false, -1, &kPinset_google_root_pems },
{ "cdn.mozilla.net", true, false, true, -1, &kPinset_mozilla },
{ "cdn.mozilla.org", true, false, true, -1, &kPinset_mozilla },
{ "cg.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
@ -1178,8 +1179,8 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
{ "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
};
// Pinning Preload List Length = 476;
// Pinning Preload List Length = 477;
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1524685607926000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1527453921095000);

File diff suppressed because it is too large Load Diff

View File

@ -39,122 +39,29 @@ namespace storage {
#define MAX_MILLISECONDS_BETWEEN_RESULTS 75
#define MAX_ROWS_PER_RESULT 15
////////////////////////////////////////////////////////////////////////////////
//// Local Classes
// It is not possible to use ESR52's nsProxyRelease.h without substantial and
// unacceptable modification, so we use part of it here to simulate it and
// fix bugs 1375217 and 1350752.
//
// XXX: If this is needed lots of places, we should move it to that header.
namespace {
typedef AsyncExecuteStatements::ExecutionState ExecutionState;
typedef AsyncExecuteStatements::StatementDataArray StatementDataArray;
/**
* Notifies a callback with a result set.
*/
class CallbackResultNotifier : public nsRunnable
template<typename T>
class ProxyReleaseEvent : public nsRunnable
{
public:
CallbackResultNotifier(mozIStorageStatementCallback *aCallback,
mozIStorageResultSet *aResults,
AsyncExecuteStatements *aEventStatus) :
mCallback(aCallback)
, mResults(aResults)
, mEventStatus(aEventStatus)
explicit ProxyReleaseEvent(already_AddRefed<T> aDoomed)
: mDoomed(aDoomed.take()) {}
NS_IMETHOD Run() override
{
}
NS_IMETHOD Run()
{
NS_ASSERTION(mCallback, "Trying to notify about results without a callback!");
if (mEventStatus->shouldNotify()) {
// Hold a strong reference to the callback while notifying it, so that if
// it spins the event loop, the callback won't be released and freed out
// from under us.
nsCOMPtr<mozIStorageStatementCallback> callback = mCallback;
(void)callback->HandleResult(mResults);
}
NS_IF_RELEASE(mDoomed);
return NS_OK;
}
private:
mozIStorageStatementCallback *mCallback;
nsCOMPtr<mozIStorageResultSet> mResults;
RefPtr<AsyncExecuteStatements> mEventStatus;
T* MOZ_OWNING_REF mDoomed;
};
/**
* Notifies the calling thread that an error has occurred.
*/
class ErrorNotifier : public nsRunnable
{
public:
ErrorNotifier(mozIStorageStatementCallback *aCallback,
mozIStorageError *aErrorObj,
AsyncExecuteStatements *aEventStatus) :
mCallback(aCallback)
, mErrorObj(aErrorObj)
, mEventStatus(aEventStatus)
{
}
NS_IMETHOD Run()
{
if (mEventStatus->shouldNotify() && mCallback) {
// Hold a strong reference to the callback while notifying it, so that if
// it spins the event loop, the callback won't be released and freed out
// from under us.
nsCOMPtr<mozIStorageStatementCallback> callback = mCallback;
(void)callback->HandleError(mErrorObj);
}
return NS_OK;
}
private:
mozIStorageStatementCallback *mCallback;
nsCOMPtr<mozIStorageError> mErrorObj;
RefPtr<AsyncExecuteStatements> mEventStatus;
};
/**
* Notifies the calling thread that the statement has finished executing. Takes
* ownership of the StatementData so it is released on the proper thread.
*/
class CompletionNotifier : public nsRunnable
{
public:
/**
* This takes ownership of the callback and the StatementData. They are
* released on the thread this is dispatched to (which should always be the
* calling thread).
*/
CompletionNotifier(mozIStorageStatementCallback *aCallback,
ExecutionState aReason)
: mCallback(aCallback)
, mReason(aReason)
{
}
NS_IMETHOD Run()
{
if (mCallback) {
(void)mCallback->HandleCompletion(mReason);
NS_RELEASE(mCallback);
}
return NS_OK;
}
private:
mozIStorageStatementCallback *mCallback;
ExecutionState mReason;
};
} // namespace
////////////////////////////////////////////////////////////////////////////////
//// AsyncExecuteStatements
@ -208,16 +115,24 @@ AsyncExecuteStatements::AsyncExecuteStatements(StatementDataArray &aStatements,
, mCancelRequested(false)
, mMutex(aConnection->sharedAsyncExecutionMutex)
, mDBMutex(aConnection->sharedDBMutex)
, mRequestStartDate(TimeStamp::Now())
, mRequestStartDate(TimeStamp::Now())
{
(void)mStatements.SwapElements(aStatements);
NS_ASSERTION(mStatements.Length(), "We weren't given any statements!");
NS_IF_ADDREF(mCallback);
}
AsyncExecuteStatements::~AsyncExecuteStatements()
{
MOZ_ASSERT(!mCallback, "Never called the Completion callback!");
MOZ_ASSERT(!mHasTransaction, "There should be no transaction at this point");
if (mCallback) {
// NS_ProxyRelease(mCallingThread, mCallback.forget());
nsCOMPtr<nsIRunnable> ev =
new ProxyReleaseEvent<mozIStorageStatementCallback>(mCallback.forget());
if (NS_FAILED(mCallingThread->Dispatch(ev, NS_DISPATCH_NORMAL))) {
NS_WARNING("AsyncExecuteStatements dtor failed proxy release");
}
}
}
bool
@ -462,16 +377,30 @@ AsyncExecuteStatements::notifyComplete()
mHasTransaction = false;
}
// Always generate a completion notification; it is what guarantees that our
// destruction does not happen here on the async thread.
RefPtr<CompletionNotifier> completionEvent =
new CompletionNotifier(mCallback, mState);
// This will take ownership of mCallback and make sure its destruction will
// happen on the owner thread.
(void)mCallingThread->Dispatch(
NS_NewRunnableMethod(this, &AsyncExecuteStatements::notifyCompleteOnCallingThread),
NS_DISPATCH_NORMAL);
// We no longer own mCallback (the CompletionNotifier takes ownership).
mCallback = nullptr;
(void)mCallingThread->Dispatch(completionEvent, NS_DISPATCH_NORMAL);
return NS_OK;
}
nsresult
AsyncExecuteStatements::notifyCompleteOnCallingThread() {
#ifdef DEBUG
bool onCallingThread = false;
(void)mCallingThread->IsOnCurrentThread(&onCallingThread);
MOZ_ASSERT(onCallingThread);
#endif
// Take ownership of mCallback and responsibility for freeing it when we
// release it. Any notifyResultsOnCallingThread and notifyErrorOnCallingThread
// calls on the stack spinning the event loop have guaranteed their safety by
// creating their own strong reference before invoking the callback.
nsCOMPtr<mozIStorageStatementCallback> callback = mCallback.forget();
if (callback) {
(void)callback->HandleCompletion(mState);
}
return NS_OK;
}
@ -500,27 +429,63 @@ AsyncExecuteStatements::notifyError(mozIStorageError *aError)
if (!mCallback)
return NS_OK;
RefPtr<ErrorNotifier> notifier =
new ErrorNotifier(mCallback, aError, this);
NS_ENSURE_TRUE(notifier, NS_ERROR_OUT_OF_MEMORY);
(void)mCallingThread->Dispatch(
NS_NewRunnableMethodWithArg<nsCOMPtr<mozIStorageError>>(this, &AsyncExecuteStatements::notifyErrorOnCallingThread, aError),
NS_DISPATCH_NORMAL);
return mCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
return NS_OK;
}
nsresult
AsyncExecuteStatements::notifyErrorOnCallingThread(mozIStorageError *aError) {
#ifdef DEBUG
bool onCallingThread = false;
(void)mCallingThread->IsOnCurrentThread(&onCallingThread);
MOZ_ASSERT(onCallingThread);
#endif
// Acquire our own strong reference so that if the callback spins a nested
// event loop and notifyCompleteOnCallingThread is executed, forgetting
// mCallback, we still have a valid/strong reference that won't be freed until
// we exit.
nsCOMPtr<mozIStorageStatementCallback> callback = mCallback;
if (shouldNotify() && callback) {
(void)callback->HandleError(aError);
}
return NS_OK;
}
nsresult
AsyncExecuteStatements::notifyResults()
{
mMutex.AssertNotCurrentThreadOwns();
NS_ASSERTION(mCallback, "notifyResults called without a callback!");
MOZ_ASSERT(mCallback, "notifyResults called without a callback!");
RefPtr<CallbackResultNotifier> notifier =
new CallbackResultNotifier(mCallback, mResultSet, this);
NS_ENSURE_TRUE(notifier, NS_ERROR_OUT_OF_MEMORY);
// This takes ownership of mResultSet, a new one will be generated in
// buildAndNotifyResults() when further results will arrive.
(void)mCallingThread->Dispatch(
NS_NewRunnableMethodWithArg<RefPtr<ResultSet>>(this, &AsyncExecuteStatements::notifyResultsOnCallingThread, mResultSet.forget()),
NS_DISPATCH_NORMAL);
nsresult rv = mCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
if (NS_SUCCEEDED(rv))
mResultSet = nullptr; // we no longer own it on success
return rv;
return NS_OK;
}
nsresult
AsyncExecuteStatements::notifyResultsOnCallingThread(ResultSet *aResultSet)
{
#ifdef DEBUG
bool onCallingThread = false;
(void)mCallingThread->IsOnCurrentThread(&onCallingThread);
MOZ_ASSERT(onCallingThread);
#endif
// Acquire our own strong reference so that if the callback spins a nested
// event loop and notifyCompleteOnCallingThread is executed, forgetting
// mCallback, we still have a valid/strong reference that won't be freed until
// we exit.
nsCOMPtr<mozIStorageStatementCallback> callback = mCallback;
if (shouldNotify() && callback) {
(void)callback->HandleResult(aResultSet);
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(

View File

@ -82,6 +82,14 @@ public:
*/
bool shouldNotify();
/**
* Used by notifyComplete(), notifyError() and notifyResults() to notify on
* the calling thread.
*/
nsresult notifyCompleteOnCallingThread();
nsresult notifyErrorOnCallingThread(mozIStorageError *aError);
nsresult notifyResultsOnCallingThread(ResultSet *aResultSet);
private:
AsyncExecuteStatements(StatementDataArray &aStatements,
Connection *aConnection,
@ -186,7 +194,10 @@ private:
RefPtr<Connection> mConnection;
sqlite3 *mNativeConnection;
bool mHasTransaction;
mozIStorageStatementCallback *mCallback;
// Note, this may not be a threadsafe object - never addref/release off
// the calling thread. We take a reference when this is created, and
// release it in the CompletionNotifier::Run() call back to this thread.
nsCOMPtr<mozIStorageStatementCallback> mCallback;
nsCOMPtr<nsIThread> mCallingThread;
RefPtr<ResultSet> mResultSet;