From 2648b5a4fe9b36344b41c55ec488c6a8cb83057b Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Tue, 11 Nov 2014 08:58:52 +1300 Subject: [PATCH 01/71] Bug 1085175 - r=roc --- dom/media/MediaCache.cpp | 33 +++++++++++++++-------- media/libnestegg/include/nestegg-stdint.h | 1 + media/libnestegg/src/nestegg.c | 3 +++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/dom/media/MediaCache.cpp b/dom/media/MediaCache.cpp index 1421a07ba11..e45c6b9c612 100644 --- a/dom/media/MediaCache.cpp +++ b/dom/media/MediaCache.cpp @@ -1173,6 +1173,7 @@ MediaCache::Update() // Figure out where we should be reading from. It's the first // uncached byte after the current mStreamOffset. int64_t dataOffset = stream->GetCachedDataEndInternal(stream->mStreamOffset); + MOZ_ASSERT(dataOffset >= 0); // Compute where we'd actually seek to to read at readOffset int64_t desiredOffset = dataOffset; @@ -1705,6 +1706,7 @@ MediaCacheStream::NotifyDataStarted(int64_t aOffset) ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor()); NS_WARN_IF_FALSE(aOffset == mChannelOffset, "Server is giving us unexpected offset"); + MOZ_ASSERT(aOffset >= 0); mChannelOffset = aOffset; if (mStreamLength >= 0) { // If we started reading at a certain offset, then for sure @@ -2134,23 +2136,28 @@ MediaCacheStream::Seek(int32_t aWhence, int64_t aOffset) return NS_ERROR_FAILURE; int64_t oldOffset = mStreamOffset; + int64_t newOffset = mStreamOffset; switch (aWhence) { case PR_SEEK_END: if (mStreamLength < 0) return NS_ERROR_FAILURE; - mStreamOffset = mStreamLength + aOffset; + newOffset = mStreamLength + aOffset; break; case PR_SEEK_CUR: - mStreamOffset += aOffset; + newOffset += aOffset; break; case PR_SEEK_SET: - mStreamOffset = aOffset; + newOffset = aOffset; break; default: NS_ERROR("Unknown whence"); return NS_ERROR_FAILURE; } + if (newOffset < 0) + return NS_ERROR_FAILURE; + mStreamOffset = newOffset; + CACHE_LOG(PR_LOG_DEBUG, ("Stream %p Seek to %lld", this, (long long)mStreamOffset)); gMediaCache->NoteSeek(this, oldOffset); @@ -2192,11 +2199,10 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) break; } size = std::min(size, bytesRemaining); - // Clamp size until 64-bit file size issues (bug 500784) are fixed. + // Clamp size until 64-bit file size issues are fixed. size = std::min(size, int64_t(INT32_MAX)); } - int32_t bytes; int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1; if (cacheBlock < 0) { // We don't have a complete cached block here. @@ -2224,7 +2230,10 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) // We can just use the data in mPartialBlockBuffer. In fact we should // use it rather than waiting for the block to fill and land in // the cache. - bytes = std::min(size, streamWithPartialBlock->mChannelOffset - mStreamOffset); + int64_t bytes = std::min(size, streamWithPartialBlock->mChannelOffset - mStreamOffset); + // Clamp bytes until 64-bit file size issues are fixed. + bytes = std::min(bytes, int64_t(INT32_MAX)); + NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= aCount, "Bytes out of range."); memcpy(aBuffer, reinterpret_cast(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes); if (mCurrentMode == MODE_METADATA) { @@ -2248,6 +2257,7 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) gMediaCache->NoteBlockUsage(this, cacheBlock, mCurrentMode, TimeStamp::Now()); int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock; + int32_t bytes; NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range."); nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes); if (NS_FAILED(rv)) { @@ -2284,9 +2294,7 @@ MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer, } nsresult -MediaCacheStream::ReadFromCache(char* aBuffer, - int64_t aOffset, - int64_t aCount) +MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount) { ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor()); if (mClosed) @@ -2308,7 +2316,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer, return NS_ERROR_FAILURE; } size = std::min(size, bytesRemaining); - // Clamp size until 64-bit file size issues (bug 500784) are fixed. + // Clamp size until 64-bit file size issues are fixed. size = std::min(size, int64_t(INT32_MAX)); } @@ -2319,7 +2327,10 @@ MediaCacheStream::ReadFromCache(char* aBuffer, // We can just use the data in mPartialBlockBuffer. In fact we should // use it rather than waiting for the block to fill and land in // the cache. - bytes = std::min(size, mChannelOffset - streamOffset); + // Clamp bytes until 64-bit file size issues are fixed. + int64_t toCopy = std::min(size, mChannelOffset - streamOffset); + bytes = std::min(toCopy, int64_t(INT32_MAX)); + NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= toCopy, "Bytes out of range."); memcpy(aBuffer + count, reinterpret_cast(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes); } else { diff --git a/media/libnestegg/include/nestegg-stdint.h b/media/libnestegg/include/nestegg-stdint.h index 599a7a5fadd..111db72b025 100644 --- a/media/libnestegg/include/nestegg-stdint.h +++ b/media/libnestegg/include/nestegg-stdint.h @@ -1,6 +1,7 @@ #ifdef _WIN32 typedef __int64 int64_t; typedef unsigned __int64 uint64_t; +#define INT64_MAX 9223372036854775807LL #else #include #endif diff --git a/media/libnestegg/src/nestegg.c b/media/libnestegg/src/nestegg.c index 6c0c3e8b3be..e281f44f694 100644 --- a/media/libnestegg/src/nestegg.c +++ b/media/libnestegg/src/nestegg.c @@ -2106,6 +2106,9 @@ nestegg_offset_seek(nestegg * ctx, uint64_t offset) { int r; + if (offset > INT64_MAX) + return -1; + /* Seek and set up parser state for segment-level element (Cluster). */ r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET); if (r != 0) From 30949640a46eff0d449b40a8e41370f2c4c7fd9d Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 10 Nov 2014 15:18:10 -0500 Subject: [PATCH 02/71] Bug 1096535. Add more DisplayLink logging. r=bas --HG-- extra : rebase_source : 6569641159d6e89abcbf677b38df449333714db3 --- gfx/thebes/gfxWindowsPlatform.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 14a146287bb..56e34231893 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -32,6 +32,7 @@ #include "gfxGDIFont.h" #include "mozilla/layers/CompositorParent.h" // for CompositorParent::IsInCompositorThread +#include "mozilla/IntegerPrintfMacros.h" #include "DeviceManagerD3D9.h" #include "mozilla/layers/ReadbackManagerD3D11.h" @@ -1522,6 +1523,9 @@ bool DoesD3D11DeviceWork(ID3D11Device *device) checked = true; if (GetModuleHandleW(L"dlumd32.dll") && GetModuleHandleW(L"igd10umd32.dll")) { +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: detected\n")); +#endif nsString displayLinkModuleVersionString; gfxWindowsPlatform::GetDLLVersion(L"dlumd32.dll", displayLinkModuleVersionString); uint64_t displayLinkModuleVersion; @@ -1531,6 +1535,11 @@ bool DoesD3D11DeviceWork(ID3D11Device *device) #endif return false; } +#if defined(MOZ_CRASHREPORTER) + nsPrintfCString displayLinkInfo("Version: " PRIx64 "\n", displayLinkModuleVersion); + CrashReporter::AppendAppNotesToCrashReport(displayLinkInfo); +#endif + if (displayLinkModuleVersion <= GFX_DRIVER_VERSION(8,6,1,36484)) { #if defined(MOZ_CRASHREPORTER) CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: too old version\n")); From ba2f4fc2db23b3190024cde8b81b76ba22cf41e2 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Mon, 10 Nov 2014 13:32:15 -0700 Subject: [PATCH 03/71] Bug 1093719 - Run only parent indexedDB xpcshell tests on Android; r=ahal --- dom/indexedDB/test/unit/xpcshell-parent-process.ini | 3 ++- dom/indexedDB/test/unit/xpcshell-shared.ini | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.ini b/dom/indexedDB/test/unit/xpcshell-parent-process.ini index 01e21eeb9e4..03563d885d2 100644 --- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini +++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini @@ -6,7 +6,7 @@ dupe-manifest = head = xpcshell-head-parent-process.js tail = -skip-if = toolkit == 'android' || toolkit == 'gonk' +skip-if = toolkit == 'gonk' support-files = bug1056939.zip GlobalObjectsChild.js @@ -21,6 +21,7 @@ support-files = [test_blob_file_backed.js] [test_bug1056939.js] [test_globalObjects_ipc.js] +skip-if = toolkit == 'android' [test_invalidate.js] # disabled for the moment. skip-if = true diff --git a/dom/indexedDB/test/unit/xpcshell-shared.ini b/dom/indexedDB/test/unit/xpcshell-shared.ini index 91e6e61f722..b3464bf46c7 100644 --- a/dom/indexedDB/test/unit/xpcshell-shared.ini +++ b/dom/indexedDB/test/unit/xpcshell-shared.ini @@ -1,8 +1,6 @@ # 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/. -[DEFAULT] -skip-if = toolkit == 'gonk' [test_add_put.js] [test_add_twice_failure.js] From 779f210fa822ba8f7c544464bcb31597d708a611 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Mon, 10 Nov 2014 12:37:35 -0800 Subject: [PATCH 04/71] Bug 1084679 - Track invalidation rects during decoding on Decoder, not imgStatusTracker. r=tn --- image/src/Decoder.cpp | 42 ------ image/src/Decoder.h | 17 ++- image/src/RasterImage.cpp | 90 ++++++------- image/src/RasterImage.h | 3 + image/src/VectorImage.cpp | 20 ++- image/src/imgDecoderObserver.h | 14 -- image/src/imgStatusTracker.cpp | 121 ++++-------------- image/src/imgStatusTracker.h | 32 ++--- .../test_synchronized_animation.html | 35 +++-- 9 files changed, 117 insertions(+), 257 deletions(-) diff --git a/image/src/Decoder.cpp b/image/src/Decoder.cpp index 24664b06390..85d10d63ebe 100644 --- a/image/src/Decoder.cpp +++ b/image/src/Decoder.cpp @@ -245,35 +245,6 @@ Decoder::AllocateFrame() return rv; } -void -Decoder::FlushInvalidations() -{ - NS_ABORT_IF_FALSE(!HasDecoderError(), - "Not allowed to make more decoder calls after error!"); - - // If we've got an empty invalidation rect, we have nothing to do - if (mInvalidRect.IsEmpty()) - return; - - if (mObserver) { -#ifdef XP_MACOSX - // Bug 703231 - // Because of high quality down sampling on mac we show scan lines while decoding. - // Bypass this problem by redrawing the border. - if (mImageMetadata.HasSize()) { - nsIntRect mImageBound(0, 0, mImageMetadata.GetWidth(), mImageMetadata.GetHeight()); - - mInvalidRect.Inflate(1); - mInvalidRect = mInvalidRect.Intersect(mImageBound); - } -#endif - mObserver->FrameChanged(&mInvalidRect); - } - - // Clear the invalidation rectangle - mInvalidRect.SetEmpty(); -} - void Decoder::SetSizeOnImage() { @@ -320,11 +291,6 @@ Decoder::PostFrameStart() // We shouldn't already be mid-frame NS_ABORT_IF_FALSE(!mInFrame, "Starting new frame but not done with old one!"); - // We should take care of any invalidation region when wrapping up the - // previous frame - NS_ABORT_IF_FALSE(mInvalidRect.IsEmpty(), - "Start image frame with non-empty invalidation region!"); - // Update our state to reflect the new frame mFrameCount++; mInFrame = true; @@ -334,11 +300,6 @@ Decoder::PostFrameStart() // reported by the Image. NS_ABORT_IF_FALSE(mFrameCount == mImage.GetNumFrames(), "Decoder frame count doesn't match image's!"); - - // Fire notifications - if (mObserver) { - mObserver->OnStartFrame(); - } } void @@ -363,9 +324,6 @@ Decoder::PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha /* = FrameBlender::k mCurrentFrame->SetBlendMethod(aBlendMethod); mCurrentFrame->ImageUpdated(mCurrentFrame->GetRect()); - // Flush any invalidations before we finish the frame - FlushInvalidations(); - // Fire notifications if (mObserver) { mObserver->OnStopFrame(); diff --git a/image/src/Decoder.h b/image/src/Decoder.h index 077f8f5ed85..5397aa2b5ea 100644 --- a/image/src/Decoder.h +++ b/image/src/Decoder.h @@ -69,14 +69,17 @@ public: void FinishSharedDecoder(); /** - * Tells the decoder to flush any pending invalidations. This informs the image - * frame of its decoded region, and sends the appropriate OnDataAvailable call - * to consumers. - * - * This can be called any time when we're midway through decoding a frame, - * and must be called after finishing a frame (before starting a new one). + * Gets the invalidation region accumulated by the decoder so far, and clears + * the decoder's invalidation region. This means that each call to + * TakeInvalidRect() returns only the invalidation region accumulated since + * the last call to TakeInvalidRect(). */ - void FlushInvalidations(); + nsIntRect TakeInvalidRect() + { + nsIntRect invalidRect = mInvalidRect; + mInvalidRect.SetEmpty(); + return invalidRect; + } // We're not COM-y, so we don't get refcounts by default NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 05307d6117d..0c0326bd775 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -484,10 +484,10 @@ RasterImage::RequestRefresh(const TimeStamp& aTime) UpdateImageContainer(); - // Explicitly call this on mStatusTracker so we're sure to not interfere - // with the decoding process - if (mStatusTracker) - mStatusTracker->FrameChanged(&res.dirtyRect); + if (mStatusTracker) { + mStatusTracker->SyncNotifyDifference(ImageStatusDiff::NoChange(), + res.dirtyRect); + } } if (res.animationFinished) { @@ -655,6 +655,17 @@ RasterImage::GetRequestedFrameIndex(uint32_t aWhichFrame) const return aWhichFrame == FRAME_FIRST ? 0 : GetCurrentFrameIndex(); } +nsIntRect +RasterImage::GetFirstFrameRect() +{ + if (mAnim) { + return mAnim->GetFirstFrameRefreshArea(); + } + + // Fall back to our size. This is implicitly zero-size if !mHasSize. + return nsIntRect(nsIntPoint(0,0), mSize); +} + //****************************************************************************** /* [notxpcom] boolean frameIsOpaque(in uint32_t aWhichFrame); */ NS_IMETHODIMP_(bool) @@ -1457,7 +1468,7 @@ RasterImage::ResetAnimation() // Update display if (mStatusTracker) { nsIntRect rect = mAnim->GetFirstFrameRefreshArea(); - mStatusTracker->FrameChanged(&rect); + mStatusTracker->SyncNotifyDifference(ImageStatusDiff::NoChange(), rect); } // Start the animation again. It may not have been running before, if @@ -1558,14 +1569,6 @@ RasterImage::AddSourceData(const char *aBuffer, uint32_t aCount) rv = WriteToDecoder(aBuffer, aCount, DECODE_SYNC); CONTAINER_ENSURE_SUCCESS(rv); - // We're not storing source data, so this data is probably coming straight - // from the network. In this case, we want to display data as soon as we - // get it, so we want to flush invalidations after every write. - nsRefPtr kungFuDeathGrip = mDecoder; - mInDecoder = true; - mDecoder->FlushInvalidations(); - mInDecoder = false; - rv = FinishedSomeDecoding(); CONTAINER_ENSURE_SUCCESS(rv); } @@ -2416,15 +2419,6 @@ RasterImage::SyncDecode() DECODE_SYNC); CONTAINER_ENSURE_SUCCESS(rv); - // When we're doing a sync decode, we want to get as much information from the - // image as possible. We've send the decoder all of our data, so now's a good - // time to flush any invalidations (in case we don't have all the data and what - // we got left us mid-frame). - nsRefPtr kungFuDeathGrip = mDecoder; - mInDecoder = true; - mDecoder->FlushInvalidations(); - mInDecoder = false; - rv = FinishedSomeDecoding(); CONTAINER_ENSURE_SUCCESS(rv); @@ -2498,9 +2492,8 @@ RasterImage::NotifyNewScaledFrame() if (mStatusTracker) { // Send an invalidation so observers will repaint and can take advantage of // the new scaled frame if possible. - // XXX(seth): Why does FrameChanged take a pointer and not a reference? - nsIntRect invalidationRect(0, 0, mSize.width, mSize.height); - mStatusTracker->FrameChanged(&invalidationRect); + nsIntRect rect(0, 0, mSize.width, mSize.height); + mStatusTracker->SyncNotifyDifference(ImageStatusDiff::NoChange(), rect); } } @@ -3001,9 +2994,12 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D bool done = false; bool wasSize = false; + nsIntRect invalidRect; nsresult rv = NS_OK; if (image->mDecoder) { + invalidRect = image->mDecoder->TakeInvalidRect(); + if (request && request->mChunkCount && !image->mDecoder->IsSizeDecode()) { Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS, request->mChunkCount); } @@ -3046,6 +3042,17 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D } } + if (GetCurrentFrameIndex() > 0) { + // Don't send invalidations for animated frames after the first; let + // RequestRefresh take care of that. + invalidRect = nsIntRect(); + } + if (mHasBeenDecoded && !invalidRect.IsEmpty()) { + // Don't send partial invalidations if we've been decoded before. + invalidRect = mDecoded ? GetFirstFrameRect() + : nsIntRect(); + } + ImageStatusDiff diff = request ? image->mStatusTracker->Difference(request->mStatusTracker) : image->mStatusTracker->DecodeStateAsDifference(); @@ -3058,13 +3065,15 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D // FinishedSomeDecoding on the stack. NS_WARNING("Recursively notifying in RasterImage::FinishedSomeDecoding!"); mStatusDiff.Combine(diff); + mInvalidRect.Union(invalidRect); } else { MOZ_ASSERT(mStatusDiff.IsNoChange(), "Shouldn't have an accumulated change at this point"); + MOZ_ASSERT(mInvalidRect.IsEmpty(), "Shouldn't have an accumulated invalidation rect here"); - while (!diff.IsNoChange()) { + while (!diff.IsNoChange() || !invalidRect.IsEmpty()) { // Tell the observers what happened. mNotifying = true; - image->mStatusTracker->SyncNotifyDifference(diff); + image->mStatusTracker->SyncNotifyDifference(diff, invalidRect); mNotifying = false; // Gather any status changes that may have occurred as a result of sending @@ -3072,6 +3081,8 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D // notifications for them next. diff = mStatusDiff; mStatusDiff = ImageStatusDiff::NoChange(); + invalidRect = mInvalidRect; + mInvalidRect = nsIntRect(); } } @@ -3484,31 +3495,6 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg, aImg->mDecodeRequest->mChunkCount += chunkCount; } - // Flush invalidations (and therefore paint) now that we've decoded all the - // chunks we're going to. - // - // However, don't paint if: - // - // * This was an until-size decode. Until-size decodes are always followed - // by normal decodes, so don't bother painting. - // - // * The decoder flagged an error. The decoder may have written garbage - // into the output buffer; don't paint it to the screen. - // - // * We have all the source data. This disables progressive display of - // previously-decoded images, thus letting us finish decoding faster, - // since we don't waste time painting while we decode. - // Decoder::PostFrameStop() will flush invalidations once the decode is - // done. - - if (aDecodeType != DECODE_TYPE_UNTIL_SIZE && - !aImg->mDecoder->HasError() && - !aImg->mHasSourceData) { - aImg->mInDecoder = true; - aImg->mDecoder->FlushInvalidations(); - aImg->mInDecoder = false; - } - return NS_OK; } diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index 9dd2cde72c8..f1b17050c81 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -552,6 +552,8 @@ private: uint32_t GetCurrentFrameIndex() const; uint32_t GetRequestedFrameIndex(uint32_t aWhichFrame) const; + nsIntRect GetFirstFrameRect(); + size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const; @@ -662,6 +664,7 @@ private: // data // Notification state. Used to avoid recursive notifications. ImageStatusDiff mStatusDiff; + nsIntRect mInvalidRect; bool mNotifying:1; // Boolean flags (clustered together to conserve space): diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 94c6bcf6021..2275ac08700 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -571,8 +571,10 @@ VectorImage::SendInvalidationNotifications() if (mStatusTracker) { SurfaceCache::Discard(this); - mStatusTracker->FrameChanged(&nsIntRect::GetMaxSizedIntRect()); - mStatusTracker->OnStopFrame(); + ImageStatusDiff diff; + diff.diffState = FLAG_FRAME_STOPPED; + mStatusTracker->ApplyDifference(diff); + mStatusTracker->SyncNotifyDifference(diff, nsIntRect::GetMaxSizedIntRect()); } } @@ -1119,17 +1121,11 @@ VectorImage::OnSVGDocumentLoaded() // Tell *our* observers that we're done loading. if (mStatusTracker) { - nsRefPtr clone = mStatusTracker->CloneForRecording(); - imgDecoderObserver* observer = clone->GetDecoderObserver(); - - observer->OnStartContainer(); // Signal that width/height are available. - observer->FrameChanged(&nsIntRect::GetMaxSizedIntRect()); - observer->OnStopFrame(); - observer->OnStopDecode(NS_OK); // Unblock page load. - - ImageStatusDiff diff = mStatusTracker->Difference(clone); + ImageStatusDiff diff; + diff.diffState = FLAG_HAS_SIZE | FLAG_FRAME_STOPPED | FLAG_DECODE_STOPPED | + FLAG_ONLOAD_UNBLOCKED; mStatusTracker->ApplyDifference(diff); - mStatusTracker->SyncNotifyDifference(diff); + mStatusTracker->SyncNotifyDifference(diff, nsIntRect::GetMaxSizedIntRect()); } EvaluateAnimation(); diff --git a/image/src/imgDecoderObserver.h b/image/src/imgDecoderObserver.h index f7b81975fcf..91ebf06af1c 100644 --- a/image/src/imgDecoderObserver.h +++ b/image/src/imgDecoderObserver.h @@ -66,20 +66,6 @@ public: */ virtual void OnStartContainer() = 0; - /** - * Decode notification. - * - * Called when we know a frame has begun decoding. - */ - virtual void OnStartFrame() = 0; - - /** - * Decode notification. - * - * called when there is more to paint. - */ - virtual void FrameChanged(const nsIntRect * aDirtyRect) = 0; - /** * Decode notification. * diff --git a/image/src/imgStatusTracker.cpp b/image/src/imgStatusTracker.cpp index ebf9fec3d9d..8e17938e8f8 100644 --- a/image/src/imgStatusTracker.cpp +++ b/image/src/imgStatusTracker.cpp @@ -62,22 +62,6 @@ public: tracker->RecordStartContainer(image); } - virtual void OnStartFrame() MOZ_OVERRIDE - { - LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartFrame"); - nsRefPtr tracker = mTracker.get(); - if (!tracker) { return; } - tracker->RecordStartFrame(); - } - - virtual void FrameChanged(const nsIntRect* dirtyRect) MOZ_OVERRIDE - { - LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::FrameChanged"); - nsRefPtr tracker = mTracker.get(); - if (!tracker) { return; } - tracker->RecordFrameChanged(dirtyRect); - } - virtual void OnStopFrame() MOZ_OVERRIDE { LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopFrame"); @@ -159,7 +143,6 @@ imgStatusTracker::imgStatusTracker(const imgStatusTracker& aOther) // - mProperties, because we don't need it and it'd just point at the same // object // - mConsumers, because we don't need to talk to consumers - // - mInvalidRect, because the point of it is to be fired off and reset { mTrackerObserver = new imgStatusTrackerObserver(this); } @@ -370,7 +353,7 @@ imgStatusTracker::NotifyCurrentState(imgRequestProxy* proxy) #define NOTIFY_IMAGE_OBSERVERS(func) \ do { \ - ProxyArray::ForwardIterator iter(proxies); \ + ProxyArray::ForwardIterator iter(aProxies); \ while (iter.HasMore()) { \ nsRefPtr proxy = iter.GetNext().get(); \ if (proxy && !proxy->NotificationsDeferred()) { \ @@ -380,57 +363,57 @@ imgStatusTracker::NotifyCurrentState(imgRequestProxy* proxy) } while (false); /* static */ void -imgStatusTracker::SyncNotifyState(ProxyArray& proxies, - bool hasImage, uint32_t state, - nsIntRect& dirtyRect) +imgStatusTracker::SyncNotifyState(ProxyArray& aProxies, + bool aHasImage, uint32_t aState, + const nsIntRect& aDirtyRect) { MOZ_ASSERT(NS_IsMainThread()); // OnStartRequest - if (state & FLAG_REQUEST_STARTED) + if (aState & FLAG_REQUEST_STARTED) NOTIFY_IMAGE_OBSERVERS(OnStartRequest()); // OnStartContainer - if (state & FLAG_HAS_SIZE) + if (aState & FLAG_HAS_SIZE) NOTIFY_IMAGE_OBSERVERS(OnStartContainer()); // OnStartDecode - if (state & FLAG_DECODE_STARTED) + if (aState & FLAG_DECODE_STARTED) NOTIFY_IMAGE_OBSERVERS(OnStartDecode()); // BlockOnload - if (state & FLAG_ONLOAD_BLOCKED) + if (aState & FLAG_ONLOAD_BLOCKED) NOTIFY_IMAGE_OBSERVERS(BlockOnload()); - if (hasImage) { + if (aHasImage) { // OnFrameUpdate // If there's any content in this frame at all (always true for // vector images, true for raster images that have decoded at // least one frame) then send OnFrameUpdate. - if (!dirtyRect.IsEmpty()) - NOTIFY_IMAGE_OBSERVERS(OnFrameUpdate(&dirtyRect)); + if (!aDirtyRect.IsEmpty()) + NOTIFY_IMAGE_OBSERVERS(OnFrameUpdate(&aDirtyRect)); - if (state & FLAG_FRAME_STOPPED) + if (aState & FLAG_FRAME_STOPPED) NOTIFY_IMAGE_OBSERVERS(OnStopFrame()); // OnImageIsAnimated - if (state & FLAG_IS_ANIMATED) + if (aState & FLAG_IS_ANIMATED) NOTIFY_IMAGE_OBSERVERS(OnImageIsAnimated()); } // Send UnblockOnload before OnStopDecode and OnStopRequest. This allows // observers that can fire events when they receive those notifications to do // so then, instead of being forced to wait for UnblockOnload. - if (state & FLAG_ONLOAD_UNBLOCKED) { + if (aState & FLAG_ONLOAD_UNBLOCKED) { NOTIFY_IMAGE_OBSERVERS(UnblockOnload()); } - if (state & FLAG_DECODE_STOPPED) { - NS_ABORT_IF_FALSE(hasImage, "stopped decoding without ever having an image?"); + if (aState & FLAG_DECODE_STOPPED) { + MOZ_ASSERT(aHasImage, "Stopped decoding without ever having an image?"); NOTIFY_IMAGE_OBSERVERS(OnStopDecode()); } - if (state & FLAG_REQUEST_STOPPED) { - NOTIFY_IMAGE_OBSERVERS(OnStopRequest(state & FLAG_MULTIPART_STOPPED)); + if (aState & FLAG_REQUEST_STOPPED) { + NOTIFY_IMAGE_OBSERVERS(OnStopRequest(aState & FLAG_MULTIPART_STOPPED)); } } @@ -440,22 +423,6 @@ imgStatusTracker::Difference(imgStatusTracker* aOther) const MOZ_ASSERT(aOther, "aOther cannot be null"); ImageStatusDiff diff; diff.diffState = ~mState & aOther->mState; - - // Only record partial invalidations if we haven't been decoded before. - // When images are re-decoded after discarding, we don't want to display - // partially decoded versions to the user. - const uint32_t combinedState = mState | aOther->mState; - const bool doInvalidations = !(mState & FLAG_DECODE_STOPPED) || - aOther->mState & FLAG_DECODE_STOPPED || - combinedState & FLAG_HAS_ERROR; - - // Record and reset the invalid rectangle. - // XXX(seth): We shouldn't be resetting anything here; see bug 910441. - if (doInvalidations) { - diff.invalidRect = aOther->mInvalidRect; - aOther->mInvalidRect.SetEmpty(); - } - return diff; } @@ -476,18 +443,15 @@ imgStatusTracker::ApplyDifference(const ImageStatusDiff& aDiff) } void -imgStatusTracker::SyncNotifyDifference(const ImageStatusDiff& diff) +imgStatusTracker::SyncNotifyDifference(const ImageStatusDiff& aDiff, + const nsIntRect& aInvalidRect /* = nsIntRect() */) { MOZ_ASSERT(NS_IsMainThread(), "Use mConsumers on main thread only"); LOG_SCOPE(GetImgLog(), "imgStatusTracker::SyncNotifyDifference"); - nsIntRect invalidRect = mInvalidRect.Union(diff.invalidRect); + SyncNotifyState(mConsumers, !!mImage, aDiff.diffState, aInvalidRect); - SyncNotifyState(mConsumers, !!mImage, diff.diffState, invalidRect); - - mInvalidRect.SetEmpty(); - - if (diff.diffState & FLAG_HAS_ERROR) { + if (aDiff.diffState & FLAG_HAS_ERROR) { FireFailureNotification(); } } @@ -648,14 +612,6 @@ imgStatusTracker::SendStartContainer(imgRequestProxy* aProxy) aProxy->OnStartContainer(); } -void -imgStatusTracker::RecordStartFrame() -{ - mInvalidRect.SetEmpty(); -} - -// No SendStartFrame since it's not observed below us. - void imgStatusTracker::RecordStopFrame() { @@ -746,23 +702,6 @@ imgStatusTracker::OnUnlockedDraw() } } -void -imgStatusTracker::RecordFrameChanged(const nsIntRect* aDirtyRect) -{ - NS_ABORT_IF_FALSE(mImage, - "RecordFrameChanged called before we have an Image"); - mInvalidRect = mInvalidRect.Union(*aDirtyRect); -} - -void -imgStatusTracker::SendFrameChanged(imgRequestProxy* aProxy, - const nsIntRect* aDirtyRect) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!aProxy->NotificationsDeferred()) - aProxy->OnFrameUpdate(aDirtyRect); -} - /* non-virtual sort-of-nsIRequestObserver methods */ void imgStatusTracker::RecordStartRequest() @@ -895,22 +834,6 @@ imgStatusTracker::OnDiscard() } } -void -imgStatusTracker::FrameChanged(const nsIntRect* aDirtyRect) -{ - MOZ_ASSERT(NS_IsMainThread()); - RecordFrameChanged(aDirtyRect); - - /* notify the kids */ - ProxyArray::ForwardIterator iter(mConsumers); - while (iter.HasMore()) { - nsRefPtr proxy = iter.GetNext().get(); - if (proxy) { - SendFrameChanged(proxy, aDirtyRect); - } - } -} - void imgStatusTracker::OnStopFrame() { diff --git a/image/src/imgStatusTracker.h b/image/src/imgStatusTracker.h index 47ffb589d54..e4a37111e28 100644 --- a/image/src/imgStatusTracker.h +++ b/image/src/imgStatusTracker.h @@ -46,8 +46,7 @@ enum { struct ImageStatusDiff { ImageStatusDiff() - : invalidRect() - , diffState(0) + : diffState(0) { } static ImageStatusDiff NoChange() { return ImageStatusDiff(); } @@ -55,17 +54,14 @@ struct ImageStatusDiff bool operator!=(const ImageStatusDiff& aOther) const { return !(*this == aOther); } bool operator==(const ImageStatusDiff& aOther) const { - return aOther.invalidRect == invalidRect - && aOther.diffState == diffState; + return aOther.diffState == diffState; } void Combine(const ImageStatusDiff& aOther) { - invalidRect = invalidRect.Union(aOther.invalidRect); diffState |= aOther.diffState; } - nsIntRect invalidRect; - uint32_t diffState; + uint32_t diffState; }; } // namespace image @@ -179,7 +175,7 @@ public: void RecordLoaded(); // Shorthand for recording all the decode notifications: StartDecode, - // StartFrame, DataAvailable, StopFrame, StopDecode. + // DataAvailable, StopFrame, StopDecode. void RecordDecoded(); /* non-virtual imgDecoderObserver methods */ @@ -189,10 +185,6 @@ public: void SendStartDecode(imgRequestProxy* aProxy); void RecordStartContainer(imgIContainer* aContainer); void SendStartContainer(imgRequestProxy* aProxy); - void RecordStartFrame(); - // No SendStartFrame since it's not observed below us. - void RecordFrameChanged(const nsIntRect* aDirtyRect); - void SendFrameChanged(imgRequestProxy* aProxy, const nsIntRect* aDirtyRect); void RecordStopFrame(); void SendStopFrame(imgRequestProxy* aProxy); void RecordStopDecode(nsresult statusg); @@ -219,7 +211,6 @@ public: void OnDataAvailable(); void OnStopRequest(bool aLastPart, nsresult aStatus); void OnDiscard(); - void FrameChanged(const nsIntRect* aDirtyRect); void OnUnlockedDraw(); // This is called only by VectorImage, and only to ensure tests work // properly. Do not use it. @@ -265,9 +256,8 @@ public: // Notify for the changes captured in an ImageStatusDiff. Because this may // result in recursive notifications, no decoding locks may be held. // Called on the main thread only. - void SyncNotifyDifference(const mozilla::image::ImageStatusDiff& aDiff); - - nsIntRect GetInvalidRect() const { return mInvalidRect; } + void SyncNotifyDifference(const mozilla::image::ImageStatusDiff& aDiff, + const nsIntRect& aInvalidRect = nsIntRect()); private: typedef nsTObserverArray> ProxyArray; @@ -282,16 +272,12 @@ private: // Main thread only, since imgRequestProxy calls are expected on the main // thread, and mConsumers is not threadsafe. - static void SyncNotifyState(ProxyArray& proxies, - bool hasImage, uint32_t state, - nsIntRect& dirtyRect); + static void SyncNotifyState(ProxyArray& aProxies, + bool aHasImage, uint32_t aState, + const nsIntRect& aInvalidRect); nsCOMPtr mRequestRunnable; - // The invalid area of the most recent frame we know about. (All previous - // frames are assumed to be fully valid.) - nsIntRect mInvalidRect; - // This weak ref should be set null when the image goes out of scope. mozilla::image::Image* mImage; diff --git a/image/test/mochitest/test_synchronized_animation.html b/image/test/mochitest/test_synchronized_animation.html index ee63824c738..9c0bf42a75b 100644 --- a/image/test/mochitest/test_synchronized_animation.html +++ b/image/test/mochitest/test_synchronized_animation.html @@ -33,6 +33,7 @@ var gRanEvent = false; var gObserver; var gImg1; var gImg2; +var gFirstImageLoaded = false; var gOuter; var gFinished = false; var gFirstRequest = null; @@ -71,20 +72,37 @@ function failTest() { cleanUpAndFinish(); } +function waitForLoadAndTest(image) { + return () => { + // Draw the image into a canvas to ensure it's decoded. + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + context.drawImage(image, 0, 0); + + // Attach the observer. + var imgLoadingContent = image.QueryInterface(Ci.nsIImageLoadingContent); + imgLoadingContent.addObserver(gOuter); + + // If the other image already loaded, add both images to the document, which + // begins the real test. + if (gFirstImageLoaded) { + gContent.appendChild(gImg1); + gContent.appendChild(gImg2); + } else { + gFirstImageLoaded = true; + } + }; +} + function main() { gImg1 = new Image(); gImg2 = new Image(); - // Create, customize & attach decoder observer + // Create and customize decoder observer var obs = new ImageDecoderObserverStub(); obs.frameUpdate = frameUpdate; gOuter = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools).createScriptedObserver(obs); - var imgLoadingContent = gImg1.QueryInterface(Ci.nsIImageLoadingContent); - imgLoadingContent.addObserver(gOuter); - - imgLoadingContent = gImg2.QueryInterface(Ci.nsIImageLoadingContent); - imgLoadingContent.addObserver(gOuter); // We want to test the cold loading behavior, so clear cache in case an // earlier test got our image in there already. @@ -94,8 +112,9 @@ function main() { gImg1.src = "animated1.gif"; gImg2.src = "animated2.gif"; - gContent.appendChild(gImg1); - gContent.appendChild(gImg2); + // Wait for each image to load. + gImg1.addEventListener('load', waitForLoadAndTest(gImg1)); + gImg2.addEventListener('load', waitForLoadAndTest(gImg2)); // In case something goes wrong, fail earlier than mochitest timeout, // and with more information. From 28083a633b6306f950b2194df508c1176c61a637 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 10 Nov 2014 12:53:34 -0800 Subject: [PATCH 05/71] Backed out changeset dc2e15a7df8d (bug 1096535) for bustage on a CLOSED TREE --- gfx/thebes/gfxWindowsPlatform.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 56e34231893..14a146287bb 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -32,7 +32,6 @@ #include "gfxGDIFont.h" #include "mozilla/layers/CompositorParent.h" // for CompositorParent::IsInCompositorThread -#include "mozilla/IntegerPrintfMacros.h" #include "DeviceManagerD3D9.h" #include "mozilla/layers/ReadbackManagerD3D11.h" @@ -1523,9 +1522,6 @@ bool DoesD3D11DeviceWork(ID3D11Device *device) checked = true; if (GetModuleHandleW(L"dlumd32.dll") && GetModuleHandleW(L"igd10umd32.dll")) { -#if defined(MOZ_CRASHREPORTER) - CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: detected\n")); -#endif nsString displayLinkModuleVersionString; gfxWindowsPlatform::GetDLLVersion(L"dlumd32.dll", displayLinkModuleVersionString); uint64_t displayLinkModuleVersion; @@ -1535,11 +1531,6 @@ bool DoesD3D11DeviceWork(ID3D11Device *device) #endif return false; } -#if defined(MOZ_CRASHREPORTER) - nsPrintfCString displayLinkInfo("Version: " PRIx64 "\n", displayLinkModuleVersion); - CrashReporter::AppendAppNotesToCrashReport(displayLinkInfo); -#endif - if (displayLinkModuleVersion <= GFX_DRIVER_VERSION(8,6,1,36484)) { #if defined(MOZ_CRASHREPORTER) CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: too old version\n")); From 31684fffbcda113c9c96dca2f5c0c78f28836587 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 10 Nov 2014 13:18:40 -0800 Subject: [PATCH 06/71] Backed out changeset 992ad9a82996 (bug 1085175) for bustage on a CLOSED TREE --- dom/media/MediaCache.cpp | 33 ++++++++--------------- media/libnestegg/include/nestegg-stdint.h | 1 - media/libnestegg/src/nestegg.c | 3 --- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/dom/media/MediaCache.cpp b/dom/media/MediaCache.cpp index e45c6b9c612..1421a07ba11 100644 --- a/dom/media/MediaCache.cpp +++ b/dom/media/MediaCache.cpp @@ -1173,7 +1173,6 @@ MediaCache::Update() // Figure out where we should be reading from. It's the first // uncached byte after the current mStreamOffset. int64_t dataOffset = stream->GetCachedDataEndInternal(stream->mStreamOffset); - MOZ_ASSERT(dataOffset >= 0); // Compute where we'd actually seek to to read at readOffset int64_t desiredOffset = dataOffset; @@ -1706,7 +1705,6 @@ MediaCacheStream::NotifyDataStarted(int64_t aOffset) ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor()); NS_WARN_IF_FALSE(aOffset == mChannelOffset, "Server is giving us unexpected offset"); - MOZ_ASSERT(aOffset >= 0); mChannelOffset = aOffset; if (mStreamLength >= 0) { // If we started reading at a certain offset, then for sure @@ -2136,28 +2134,23 @@ MediaCacheStream::Seek(int32_t aWhence, int64_t aOffset) return NS_ERROR_FAILURE; int64_t oldOffset = mStreamOffset; - int64_t newOffset = mStreamOffset; switch (aWhence) { case PR_SEEK_END: if (mStreamLength < 0) return NS_ERROR_FAILURE; - newOffset = mStreamLength + aOffset; + mStreamOffset = mStreamLength + aOffset; break; case PR_SEEK_CUR: - newOffset += aOffset; + mStreamOffset += aOffset; break; case PR_SEEK_SET: - newOffset = aOffset; + mStreamOffset = aOffset; break; default: NS_ERROR("Unknown whence"); return NS_ERROR_FAILURE; } - if (newOffset < 0) - return NS_ERROR_FAILURE; - mStreamOffset = newOffset; - CACHE_LOG(PR_LOG_DEBUG, ("Stream %p Seek to %lld", this, (long long)mStreamOffset)); gMediaCache->NoteSeek(this, oldOffset); @@ -2199,10 +2192,11 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) break; } size = std::min(size, bytesRemaining); - // Clamp size until 64-bit file size issues are fixed. + // Clamp size until 64-bit file size issues (bug 500784) are fixed. size = std::min(size, int64_t(INT32_MAX)); } + int32_t bytes; int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1; if (cacheBlock < 0) { // We don't have a complete cached block here. @@ -2230,10 +2224,7 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) // We can just use the data in mPartialBlockBuffer. In fact we should // use it rather than waiting for the block to fill and land in // the cache. - int64_t bytes = std::min(size, streamWithPartialBlock->mChannelOffset - mStreamOffset); - // Clamp bytes until 64-bit file size issues are fixed. - bytes = std::min(bytes, int64_t(INT32_MAX)); - NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= aCount, "Bytes out of range."); + bytes = std::min(size, streamWithPartialBlock->mChannelOffset - mStreamOffset); memcpy(aBuffer, reinterpret_cast(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes); if (mCurrentMode == MODE_METADATA) { @@ -2257,7 +2248,6 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) gMediaCache->NoteBlockUsage(this, cacheBlock, mCurrentMode, TimeStamp::Now()); int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock; - int32_t bytes; NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range."); nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes); if (NS_FAILED(rv)) { @@ -2294,7 +2284,9 @@ MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer, } nsresult -MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount) +MediaCacheStream::ReadFromCache(char* aBuffer, + int64_t aOffset, + int64_t aCount) { ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor()); if (mClosed) @@ -2316,7 +2308,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount) return NS_ERROR_FAILURE; } size = std::min(size, bytesRemaining); - // Clamp size until 64-bit file size issues are fixed. + // Clamp size until 64-bit file size issues (bug 500784) are fixed. size = std::min(size, int64_t(INT32_MAX)); } @@ -2327,10 +2319,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount) // We can just use the data in mPartialBlockBuffer. In fact we should // use it rather than waiting for the block to fill and land in // the cache. - // Clamp bytes until 64-bit file size issues are fixed. - int64_t toCopy = std::min(size, mChannelOffset - streamOffset); - bytes = std::min(toCopy, int64_t(INT32_MAX)); - NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= toCopy, "Bytes out of range."); + bytes = std::min(size, mChannelOffset - streamOffset); memcpy(aBuffer + count, reinterpret_cast(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes); } else { diff --git a/media/libnestegg/include/nestegg-stdint.h b/media/libnestegg/include/nestegg-stdint.h index 111db72b025..599a7a5fadd 100644 --- a/media/libnestegg/include/nestegg-stdint.h +++ b/media/libnestegg/include/nestegg-stdint.h @@ -1,7 +1,6 @@ #ifdef _WIN32 typedef __int64 int64_t; typedef unsigned __int64 uint64_t; -#define INT64_MAX 9223372036854775807LL #else #include #endif diff --git a/media/libnestegg/src/nestegg.c b/media/libnestegg/src/nestegg.c index e281f44f694..6c0c3e8b3be 100644 --- a/media/libnestegg/src/nestegg.c +++ b/media/libnestegg/src/nestegg.c @@ -2106,9 +2106,6 @@ nestegg_offset_seek(nestegg * ctx, uint64_t offset) { int r; - if (offset > INT64_MAX) - return -1; - /* Seek and set up parser state for segment-level element (Cluster). */ r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET); if (r != 0) From da40c53ff4f41583def53997a7d4b6bde44789ec Mon Sep 17 00:00:00 2001 From: Blake Date: Mon, 10 Nov 2014 11:54:08 +0800 Subject: [PATCH 07/71] Bug 1082545 - Make fastSeek always fast. r=sotaro --HG-- extra : rebase_source : 4e12b971b2ee18931a54d30d51fc71437e095cdd --- dom/media/omx/OmxDecoder.cpp | 49 ++++++++++++++++++++++++++++++------ dom/media/omx/OmxDecoder.h | 2 ++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/dom/media/omx/OmxDecoder.cpp b/dom/media/omx/OmxDecoder.cpp index d623a93c3ba..ee5e09197c9 100644 --- a/dom/media/omx/OmxDecoder.cpp +++ b/dom/media/omx/OmxDecoder.cpp @@ -33,6 +33,10 @@ #include "OMXCodecProxy.h" #include "OmxDecoder.h" +#define LOG_TAG "OmxDecoder" +#include +#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) + #ifdef PR_LOGGING PRLogModuleInfo *gOmxDecoderLog; #define LOG(type, msg...) PR_LOG(gOmxDecoderLog, type, (msg)) @@ -66,7 +70,8 @@ OmxDecoder::OmxDecoder(MediaResource *aResource, mIsVideoSeeking(false), mAudioMetadataRead(false), mAudioPaused(false), - mVideoPaused(false) + mVideoPaused(false), + mVideoLastFrameTime(-1) { mLooper = new ALooper; mLooper->setName("OmxDecoder"); @@ -556,14 +561,43 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs, mIsVideoSeeking = true; } MediaSource::ReadOptions options; - options.setSeekTo(aTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); - err = mVideoSource->read(&mVideoBuffer, &options); - { - Mutex::Autolock autoLock(mSeekLock); - mIsVideoSeeking = false; - PostReleaseVideoBuffer(nullptr, FenceHandle()); + MediaSource::ReadOptions::SeekMode seekMode; + // If the last timestamp of decoded frame is smaller than seekTime, + // seek to next key frame. Otherwise seek to the previos one. + if (mVideoLastFrameTime > aTimeUs || mVideoLastFrameTime == -1) { + seekMode = MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; + } else { + seekMode = MediaSource::ReadOptions::SEEK_NEXT_SYNC; } + bool findNextBuffer = true; + while (findNextBuffer) { + options.setSeekTo(aTimeUs, seekMode); + findNextBuffer = false; + err = mVideoSource->read(&mVideoBuffer, &options); + { + Mutex::Autolock autoLock(mSeekLock); + mIsVideoSeeking = false; + PostReleaseVideoBuffer(nullptr, FenceHandle()); + } + // If there is no next Keyframe, jump to the previous key frame. + if (err == ERROR_END_OF_STREAM && seekMode == MediaSource::ReadOptions::SEEK_NEXT_SYNC) { + seekMode = MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; + findNextBuffer = true; + { + Mutex::Autolock autoLock(mSeekLock); + mIsVideoSeeking = true; + } + continue; + } else if (err != OK) { + ALOG("Unexpected error when seeking to %lld", aTimeUs); + break; + } + if (mVideoBuffer->range_length() == 0) { + ReleaseVideoBuffer(); + findNextBuffer = true; + } + } aDoSeek = false; } else { err = mVideoSource->read(&mVideoBuffer); @@ -635,6 +669,7 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs, if ((aKeyframeSkip && timeUs < aTimeUs) || length == 0) { aFrame->mShouldSkip = true; } + mVideoLastFrameTime = timeUs; } else if (err == INFO_FORMAT_CHANGED) { // If the format changed, update our cached info. diff --git a/dom/media/omx/OmxDecoder.h b/dom/media/omx/OmxDecoder.h index a2f3bb6d561..c5c6e2c3192 100644 --- a/dom/media/omx/OmxDecoder.h +++ b/dom/media/omx/OmxDecoder.h @@ -60,6 +60,8 @@ class OmxDecoder : public OMXCodecProxy::EventListener { int32_t mAudioChannels; int32_t mAudioSampleRate; int64_t mDurationUs; + int64_t mVideoLastFrameTime; + VideoFrame mVideoFrame; AudioFrame mAudioFrame; MP3FrameParser mMP3FrameParser; From 2f2f7fc544741c42af659500bed3cbb2440fe4a9 Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Mon, 10 Nov 2014 02:03:00 -0500 Subject: [PATCH 08/71] Bug 1092888 - Part 1: Remove preference for selection carets with non-editable fields support. r=roc --HG-- extra : rebase_source : 23e1c11c1a89a5e5fa4d80af6abace7d1c7e2012 --- layout/base/SelectionCarets.cpp | 23 ----------------------- modules/libpref/init/all.js | 1 - 2 files changed, 24 deletions(-) diff --git a/layout/base/SelectionCarets.cpp b/layout/base/SelectionCarets.cpp index 6c6437b8192..d5554b492b0 100644 --- a/layout/base/SelectionCarets.cpp +++ b/layout/base/SelectionCarets.cpp @@ -62,13 +62,6 @@ static const char* kSelectionCaretsLogModuleName = "SelectionCarets"; static const int32_t kMoveStartTolerancePx = 5; // Time for trigger scroll end event, in miliseconds. static const int32_t kScrollEndTimerDelay = 300; -// Read from preference "selectioncaret.noneditable". Indicate whether support -// non-editable fields selection or not. We have stable state for editable -// fields selection now. And we don't want to break this stable state when -// enabling non-editable support. So I add a pref to control to support or -// not. Once non-editable fields support is stable. We should remove this -// pref. -static bool kSupportNonEditableFields = false; NS_IMPL_ISUPPORTS(SelectionCarets, nsIReflowObserver, @@ -102,8 +95,6 @@ SelectionCarets::SelectionCarets(nsIPresShell* aPresShell) if (!addedPref) { Preferences::AddIntVarCache(&sSelectionCaretsInflateSize, "selectioncaret.inflatesize.threshold"); - Preferences::AddBoolVarCache(&kSupportNonEditableFields, - "selectioncaret.noneditable"); addedPref = true; } } @@ -502,14 +493,6 @@ SelectionCarets::UpdateSelectionCarets() return; } - // If frame isn't editable and we don't support non-editable fields, bail - // out. - if (!kSupportNonEditableFields && - (!startFrame->GetContent()->IsEditable() || - !endFrame->GetContent()->IsEditable())) { - return; - } - // Check if startFrame is after endFrame. if (nsLayoutUtils::CompareTreePosition(startFrame, endFrame) > 0) { SetVisibility(false); @@ -615,12 +598,6 @@ SelectionCarets::SelectWord() return NS_OK; } - // If frame isn't editable and we don't support non-editable fields, bail - // out. - if (!kSupportNonEditableFields && !ptFrame->GetContent()->IsEditable()) { - return NS_OK; - } - nsPoint ptInFrame = mDownPoint; nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 767f1b9bf72..733c33ae2c2 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4364,7 +4364,6 @@ pref("touchcaret.expiration.time", 3000); // Turn off selection caret by default pref("selectioncaret.enabled", false); -pref("selectioncaret.noneditable", false); // This will inflate size of selection caret frame when we checking if // user click on selection caret or not. In app units. From b7bd9a936cc93e2b29cbc4506eaa3fb5770a8efb Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Mon, 10 Nov 2014 02:04:00 -0500 Subject: [PATCH 09/71] Bug 1092888 - Part 2: Check pointer of FrameSelection and Selection is valid. r=roc --HG-- extra : rebase_source : 9e343626d67f6d9d4435535e3d10535ca1006cf0 --- layout/base/SelectionCarets.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/layout/base/SelectionCarets.cpp b/layout/base/SelectionCarets.cpp index d5554b492b0..434999e1c81 100644 --- a/layout/base/SelectionCarets.cpp +++ b/layout/base/SelectionCarets.cpp @@ -480,6 +480,11 @@ SelectionCarets::UpdateSelectionCarets() // Check start and end frame is rtl or ltr text nsRefPtr fs = GetFrameSelection(); + if (!fs) { + SetVisibility(false); + return; + } + int32_t startOffset; nsIFrame* startFrame = FindFirstNodeWithFrame(mPresShell->GetDocument(), firstRange, fs, false, startOffset); @@ -637,7 +642,9 @@ SelectionCarets::SelectWord() // Clear maintain selection otherwise we cannot select less than a word nsRefPtr fs = GetFrameSelection(); - fs->MaintainSelection(); + if (fs) { + fs->MaintainSelection(); + } return rs; } @@ -727,6 +734,9 @@ SelectionCarets::DragSelection(const nsPoint &movePoint) } nsRefPtr fs = GetFrameSelection(); + if (!fs) { + return nsEventStatus_eConsumeNoDefault; + } nsresult result; nsIFrame *newFrame = nullptr; @@ -751,6 +761,10 @@ SelectionCarets::DragSelection(const nsPoint &movePoint) } nsRefPtr selection = GetSelection(); + if (!selection) { + return nsEventStatus_eConsumeNoDefault; + } + int32_t rangeCount = selection->GetRangeCount(); if (rangeCount <= 0) { return nsEventStatus_eConsumeNoDefault; @@ -801,12 +815,19 @@ SelectionCarets::GetCaretYCenterPosition() } nsRefPtr selection = GetSelection(); + if (!selection) { + return 0; + } + int32_t rangeCount = selection->GetRangeCount(); if (rangeCount <= 0) { return 0; } nsRefPtr fs = GetFrameSelection(); + if (!fs) { + return 0; + } MOZ_ASSERT(mDragMode != NONE); nsCOMPtr node; @@ -839,14 +860,18 @@ void SelectionCarets::SetSelectionDragState(bool aState) { nsRefPtr fs = GetFrameSelection(); - fs->SetDragState(aState); + if (fs) { + fs->SetDragState(aState); + } } void SelectionCarets::SetSelectionDirection(bool aForward) { nsRefPtr selection = GetSelection(); - selection->SetDirection(aForward ? eDirNext : eDirPrevious); + if (selection) { + selection->SetDirection(aForward ? eDirNext : eDirPrevious); + } } static void From b9246cdc96791dc06b6e10cf4786ae9b4abac78a Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Mon, 10 Nov 2014 02:04:00 -0500 Subject: [PATCH 10/71] Bug 1092888 - Part 3: Fix test fails on 824080-1/3/4/5.html. r=roc --HG-- extra : rebase_source : b9e1b6289275cb34067cf1dca71a258de7379a95 --- editor/reftests/reftest.list | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/reftests/reftest.list b/editor/reftests/reftest.list index 835ca50fb17..345c1308897 100644 --- a/editor/reftests/reftest.list +++ b/editor/reftests/reftest.list @@ -98,12 +98,12 @@ skip-if(Android||B2G) needs-focus == 462758-grabbers-resizers.html 462758-grabbe == 388980-1.html 388980-1-ref.html needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html skip-if(B2G) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658 -needs-focus == 824080-1.html 824080-1-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-1.html 824080-1-ref.html needs-focus == 824080-2.html 824080-2-ref.html -needs-focus test-pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html needs-focus != 824080-2.html 824080-3.html -needs-focus == 824080-4.html 824080-4-ref.html -needs-focus test-pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-4.html 824080-4-ref.html +needs-focus pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html needs-focus != 824080-4.html 824080-5.html needs-focus == 824080-6.html 824080-6-ref.html needs-focus pref(selectioncaret.enabled,false) == 824080-7.html 824080-7-ref.html From 6188305b3355cc1471b7c41a530e72193a55a4aa Mon Sep 17 00:00:00 2001 From: David Major Date: Tue, 11 Nov 2014 10:31:13 +1300 Subject: [PATCH 11/71] Bug 1096155: Report the correct OOM size when the caller doesn't specify a length. r=froydnj --HG-- extra : rebase_source : 437d3acc69b0940cf388039a318eda7d9d27e082 --- xpcom/string/nsTSubstring.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xpcom/string/nsTSubstring.cpp b/xpcom/string/nsTSubstring.cpp index 5780e342a40..dad0f08bdf9 100644 --- a/xpcom/string/nsTSubstring.cpp +++ b/xpcom/string/nsTSubstring.cpp @@ -292,7 +292,8 @@ void nsTSubstring_CharT::Assign(const char_type* aData, size_type aLength) { if (!Assign(aData, aLength, fallible_t())) { - NS_ABORT_OOM(aLength); + NS_ABORT_OOM(aLength == size_type(-1) ? char_traits::length(aData) + : aLength); } } From 56d56896292263cf511cf31c30e549c8defc35a8 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 7 Nov 2014 14:44:12 -0500 Subject: [PATCH 12/71] Bug 1095633 - part 1 - remove uses of HAVE_CPP_TROUBLE_COMPARING_TO_ZERO from headers; r=bz --- parser/html/nsHtml5RefPtr.h | 26 --------------------- xpcom/base/nsAutoPtr.h | 46 ------------------------------------- xpcom/base/nsRefPtr.h | 23 ------------------- xpcom/glue/nsCOMPtr.h | 23 ------------------- 4 files changed, 118 deletions(-) diff --git a/parser/html/nsHtml5RefPtr.h b/parser/html/nsHtml5RefPtr.h index 3b24b1a140b..b27c9dea520 100644 --- a/parser/html/nsHtml5RefPtr.h +++ b/parser/html/nsHtml5RefPtr.h @@ -450,30 +450,4 @@ operator!=( NSCAP_Zero* lhs, const nsHtml5RefPtr& rhs ) return reinterpret_cast(lhs) != static_cast(rhs.get()); } - -#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO - - // We need to explicitly define comparison operators for `int' - // because the compiler is lame. - -template -inline -bool -operator==( const nsHtml5RefPtr& lhs, int rhs ) - // specifically to allow |smartPtr == 0| - { - return static_cast(lhs.get()) == reinterpret_cast(rhs); - } - -template -inline -bool -operator==( int lhs, const nsHtml5RefPtr& rhs ) - // specifically to allow |0 == smartPtr| - { - return reinterpret_cast(lhs) == static_cast(rhs.get()); - } - -#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) - #endif // !defined(nsHtml5RefPtr_h) diff --git a/xpcom/base/nsAutoPtr.h b/xpcom/base/nsAutoPtr.h index a7d86b96d0d..d5710ac82c1 100644 --- a/xpcom/base/nsAutoPtr.h +++ b/xpcom/base/nsAutoPtr.h @@ -407,29 +407,6 @@ operator!=(NSCAP_Zero* aLhs, const nsAutoPtr& aRhs) } -#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO - -// We need to explicitly define comparison operators for `int' -// because the compiler is lame. - -template -inline bool -operator==(const nsAutoPtr& aLhs, int aRhs) -// specifically to allow |smartPtr == 0| -{ - return static_cast(aLhs.get()) == reinterpret_cast(aRhs); -} - -template -inline bool -operator==(int aLhs, const nsAutoPtr& aRhs) -// specifically to allow |0 == smartPtr| -{ - return reinterpret_cast(aLhs) == static_cast(aRhs.get()); -} - -#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) - /*****************************************************************************/ // template class nsAutoArrayPtrGetterTransfers; @@ -782,29 +759,6 @@ operator!=(NSCAP_Zero* aLhs, const nsAutoArrayPtr& aRhs) } -#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO - -// We need to explicitly define comparison operators for `int' -// because the compiler is lame. - -template -inline bool -operator==(const nsAutoArrayPtr& aLhs, int aRhs) -// specifically to allow |smartPtr == 0| -{ - return static_cast(aLhs.get()) == reinterpret_cast(aRhs); -} - -template -inline bool -operator==(int aLhs, const nsAutoArrayPtr& aRhs) -// specifically to allow |0 == smartPtr| -{ - return reinterpret_cast(aLhs) == static_cast(aRhs.get()); -} - -#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) - /*****************************************************************************/ template diff --git a/xpcom/base/nsRefPtr.h b/xpcom/base/nsRefPtr.h index a96483ed9fd..de4895c6fb0 100644 --- a/xpcom/base/nsRefPtr.h +++ b/xpcom/base/nsRefPtr.h @@ -502,29 +502,6 @@ operator!=(NSCAP_Zero* aLhs, const nsRefPtr& aRhs) } -#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO - -// We need to explicitly define comparison operators for `int' -// because the compiler is lame. - -template -inline bool -operator==(const nsRefPtr& aLhs, int aRhs) -// specifically to allow |smartPtr == 0| -{ - return static_cast(aLhs.get()) == reinterpret_cast(aRhs); -} - -template -inline bool -operator==(int aLhs, const nsRefPtr& aRhs) -// specifically to allow |0 == smartPtr| -{ - return reinterpret_cast(aLhs) == static_cast(aRhs.get()); -} - -#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) - template inline nsresult CallQueryInterface(nsRefPtr& aSourcePtr, DestinationType** aDestPtr) diff --git a/xpcom/glue/nsCOMPtr.h b/xpcom/glue/nsCOMPtr.h index 724a22ca876..240b11e7e12 100644 --- a/xpcom/glue/nsCOMPtr.h +++ b/xpcom/glue/nsCOMPtr.h @@ -1482,29 +1482,6 @@ operator!=(NSCAP_Zero* aLhs, const nsCOMPtr& aRhs) } -#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO - -// We need to explicitly define comparison operators for `int' -// because the compiler is lame. - -// Specifically to allow |smartPtr == 0|. -template -inline bool -operator==(const nsCOMPtr& lhs, int rhs) -{ - return static_cast(lhs.get()) == reinterpret_cast(rhs); -} - -// Specifically to allow |0 == smartPtr|. -template -inline bool -operator==(int lhs, const nsCOMPtr& rhs) -{ - return reinterpret_cast(lhs) == static_cast(rhs.get()); -} - -#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) - // Comparing any two [XP]COM objects for identity inline bool From d27be95ebce12b6fa04f2d848295ff8e7cb92e51 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 7 Nov 2014 14:08:13 -0500 Subject: [PATCH 13/71] Bug 1095633 - part 2 - remove HAVE_CPP_TROUBLE_COMPARING_TO_ZERO bits from the build system; r=mshal --- configure.in | 19 ------------------- js/src/configure.in | 18 ------------------ xpcom/xpcom-config.h.in | 5 ----- 3 files changed, 42 deletions(-) diff --git a/configure.in b/configure.in index 5a7f0d09608..4eed7697d76 100644 --- a/configure.in +++ b/configure.in @@ -3297,24 +3297,6 @@ if test "$ac_cv_cpp_unused_required" = yes ; then fi -dnl Some compilers have trouble comparing a constant reference to a templatized -dnl class to zero, and require an explicit operator==() to be defined that takes -dnl an int. This test separates the strong from the weak. - -AC_CACHE_CHECK(for trouble comparing to zero near std::operator!=(), - ac_cv_trouble_comparing_to_zero, - [AC_TRY_COMPILE([#include - template class Foo {}; - class T2; - template int operator==(const T2*, const T&) { return 0; } - template int operator!=(const T2*, const T&) { return 0; }], - [Foo f; return (0 != f);], - ac_cv_trouble_comparing_to_zero=no, - ac_cv_trouble_comparing_to_zero=yes)]) -if test "$ac_cv_trouble_comparing_to_zero" = yes ; then - AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) -fi - # try harder, when checking for __thread support, see bug 521750 comment #33 and below # We pass MOZ_OPTIMIZE_LDFLAGS to the linker because if dead_strip is # enabled, the linker in xcode 4.1 will crash. Without this it would crash when @@ -9039,7 +9021,6 @@ CPP_THROW_NEW HAVE_CPP_AMBIGUITY_RESOLVING_USING HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR HAVE_CPP_PARTIAL_SPECIALIZATION -HAVE_CPP_TROUBLE_COMPARING_TO_ZERO NEED_CPP_UNUSED_IMPLEMENTATIONS HAVE_GETPAGESIZE HAVE_ICONV diff --git a/js/src/configure.in b/js/src/configure.in index 658dd7477b2..690e5c8df35 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2664,24 +2664,6 @@ if test "$ac_cv_cpp_unused_required" = yes ; then fi -dnl Some compilers have trouble comparing a constant reference to a templatized -dnl class to zero, and require an explicit operator==() to be defined that takes -dnl an int. This test separates the strong from the weak. - -AC_CACHE_CHECK(for trouble comparing to zero near std::operator!=(), - ac_cv_trouble_comparing_to_zero, - [AC_TRY_COMPILE([#include - template class Foo {}; - class T2; - template int operator==(const T2*, const T&) { return 0; } - template int operator!=(const T2*, const T&) { return 0; }], - [Foo f; return (0 != f);], - ac_cv_trouble_comparing_to_zero=no, - ac_cv_trouble_comparing_to_zero=yes)]) -if test "$ac_cv_trouble_comparing_to_zero" = yes ; then - AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) -fi - # try harder, when checking for __thread support, see bug 521750 comment #33 and below # We pass MOZ_OPTIMIZE_LDFLAGS to the linker because if dead_strip is # enabled, the linker in xcode 4.1 will crash. Without this it would crash when diff --git a/xpcom/xpcom-config.h.in b/xpcom/xpcom-config.h.in index eb101c18e9b..2b6881fbf35 100644 --- a/xpcom/xpcom-config.h.in +++ b/xpcom/xpcom-config.h.in @@ -18,11 +18,6 @@ /* Define if a dyanmic_cast to void* gives the most derived object */ #undef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR -/* Define if the c++ compiler has trouble comparing a constant - * reference to a templatized class to zero - */ -#undef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO - /* Define if the c++ compiler requires implementations of * unused virtual methods */ From ee1928513d093bc815d9b636f940c5abad251571 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Tue, 11 Nov 2014 08:58:52 +1300 Subject: [PATCH 14/71] Bug 1085175 - r=roc --HG-- extra : rebase_source : 78e0e0b21c6bb049f9112fdb3f25639c69289dd1 --- dom/media/MediaCache.cpp | 33 +++++++++++++++-------- media/libnestegg/include/nestegg-stdint.h | 3 +++ media/libnestegg/src/nestegg.c | 3 +++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/dom/media/MediaCache.cpp b/dom/media/MediaCache.cpp index 1421a07ba11..e45c6b9c612 100644 --- a/dom/media/MediaCache.cpp +++ b/dom/media/MediaCache.cpp @@ -1173,6 +1173,7 @@ MediaCache::Update() // Figure out where we should be reading from. It's the first // uncached byte after the current mStreamOffset. int64_t dataOffset = stream->GetCachedDataEndInternal(stream->mStreamOffset); + MOZ_ASSERT(dataOffset >= 0); // Compute where we'd actually seek to to read at readOffset int64_t desiredOffset = dataOffset; @@ -1705,6 +1706,7 @@ MediaCacheStream::NotifyDataStarted(int64_t aOffset) ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor()); NS_WARN_IF_FALSE(aOffset == mChannelOffset, "Server is giving us unexpected offset"); + MOZ_ASSERT(aOffset >= 0); mChannelOffset = aOffset; if (mStreamLength >= 0) { // If we started reading at a certain offset, then for sure @@ -2134,23 +2136,28 @@ MediaCacheStream::Seek(int32_t aWhence, int64_t aOffset) return NS_ERROR_FAILURE; int64_t oldOffset = mStreamOffset; + int64_t newOffset = mStreamOffset; switch (aWhence) { case PR_SEEK_END: if (mStreamLength < 0) return NS_ERROR_FAILURE; - mStreamOffset = mStreamLength + aOffset; + newOffset = mStreamLength + aOffset; break; case PR_SEEK_CUR: - mStreamOffset += aOffset; + newOffset += aOffset; break; case PR_SEEK_SET: - mStreamOffset = aOffset; + newOffset = aOffset; break; default: NS_ERROR("Unknown whence"); return NS_ERROR_FAILURE; } + if (newOffset < 0) + return NS_ERROR_FAILURE; + mStreamOffset = newOffset; + CACHE_LOG(PR_LOG_DEBUG, ("Stream %p Seek to %lld", this, (long long)mStreamOffset)); gMediaCache->NoteSeek(this, oldOffset); @@ -2192,11 +2199,10 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) break; } size = std::min(size, bytesRemaining); - // Clamp size until 64-bit file size issues (bug 500784) are fixed. + // Clamp size until 64-bit file size issues are fixed. size = std::min(size, int64_t(INT32_MAX)); } - int32_t bytes; int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1; if (cacheBlock < 0) { // We don't have a complete cached block here. @@ -2224,7 +2230,10 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) // We can just use the data in mPartialBlockBuffer. In fact we should // use it rather than waiting for the block to fill and land in // the cache. - bytes = std::min(size, streamWithPartialBlock->mChannelOffset - mStreamOffset); + int64_t bytes = std::min(size, streamWithPartialBlock->mChannelOffset - mStreamOffset); + // Clamp bytes until 64-bit file size issues are fixed. + bytes = std::min(bytes, int64_t(INT32_MAX)); + NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= aCount, "Bytes out of range."); memcpy(aBuffer, reinterpret_cast(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes); if (mCurrentMode == MODE_METADATA) { @@ -2248,6 +2257,7 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) gMediaCache->NoteBlockUsage(this, cacheBlock, mCurrentMode, TimeStamp::Now()); int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock; + int32_t bytes; NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range."); nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes); if (NS_FAILED(rv)) { @@ -2284,9 +2294,7 @@ MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer, } nsresult -MediaCacheStream::ReadFromCache(char* aBuffer, - int64_t aOffset, - int64_t aCount) +MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount) { ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor()); if (mClosed) @@ -2308,7 +2316,7 @@ MediaCacheStream::ReadFromCache(char* aBuffer, return NS_ERROR_FAILURE; } size = std::min(size, bytesRemaining); - // Clamp size until 64-bit file size issues (bug 500784) are fixed. + // Clamp size until 64-bit file size issues are fixed. size = std::min(size, int64_t(INT32_MAX)); } @@ -2319,7 +2327,10 @@ MediaCacheStream::ReadFromCache(char* aBuffer, // We can just use the data in mPartialBlockBuffer. In fact we should // use it rather than waiting for the block to fill and land in // the cache. - bytes = std::min(size, mChannelOffset - streamOffset); + // Clamp bytes until 64-bit file size issues are fixed. + int64_t toCopy = std::min(size, mChannelOffset - streamOffset); + bytes = std::min(toCopy, int64_t(INT32_MAX)); + NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= toCopy, "Bytes out of range."); memcpy(aBuffer + count, reinterpret_cast(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes); } else { diff --git a/media/libnestegg/include/nestegg-stdint.h b/media/libnestegg/include/nestegg-stdint.h index 599a7a5fadd..c3159919c2d 100644 --- a/media/libnestegg/include/nestegg-stdint.h +++ b/media/libnestegg/include/nestegg-stdint.h @@ -1,6 +1,9 @@ #ifdef _WIN32 typedef __int64 int64_t; typedef unsigned __int64 uint64_t; +#if !defined(INT64_MAX) +#define INT64_MAX 9223372036854775807LL +#endif #else #include #endif diff --git a/media/libnestegg/src/nestegg.c b/media/libnestegg/src/nestegg.c index 6c0c3e8b3be..e281f44f694 100644 --- a/media/libnestegg/src/nestegg.c +++ b/media/libnestegg/src/nestegg.c @@ -2106,6 +2106,9 @@ nestegg_offset_seek(nestegg * ctx, uint64_t offset) { int r; + if (offset > INT64_MAX) + return -1; + /* Seek and set up parser state for segment-level element (Cluster). */ r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET); if (r != 0) From 62c082d4544cccaeedbe0968beb4562e5caa7dc9 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 10 Nov 2014 16:11:42 -0500 Subject: [PATCH 15/71] Bug 1021265. Fix DisplayLink version expansion code. r=Bas,a=lawrence GFX_DRIVER_VERSION(8,6,..) expands to 8.0006.... but ParseVersion(8.6,...) gives 8.5000... This was an unfortunate error. Having better static typing of versions would have helped here. --HG-- extra : rebase_source : 8eb9fc7d337a017b350e6ef1935f99fd4383114d --- gfx/thebes/gfxWindowsPlatform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 14a146287bb..9ac5d43a3c2 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -1531,7 +1531,7 @@ bool DoesD3D11DeviceWork(ID3D11Device *device) #endif return false; } - if (displayLinkModuleVersion <= GFX_DRIVER_VERSION(8,6,1,36484)) { + if (displayLinkModuleVersion <= V(8,6,1,36484)) { #if defined(MOZ_CRASHREPORTER) CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: too old version\n")); #endif From cb094a2eedd91587c61ef3d27ca60da675e677ea Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Mon, 10 Nov 2014 13:37:49 -0800 Subject: [PATCH 16/71] Bug 1091229 - Make nsBulletFrame block onload when it loads images. r=tn --HG-- extra : rebase_source : e6b4ed67cab9d0d674a6a5f194c14c7362723440 --- layout/generic/nsBulletFrame.cpp | 169 +++++++++++++++++----- layout/generic/nsBulletFrame.h | 22 ++- layout/reftests/svg/as-image/reftest.list | 2 +- 3 files changed, 154 insertions(+), 39 deletions(-) diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index 8d8c9584643..0ab19749e45 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -12,6 +12,7 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/PathHelpers.h" #include "mozilla/MathAlgorithms.h" +#include "mozilla/Move.h" #include "nsCOMPtr.h" #include "nsFontMetrics.h" #include "nsGkAtoms.h" @@ -51,20 +52,14 @@ NS_QUERYFRAME_TAIL_INHERITING(nsFrame) nsBulletFrame::~nsBulletFrame() { + NS_ASSERTION(!mBlockingOnload, "Still blocking onload in destructor?"); } void nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot) { - // Stop image loading first - if (mImageRequest) { - // Deregister our image request from the refresh driver - nsLayoutUtils::DeregisterImageRequest(PresContext(), - mImageRequest, - &mRequestRegistered); - mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE); - mImageRequest = nullptr; - } + // Stop image loading first. + DeregisterAndCancelImageRequest(); if (mListener) { mListener->SetFrame(nullptr); @@ -132,35 +127,21 @@ nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) } if (needNewRequest) { - nsRefPtr oldRequest = mImageRequest; - newRequest->Clone(mListener, getter_AddRefs(mImageRequest)); + nsRefPtr newRequestClone; + newRequest->Clone(mListener, getter_AddRefs(newRequestClone)); // Deregister the old request. We wait until after Clone is done in case // the old request and the new request are the same underlying image // accessed via different URLs. - if (oldRequest) { - nsLayoutUtils::DeregisterImageRequest(PresContext(), oldRequest, - &mRequestRegistered); - oldRequest->CancelAndForgetObserver(NS_ERROR_FAILURE); - oldRequest = nullptr; - } + DeregisterAndCancelImageRequest(); // Register the new request. - if (mImageRequest) { - nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(), - mImageRequest, - &mRequestRegistered); - } + mImageRequest = Move(newRequestClone); + RegisterImageRequest(/* aKnownToBeAnimated = */ false); } } else { - // No image request on the new style context - if (mImageRequest) { - nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest, - &mRequestRegistered); - - mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE); - mImageRequest = nullptr; - } + // No image request on the new style context. + DeregisterAndCancelImageRequest(); } #ifdef ACCESSIBILITY @@ -692,14 +673,67 @@ nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aDa // Register the image request with the refresh driver now that we know it's // animated. if (aRequest == mImageRequest) { - nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest, - &mRequestRegistered); + RegisterImageRequest(/* aKnownToBeAnimated = */ true); } } + if (aType == imgINotificationObserver::LOAD_COMPLETE) { + // Unconditionally start decoding for now. + // XXX(seth): We eventually want to decide whether to do this based on + // visibility. We should get that for free from bug 1091236. + if (aRequest == mImageRequest) { + mImageRequest->RequestDecode(); + } + InvalidateFrame(); + } + return NS_OK; } +NS_IMETHODIMP +nsBulletFrame::BlockOnload(imgIRequest* aRequest) +{ + if (aRequest != mImageRequest) { + return NS_OK; + } + + NS_ASSERTION(!mBlockingOnload, "Double BlockOnload for an nsBulletFrame?"); + + nsIDocument* doc = GetOurCurrentDoc(); + if (doc) { + mBlockingOnload = true; + doc->BlockOnload(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsBulletFrame::UnblockOnload(imgIRequest* aRequest) +{ + if (aRequest != mImageRequest) { + return NS_OK; + } + + NS_ASSERTION(!mBlockingOnload, "Double UnblockOnload for an nsBulletFrame?"); + + nsIDocument* doc = GetOurCurrentDoc(); + if (doc) { + doc->UnblockOnload(false); + } + mBlockingOnload = false; + + return NS_OK; +} + +nsIDocument* +nsBulletFrame::GetOurCurrentDoc() const +{ + nsIContent* parentContent = GetParent()->GetContent(); + return parentContent ? parentContent->GetComposedDoc() + : nullptr; +} + nsresult nsBulletFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage) { @@ -873,7 +907,57 @@ nsBulletFrame::GetSpokenText(nsAString& aText) } } +void +nsBulletFrame::RegisterImageRequest(bool aKnownToBeAnimated) +{ + if (mImageRequest) { + // mRequestRegistered is a bitfield; unpack it temporarily so we can take + // the address. + bool isRequestRegistered = mRequestRegistered; + if (aKnownToBeAnimated) { + nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest, + &isRequestRegistered); + } else { + nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(), + mImageRequest, + &isRequestRegistered); + } + + isRequestRegistered = mRequestRegistered; + } +} + + +void +nsBulletFrame::DeregisterAndCancelImageRequest() +{ + if (mImageRequest) { + // mRequestRegistered is a bitfield; unpack it temporarily so we can take + // the address. + bool isRequestRegistered = mRequestRegistered; + + // Deregister our image request from the refresh driver. + nsLayoutUtils::DeregisterImageRequest(PresContext(), + mImageRequest, + &isRequestRegistered); + + isRequestRegistered = mRequestRegistered; + + // Unblock onload if we blocked it. + if (mBlockingOnload) { + nsIDocument* doc = GetOurCurrentDoc(); + if (doc) { + doc->UnblockOnload(false); + } + mBlockingOnload = false; + } + + // Cancel the image request and forget about it. + mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE); + mImageRequest = nullptr; + } +} @@ -894,7 +978,26 @@ nsBulletListener::~nsBulletListener() NS_IMETHODIMP nsBulletListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { - if (!mFrame) + if (!mFrame) { return NS_ERROR_FAILURE; + } return mFrame->Notify(aRequest, aType, aData); } + +NS_IMETHODIMP +nsBulletListener::BlockOnload(imgIRequest* aRequest) +{ + if (!mFrame) { + return NS_ERROR_FAILURE; + } + return mFrame->BlockOnload(aRequest); +} + +NS_IMETHODIMP +nsBulletListener::UnblockOnload(imgIRequest* aRequest) +{ + if (!mFrame) { + return NS_ERROR_FAILURE; + } + return mFrame->UnblockOnload(aRequest); +} diff --git a/layout/generic/nsBulletFrame.h b/layout/generic/nsBulletFrame.h index 91ac2dea88c..8b9cc3901d7 100644 --- a/layout/generic/nsBulletFrame.h +++ b/layout/generic/nsBulletFrame.h @@ -12,19 +12,22 @@ #include "nsFrame.h" #include "imgINotificationObserver.h" +#include "imgIOnloadBlocker.h" class imgIContainer; class imgRequestProxy; class nsBulletFrame; -class nsBulletListener MOZ_FINAL : public imgINotificationObserver +class nsBulletListener MOZ_FINAL : public imgINotificationObserver, + public imgIOnloadBlocker { public: nsBulletListener(); NS_DECL_ISUPPORTS NS_DECL_IMGINOTIFICATIONOBSERVER + NS_DECL_IMGIONLOADBLOCKER void SetFrame(nsBulletFrame *frame) { mFrame = frame; } @@ -50,11 +53,14 @@ public: : nsFrame(aContext) , mPadding(GetWritingMode()) , mIntrinsicSize(GetWritingMode()) - { - } + , mRequestRegistered(false) + , mBlockingOnload(false) + { } virtual ~nsBulletFrame(); - NS_IMETHOD Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData); + NS_IMETHOD Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData); + NS_IMETHOD BlockOnload(imgIRequest* aRequest); + NS_IMETHOD UnblockOnload(imgIRequest* aRequest); // nsIFrame virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; @@ -111,6 +117,7 @@ protected: float aFontSizeInflation); void GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup); + nsIDocument* GetOurCurrentDoc() const; mozilla::LogicalMargin mPadding; nsRefPtr mImageRequest; @@ -120,10 +127,15 @@ protected: int32_t mOrdinal; private: + void RegisterImageRequest(bool aKnownToBeAnimated); + void DeregisterAndCancelImageRequest(); // This is a boolean flag indicating whether or not the current image request // has been registered with the refresh driver. - bool mRequestRegistered; + bool mRequestRegistered : 1; + + // Whether we're currently blocking onload. + bool mBlockingOnload : 1; }; #endif /* nsBulletFrame_h___ */ diff --git a/layout/reftests/svg/as-image/reftest.list b/layout/reftests/svg/as-image/reftest.list index 353e3c6b0d1..80a3bd05548 100644 --- a/layout/reftests/svg/as-image/reftest.list +++ b/layout/reftests/svg/as-image/reftest.list @@ -127,7 +127,7 @@ skip-if(B2G) == img-fragment-2a.html img-fragment-2-ref.html # bug 773482 skip-if(B2G) == img-fragment-2b.html img-fragment-2-ref.html # bug 773482 skip-if(B2G) == img-fragment-2c.html img-fragment-2-ref.html # bug 773482 -skip-if(B2G) == list-simple-1.html list-simple-1-ref.html # bug 773482 +fuzzy-if(B2G,68,4) == list-simple-1.html list-simple-1-ref.html == svg-image-simple-1.svg lime100x100.svg == svg-image-simple-2.svg lime100x100.svg From 5e22eb2a7c1816f5d11a57a56052b8e4abd5d110 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Mon, 10 Nov 2014 13:37:52 -0800 Subject: [PATCH 17/71] Bug 1091921 - Don't disable operator delete for Monitor and Mutex Auto helpers. r=froydnj --HG-- extra : rebase_source : 9754a3daab2b3452201ed9575a4cc00b6b8d6231 --- xpcom/glue/Monitor.h | 2 -- xpcom/glue/Mutex.h | 2 -- xpcom/glue/ReentrantMonitor.h | 2 -- 3 files changed, 6 deletions(-) diff --git a/xpcom/glue/Monitor.h b/xpcom/glue/Monitor.h index 62e20f58342..60750acb332 100644 --- a/xpcom/glue/Monitor.h +++ b/xpcom/glue/Monitor.h @@ -96,7 +96,6 @@ private: MonitorAutoLock(const MonitorAutoLock&); MonitorAutoLock& operator=(const MonitorAutoLock&); static void* operator new(size_t) CPP_THROW_NEW; - static void operator delete(void*); Monitor* mMonitor; }; @@ -127,7 +126,6 @@ private: MonitorAutoUnlock(const MonitorAutoUnlock&); MonitorAutoUnlock& operator=(const MonitorAutoUnlock&); static void* operator new(size_t) CPP_THROW_NEW; - static void operator delete(void*); Monitor* mMonitor; }; diff --git a/xpcom/glue/Mutex.h b/xpcom/glue/Mutex.h index 7544b7b5c3d..a5ed05f36a3 100644 --- a/xpcom/glue/Mutex.h +++ b/xpcom/glue/Mutex.h @@ -174,7 +174,6 @@ private: BaseAutoLock(BaseAutoLock&); BaseAutoLock& operator=(BaseAutoLock&); static void* operator new(size_t) CPP_THROW_NEW; - static void operator delete(void*); T* mLock; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER @@ -212,7 +211,6 @@ private: BaseAutoUnlock(BaseAutoUnlock&); BaseAutoUnlock& operator=(BaseAutoUnlock&); static void* operator new(size_t) CPP_THROW_NEW; - static void operator delete(void*); T* mLock; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER diff --git a/xpcom/glue/ReentrantMonitor.h b/xpcom/glue/ReentrantMonitor.h index e3e9bbaeb7b..0798fe2af3e 100644 --- a/xpcom/glue/ReentrantMonitor.h +++ b/xpcom/glue/ReentrantMonitor.h @@ -198,7 +198,6 @@ private: ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&); ReentrantMonitorAutoEnter& operator=(const ReentrantMonitorAutoEnter&); static void* operator new(size_t) CPP_THROW_NEW; - static void operator delete(void*); mozilla::ReentrantMonitor* mReentrantMonitor; }; @@ -240,7 +239,6 @@ private: ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit&); ReentrantMonitorAutoExit& operator=(const ReentrantMonitorAutoExit&); static void* operator new(size_t) CPP_THROW_NEW; - static void operator delete(void*); ReentrantMonitor* mReentrantMonitor; }; From 60cc7c124004b267a4f0bcc7bda3922d8f6c3e12 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 10 Nov 2014 21:41:40 +0000 Subject: [PATCH 18/71] Bug 1093806 - Convert DCFromContext to DCFromDrawTarget. r=Bas --- gfx/thebes/gfxGDIFont.cpp | 2 +- gfx/thebes/gfxWindowsPlatform.cpp | 30 +++++++++++++++-- gfx/thebes/gfxWindowsPlatform.h | 54 +++++++++++++------------------ 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/gfx/thebes/gfxGDIFont.cpp b/gfx/thebes/gfxGDIFont.cpp index 22262cffee8..180eb1ef2e9 100644 --- a/gfx/thebes/gfxGDIFont.cpp +++ b/gfx/thebes/gfxGDIFont.cpp @@ -471,7 +471,7 @@ gfxGDIFont::GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) return width; } - DCFromContext dc(aCtx); + DCFromDrawTarget dc(*aCtx->GetDrawTarget()); AutoSelectFont fs(dc, GetHFONT()); int devWidth; diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 9ac5d43a3c2..b24a41bb527 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -4,10 +4,11 @@ * 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/ArrayUtils.h" - #include "gfxWindowsPlatform.h" +#include "cairo.h" +#include "mozilla/ArrayUtils.h" + #include "gfxImageSurface.h" #include "gfxWindowsSurface.h" @@ -80,6 +81,31 @@ using namespace mozilla::layers; using namespace mozilla::widget; using namespace mozilla::image; +DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget) +{ + mDC = nullptr; + if (aDrawTarget.GetBackendType() == BackendType::CAIRO) { + cairo_surface_t *surf = (cairo_surface_t*) + aDrawTarget.GetNativeSurface(NativeSurfaceType::CAIRO_SURFACE); + cairo_surface_type_t surfaceType = cairo_surface_get_type(surf); + if (surfaceType == CAIRO_SURFACE_TYPE_WIN32 || + surfaceType == CAIRO_SURFACE_TYPE_WIN32_PRINTING) { + mDC = cairo_win32_surface_get_dc(surf); + mNeedsRelease = false; + SaveDC(mDC); + cairo_t* ctx = (cairo_t*) + aDrawTarget.GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT); + cairo_scaled_font_t* scaled = cairo_get_scaled_font(ctx); + cairo_win32_scaled_font_select_font(scaled, mDC); + } + if (!mDC) { + mDC = GetDC(nullptr); + SetGraphicsMode(mDC, GM_ADVANCED); + mNeedsRelease = true; + } + } +} + #ifdef CAIRO_HAS_D2D_SURFACE static const char *kFeatureLevelPref = diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 0fbdcc50a38..3159f2e4ae2 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -20,8 +20,8 @@ #include "gfxDWriteFonts.h" #endif #include "gfxPlatform.h" -#include "gfxContext.h" - +#include "gfxTypes.h" +#include "mozilla/Attributes.h" #include "nsTArray.h" #include "nsDataHashtable.h" @@ -44,6 +44,9 @@ #endif namespace mozilla { +namespace gfx { +class DrawTarget; +} namespace layers { class DeviceManagerD3D9; class ReadbackManagerD3D11; @@ -55,44 +58,31 @@ struct IDXGIAdapter1; class nsIMemoryReporter; -// Utility to get a Windows HDC from a thebes context, -// used by both GDI and Uniscribe font shapers -struct DCFromContext { - DCFromContext(gfxContext *aContext) { - dc = nullptr; - nsRefPtr aSurface = aContext->CurrentSurface(); - if (aSurface && - (aSurface->GetType() == gfxSurfaceType::Win32 || - aSurface->GetType() == gfxSurfaceType::Win32Printing)) - { - dc = static_cast(aSurface.get())->GetDC(); - needsRelease = false; - SaveDC(dc); - cairo_scaled_font_t* scaled = - cairo_get_scaled_font(aContext->GetCairo()); - cairo_win32_scaled_font_select_font(scaled, dc); - } - if (!dc) { - dc = GetDC(nullptr); - SetGraphicsMode(dc, GM_ADVANCED); - needsRelease = true; - } - } +/** + * Utility to get a Windows HDC from a Moz2D DrawTarget. If the DrawTarget is + * not backed by a HDC this will get the HDC for the screen device context + * instead. + */ +class MOZ_STACK_CLASS DCFromDrawTarget MOZ_FINAL +{ +public: + DCFromDrawTarget(mozilla::gfx::DrawTarget& aDrawTarget); - ~DCFromContext() { - if (needsRelease) { - ReleaseDC(nullptr, dc); + ~DCFromDrawTarget() { + if (mNeedsRelease) { + ReleaseDC(nullptr, mDC); } else { - RestoreDC(dc, -1); + RestoreDC(mDC, -1); } } operator HDC () { - return dc; + return mDC; } - HDC dc; - bool needsRelease; +private: + HDC mDC; + bool mNeedsRelease; }; // ClearType parameters set by running ClearType tuner From 34c0ce8374a4eaf541fd5dc2ddc70846f3c8d573 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 10 Nov 2014 21:41:41 +0000 Subject: [PATCH 19/71] Bug 1093813 - Remove the gfxContext argument from gfxHarfBuzzShaper's GetGlyphHAdvance, GetGlyphVAdvance and GetGlyphVOrigin methods. r=jfkthame --- gfx/thebes/gfxFont.cpp | 2 +- gfx/thebes/gfxHarfBuzzShaper.cpp | 18 +++++++----------- gfx/thebes/gfxHarfBuzzShaper.h | 8 +++----- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 77730f8961f..634fe7f859e 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -806,7 +806,7 @@ gfxFont::GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID) if (!shaper->Initialize()) { return 0; } - return shaper->GetGlyphHAdvance(aCtx, aGID) / 65536.0; + return shaper->GetGlyphHAdvance(aGID) / 65536.0; } /*static*/ diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index 99a74e83778..9dbf1d48696 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -184,8 +184,7 @@ struct GlyphMetrics { }; hb_position_t -gfxHarfBuzzShaper::GetGlyphHAdvance(gfxContext *aContext, - hb_codepoint_t glyph) const +gfxHarfBuzzShaper::GetGlyphHAdvance(hb_codepoint_t glyph) const { // font did not implement GetGlyphWidth, so get an unhinted value // directly from the font tables @@ -208,8 +207,7 @@ gfxHarfBuzzShaper::GetGlyphHAdvance(gfxContext *aContext, } hb_position_t -gfxHarfBuzzShaper::GetGlyphVAdvance(gfxContext *aContext, - hb_codepoint_t glyph) const +gfxHarfBuzzShaper::GetGlyphVAdvance(hb_codepoint_t glyph) const { if (!mVmtxTable) { // Must be a "vertical" font that doesn't actually have vertical metrics; @@ -244,9 +242,8 @@ gfxHarfBuzzShaper::HBGetGlyphHAdvance(hb_font_t *font, void *font_data, gfxFont *gfxfont = fcd->mShaper->GetFont(); if (gfxfont->ProvidesGlyphWidths()) { return gfxfont->GetGlyphWidth(fcd->mContext, glyph); - } else { - return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph); } + return fcd->mShaper->GetGlyphHAdvance(glyph); } /* static */ @@ -259,9 +256,8 @@ gfxHarfBuzzShaper::HBGetGlyphVAdvance(hb_font_t *font, void *font_data, gfxFont *gfxfont = fcd->mShaper->GetFont(); if (gfxfont->ProvidesGlyphWidths()) { return gfxfont->GetGlyphWidth(fcd->mContext, glyph); - } else { - return fcd->mShaper->GetGlyphVAdvance(fcd->mContext, glyph); } + return fcd->mShaper->GetGlyphVAdvance(glyph); } /* static */ @@ -296,15 +292,15 @@ gfxHarfBuzzShaper::HBGetGlyphVOrigin(hb_font_t *font, void *font_data, { const gfxHarfBuzzShaper::FontCallbackData *fcd = static_cast(font_data); - fcd->mShaper->GetGlyphVOrigin(fcd->mContext, glyph, x, y); + fcd->mShaper->GetGlyphVOrigin(glyph, x, y); return true; } void -gfxHarfBuzzShaper::GetGlyphVOrigin(gfxContext *aContext, hb_codepoint_t aGlyph, +gfxHarfBuzzShaper::GetGlyphVOrigin(hb_codepoint_t aGlyph, hb_position_t *aX, hb_position_t *aY) const { - *aX = -0.5 * GetGlyphHAdvance(aContext, aGlyph); + *aX = -0.5 * GetGlyphHAdvance(aGlyph); if (mVORGTable) { // We checked in Initialize() that the VORG table is safely readable, diff --git a/gfx/thebes/gfxHarfBuzzShaper.h b/gfx/thebes/gfxHarfBuzzShaper.h index ba726a9bbad..54ed5bdd73b 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.h +++ b/gfx/thebes/gfxHarfBuzzShaper.h @@ -42,13 +42,11 @@ public: hb_codepoint_t variation_selector) const; // get harfbuzz glyph advance, in font design units - hb_position_t GetGlyphHAdvance(gfxContext *aContext, - hb_codepoint_t glyph) const; + hb_position_t GetGlyphHAdvance(hb_codepoint_t glyph) const; - hb_position_t GetGlyphVAdvance(gfxContext *aContext, - hb_codepoint_t glyph) const; + hb_position_t GetGlyphVAdvance(hb_codepoint_t glyph) const; - void GetGlyphVOrigin(gfxContext *aContext, hb_codepoint_t aGlyph, + void GetGlyphVOrigin(hb_codepoint_t aGlyph, hb_position_t *aX, hb_position_t *aY) const; // get harfbuzz horizontal advance in 16.16 fixed point format. From 788f36f15220fcfed3260dddb4bd16e6f3d6b5bc Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 10 Nov 2014 21:41:41 +0000 Subject: [PATCH 20/71] Bug 1093811 - Convert the gfxFont::GetGlyphWidth() virtual method to take a Moz2D DrawTarget instead of a Thebes gfxContext. r=jfkthame --- gfx/thebes/gfxDWriteFonts.cpp | 2 +- gfx/thebes/gfxDWriteFonts.h | 2 +- gfx/thebes/gfxFT2FontBase.cpp | 2 +- gfx/thebes/gfxFT2FontBase.h | 2 +- gfx/thebes/gfxFont.cpp | 2 +- gfx/thebes/gfxFont.h | 7 +++++-- gfx/thebes/gfxGDIFont.cpp | 4 ++-- gfx/thebes/gfxGDIFont.h | 2 +- gfx/thebes/gfxGraphiteShaper.cpp | 3 ++- gfx/thebes/gfxHarfBuzzShaper.cpp | 4 ++-- 10 files changed, 17 insertions(+), 13 deletions(-) diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index 70a7d2032a5..c7e66fe198b 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -584,7 +584,7 @@ gfxDWriteFont::ProvidesGlyphWidths() const } int32_t -gfxDWriteFont::GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) +gfxDWriteFont::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) { if (!mGlyphWidths) { mGlyphWidths = new nsDataHashtable(128); diff --git a/gfx/thebes/gfxDWriteFonts.h b/gfx/thebes/gfxDWriteFonts.h index dbd17ab0260..99d2463bc63 100644 --- a/gfx/thebes/gfxDWriteFonts.h +++ b/gfx/thebes/gfxDWriteFonts.h @@ -54,7 +54,7 @@ public: virtual bool ProvidesGlyphWidths() const; - virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID); + virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID); virtual mozilla::TemporaryRef GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) MOZ_OVERRIDE; diff --git a/gfx/thebes/gfxFT2FontBase.cpp b/gfx/thebes/gfxFT2FontBase.cpp index 13562936a6a..22710869073 100644 --- a/gfx/thebes/gfxFT2FontBase.cpp +++ b/gfx/thebes/gfxFT2FontBase.cpp @@ -168,7 +168,7 @@ gfxFT2FontBase::GetGlyph(uint32_t unicode, uint32_t variation_selector) } int32_t -gfxFT2FontBase::GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) +gfxFT2FontBase::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) { cairo_text_extents_t extents; GetGlyphExtents(aGID, &extents); diff --git a/gfx/thebes/gfxFT2FontBase.h b/gfx/thebes/gfxFT2FontBase.h index c8d53b4999f..5f8648c3570 100644 --- a/gfx/thebes/gfxFT2FontBase.h +++ b/gfx/thebes/gfxFT2FontBase.h @@ -25,7 +25,7 @@ public: virtual bool ProvidesGetGlyph() const { return true; } virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector); virtual bool ProvidesGlyphWidths() const { return true; } - virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID); + virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID); cairo_scaled_font_t *CairoScaledFont() { return mScaledFont; }; virtual bool SetupCairoFont(gfxContext *aContext); diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 634fe7f859e..490bee2574e 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -791,7 +791,7 @@ gfxFont::GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID) return 0; } if (ProvidesGlyphWidths()) { - return GetGlyphWidth(aCtx, aGID) / 65536.0; + return GetGlyphWidth(*aCtx->GetDrawTarget(), aGID) / 65536.0; } if (mFUnitsConvFactor == 0.0f) { GetMetrics(eHorizontal); diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index d20d0330423..909dbc8ec0d 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -1267,6 +1267,9 @@ class gfxFont { friend class gfxHarfBuzzShaper; friend class gfxGraphiteShaper; +protected: + typedef mozilla::gfx::DrawTarget DrawTarget; + public: nsrefcnt AddRef(void) { NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt"); @@ -1709,7 +1712,7 @@ public: virtual FontType GetType() const = 0; - virtual mozilla::TemporaryRef GetScaledFont(mozilla::gfx::DrawTarget *aTarget) + virtual mozilla::TemporaryRef GetScaledFont(DrawTarget* aTarget) { return gfxPlatform::GetPlatform()->GetScaledFontForFont(aTarget, this); } bool KerningDisabled() { @@ -1820,7 +1823,7 @@ protected: // The return value is interpreted as a horizontal advance in 16.16 fixed // point format. - virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) { + virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) { return -1; } diff --git a/gfx/thebes/gfxGDIFont.cpp b/gfx/thebes/gfxGDIFont.cpp index 180eb1ef2e9..9cedcc3aa29 100644 --- a/gfx/thebes/gfxGDIFont.cpp +++ b/gfx/thebes/gfxGDIFont.cpp @@ -460,7 +460,7 @@ gfxGDIFont::GetGlyph(uint32_t aUnicode, uint32_t aVarSelector) } int32_t -gfxGDIFont::GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) +gfxGDIFont::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) { if (!mGlyphWidths) { mGlyphWidths = new nsDataHashtable(128); @@ -471,7 +471,7 @@ gfxGDIFont::GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) return width; } - DCFromDrawTarget dc(*aCtx->GetDrawTarget()); + DCFromDrawTarget dc(aDrawTarget); AutoSelectFont fs(dc, GetHFONT()); int devWidth; diff --git a/gfx/thebes/gfxGDIFont.h b/gfx/thebes/gfxGDIFont.h index 981346a8edd..d714c0d542a 100644 --- a/gfx/thebes/gfxGDIFont.h +++ b/gfx/thebes/gfxGDIFont.h @@ -60,7 +60,7 @@ public: virtual bool ProvidesGlyphWidths() const { return true; } // get hinted glyph width in pixels as 16.16 fixed-point value - virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID); + virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID); virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontCacheSizes* aSizes) const; diff --git a/gfx/thebes/gfxGraphiteShaper.cpp b/gfx/thebes/gfxGraphiteShaper.cpp index 62c74c24563..68c832d27e8 100644 --- a/gfx/thebes/gfxGraphiteShaper.cpp +++ b/gfx/thebes/gfxGraphiteShaper.cpp @@ -50,7 +50,8 @@ gfxGraphiteShaper::GrGetAdvance(const void* appFontHandle, uint16_t glyphid) { const CallbackData *cb = static_cast(appFontHandle); - return FixedToFloat(cb->mFont->GetGlyphWidth(cb->mContext, glyphid)); + return FixedToFloat(cb->mFont->GetGlyphWidth(*cb->mContext->GetDrawTarget(), + glyphid)); } static inline uint32_t diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index 9dbf1d48696..f5dd79bb4fd 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -241,7 +241,7 @@ gfxHarfBuzzShaper::HBGetGlyphHAdvance(hb_font_t *font, void *font_data, static_cast(font_data); gfxFont *gfxfont = fcd->mShaper->GetFont(); if (gfxfont->ProvidesGlyphWidths()) { - return gfxfont->GetGlyphWidth(fcd->mContext, glyph); + return gfxfont->GetGlyphWidth(*fcd->mContext->GetDrawTarget(), glyph); } return fcd->mShaper->GetGlyphHAdvance(glyph); } @@ -255,7 +255,7 @@ gfxHarfBuzzShaper::HBGetGlyphVAdvance(hb_font_t *font, void *font_data, static_cast(font_data); gfxFont *gfxfont = fcd->mShaper->GetFont(); if (gfxfont->ProvidesGlyphWidths()) { - return gfxfont->GetGlyphWidth(fcd->mContext, glyph); + return gfxfont->GetGlyphWidth(*fcd->mContext->GetDrawTarget(), glyph); } return fcd->mShaper->GetGlyphVAdvance(glyph); } From 6f5d4a82de3fb53abe6e62f84a1aa3572fc5d107 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 6 Nov 2014 14:03:05 -0800 Subject: [PATCH 21/71] Bug 1093307 - Part 2: Make OOM flushing paths more straightforward; r=jonco --HG-- extra : rebase_source : 4634215f64ea96c2057f4ff609119b2a6cad008f --- js/src/gc/GCRuntime.h | 3 ++- js/src/jsgc.cpp | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 4d4715adf46..33643a212b8 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -498,7 +498,7 @@ class GCRuntime * Must be called either during the GC or with the GC lock taken. */ Chunk *expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock); - void freeEmptyChunks(JSRuntime *rt); + void freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock); void freeChunkList(Chunk *chunkListHead); void prepareToFreeChunk(ChunkInfo &info); void releaseChunk(Chunk *chunk); @@ -543,6 +543,7 @@ class GCRuntime bool sweepPhase(SliceBudget &sliceBudget); void endSweepPhase(bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); + void decommitAllWithoutUnlocking(const AutoLockGC &lock); void decommitArenasFromAvailableList(Chunk **availableListHeadp); void decommitArenas(); void expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 5864700694e..ca9059feb11 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -744,15 +744,22 @@ GCRuntime::expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock) return freeList; } -void -GCRuntime::freeEmptyChunks(JSRuntime *rt) +static void +FreeChunkPool(JSRuntime *rt, ChunkPool &pool) { - for (ChunkPool::Enum e(emptyChunks_); !e.empty();) { + for (ChunkPool::Enum e(pool); !e.empty();) { Chunk *chunk = e.front(); e.removeAndPopFront(); MOZ_ASSERT(!chunk->info.numArenasFreeCommitted); FreeChunk(rt, chunk); } + MOZ_ASSERT(pool.count() == 0); +} + +void +GCRuntime::freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock) +{ + FreeChunkPool(rt, emptyChunks(lock)); } void @@ -1422,7 +1429,7 @@ GCRuntime::finish() chunkSet.clear(); } - freeEmptyChunks(rt); + FreeChunkPool(rt, emptyChunks_); if (rootsHash.initialized()) rootsHash.clear(); @@ -3122,6 +3129,25 @@ GCRuntime::maybePeriodicFullGC() #endif } +// Do all possible decommit immediately from the current thread without +// releasing the GC lock or allocating any memory. +void +GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC &lock) +{ + MOZ_ASSERT(emptyChunks(lock).count() == 0); + for (Chunk *chunk = *getAvailableChunkList(); chunk; chunk = chunk->info.next) { + for (size_t i = 0; i < ArenasPerChunk; ++i) { + if (chunk->decommittedArenas.get(i) || chunk->arenas[i].aheader.allocated()) + continue; + + if (MarkPagesUnused(&chunk->arenas[i], ArenaSize)) { + chunk->info.numArenasFreeCommitted--; + chunk->decommittedArenas.set(i); + } + } + } +} + void GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) { @@ -6216,7 +6242,12 @@ GCRuntime::onOutOfMallocMemory() // Throw away any excess chunks we have lying around. AutoLockGC lock(rt); - expireChunksAndArenas(true, lock); + freeEmptyChunks(rt, lock); + + // Immediately decommit as many arenas as possible in the hopes that this + // might let the OS scrape together enough pages to satisfy the failing + // malloc request. + decommitAllWithoutUnlocking(lock); } void From 1340af80901760858627d0ff0217f6472a5ea0b8 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 6 Nov 2014 14:03:09 -0800 Subject: [PATCH 22/71] Bug 1074961 - Part 12: Simplify the locking in releaseArena; r=sfink --HG-- extra : rebase_source : 3b1f8e728a31948a1bcb04aa3a46a5ea2b216aa4 --- js/src/gc/GCRuntime.h | 8 +- js/src/gc/Heap.h | 17 +--- js/src/jsgc.cpp | 226 +++++++++++++++++++++++++----------------- js/src/jsgc.h | 20 +--- 4 files changed, 149 insertions(+), 122 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 33643a212b8..b91c25a2b30 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -271,6 +271,7 @@ class GCRuntime void decFJMinorCollecting() { fjCollectionCounter--; } bool triggerGC(JS::gcreason::Reason reason); + void maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock); bool triggerZoneGC(Zone *zone, JS::gcreason::Reason reason); bool maybeGC(Zone *zone); void maybePeriodicFullGC(); @@ -481,11 +482,15 @@ class GCRuntime void freeUnusedLifoBlocksAfterSweeping(LifoAlloc *lifo); void freeAllLifoBlocksAfterSweeping(LifoAlloc *lifo); + // Public here for ReleaseArenaLists and FinalizeTypedArenas. + void releaseArena(ArenaHeader *aheader, const AutoLockGC &lock); + private: // For ArenaLists::allocateFromArena() friend class ArenaLists; Chunk *pickChunk(const AutoLockGC &lock, AutoMaybeStartBackgroundAllocation &maybeStartBGAlloc); + ArenaHeader *allocateArena(Chunk *chunk, Zone *zone, AllocKind kind, const AutoLockGC &lock); inline void arenaAllocatedDuringGC(JS::Zone *zone, ArenaHeader *arena); template @@ -544,8 +549,7 @@ class GCRuntime void endSweepPhase(bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); void decommitAllWithoutUnlocking(const AutoLockGC &lock); - void decommitArenasFromAvailableList(Chunk **availableListHeadp); - void decommitArenas(); + void decommitArenas(const AutoLockGC &lock); void expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock); void sweepBackgroundThings(); void assertBackgroundSweepingFinished(); diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index 43041baf01f..ae6c8a17678 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -37,6 +37,7 @@ struct Runtime; namespace js { +class AutoLockGC; class FreeOp; #ifdef DEBUG @@ -945,9 +946,10 @@ struct Chunk inline void insertToAvailableList(Chunk **insertPoint); inline void removeFromAvailableList(); - ArenaHeader *allocateArena(JS::Zone *zone, AllocKind kind); + ArenaHeader *allocateArena(JSRuntime *rt, JS::Zone *zone, AllocKind kind, + const AutoLockGC &lock); - void releaseArena(ArenaHeader *aheader); + void releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock); void recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thingKind, size_t thingsPerArena); @@ -1147,17 +1149,6 @@ ArenaHeader::unsetAllocDuringSweep() auxNextLink = 0; } -inline void -ReleaseArenaList(ArenaHeader *aheader) -{ - ArenaHeader *next; - for (; aheader; aheader = next) { - // Copy aheader->next before releasing. - next = aheader->next; - aheader->chunk()->releaseArena(aheader); - } -} - static void AssertValidColor(const TenuredCell *thing, uint32_t color) { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index ca9059feb11..55e9e561619 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -545,6 +545,9 @@ Arena::finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize) return nmarked; } +// Finalize arenas from src list, releasing empty arenas if keepArenas wasn't +// specified and inserting the others into the appropriate destination size +// bins. template static inline bool FinalizeTypedArenas(FreeOp *fop, @@ -554,11 +557,10 @@ FinalizeTypedArenas(FreeOp *fop, SliceBudget &budget, ArenaLists::KeepArenasEnum keepArenas) { - /* - * Finalize arenas from src list, releasing empty arenas if keepArenas - * wasn't specified and inserting the others into the appropriate - * destination size bins. - */ + // When operating in the foreground, take the lock at the top. + Maybe maybeLock; + if (!fop->runtime()->gc.isBackgroundSweeping()) + maybeLock.emplace(fop->runtime()); /* * During parallel sections, we sometimes finalize the parallel arenas, @@ -575,12 +577,18 @@ FinalizeTypedArenas(FreeOp *fop, size_t nmarked = aheader->getArena()->finalize(fop, thingKind, thingSize); size_t nfree = thingsPerArena - nmarked; - if (nmarked) + if (nmarked) { dest.insertAt(aheader, nfree); - else if (keepArenas) + } else if (keepArenas) { aheader->chunk()->recycleArena(aheader, dest, thingKind, thingsPerArena); - else - aheader->chunk()->releaseArena(aheader); + } else if (fop->runtime()->gc.isBackgroundSweeping()) { + // When background sweeping, take the lock around each release so + // that we do not block the foreground for extended periods. + AutoLockGC lock(fop->runtime()); + fop->runtime()->gc.releaseArena(aheader, lock); + } else { + fop->runtime()->gc.releaseArena(aheader, maybeLock.ref()); + } budget.step(thingsPerArena); if (budget.isOverBudget()) @@ -945,67 +953,14 @@ Chunk::fetchNextFreeArena(JSRuntime *rt) } ArenaHeader * -Chunk::allocateArena(Zone *zone, AllocKind thingKind) +Chunk::allocateArena(JSRuntime *rt, Zone *zone, AllocKind thingKind, const AutoLockGC &lock) { - MOZ_ASSERT(hasAvailableArenas()); - - JSRuntime *rt = zone->runtimeFromAnyThread(); - if (!rt->isHeapMinorCollecting() && - !rt->isHeapCompacting() && - rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) - { -#ifdef JSGC_FJGENERATIONAL - // This is an approximation to the best test, which would check that - // this thread is currently promoting into the tenured area. I doubt - // the better test would make much difference. - if (!rt->isFJMinorCollecting()) - return nullptr; -#else - return nullptr; -#endif - } - - ArenaHeader *aheader = MOZ_LIKELY(info.numArenasFreeCommitted > 0) + ArenaHeader *aheader = info.numArenasFreeCommitted > 0 ? fetchNextFreeArena(rt) : fetchNextDecommittedArena(); aheader->init(zone, thingKind); if (MOZ_UNLIKELY(!hasAvailableArenas())) removeFromAvailableList(); - - zone->usage.addGCArena(); - - if (!rt->isHeapCompacting()) { - size_t usedBytes = zone->usage.gcBytes(); - size_t thresholdBytes = zone->threshold.gcTriggerBytes(); - size_t igcThresholdBytes = thresholdBytes * rt->gc.tunables.zoneAllocThresholdFactor(); - - if (usedBytes >= thresholdBytes) { - // The threshold has been surpassed, immediately trigger a GC, - // which will be done non-incrementally. - AutoUnlockGC unlock(rt); - rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); - } else if (usedBytes >= igcThresholdBytes) { - // Reduce the delay to the start of the next incremental slice. - if (zone->gcDelayBytes < ArenaSize) - zone->gcDelayBytes = 0; - else - zone->gcDelayBytes -= ArenaSize; - - if (!zone->gcDelayBytes) { - // Start or continue an in progress incremental GC. We do this - // to try to avoid performing non-incremental GCs on zones - // which allocate a lot of data, even when incremental slices - // can't be triggered via scheduling in the event loop. - AutoUnlockGC unlock(rt); - rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); - - // Delay the next slice until a certain amount of allocation - // has been performed. - zone->gcDelayBytes = rt->gc.tunables.zoneAllocDelayBytes(); - } - } - } - return aheader; } @@ -1035,20 +990,10 @@ Chunk::recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thing } void -Chunk::releaseArena(ArenaHeader *aheader) +Chunk::releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) { MOZ_ASSERT(aheader->allocated()); MOZ_ASSERT(!aheader->hasDelayedMarking); - Zone *zone = aheader->zone; - JSRuntime *rt = zone->runtimeFromAnyThread(); - - Maybe maybeLock; - if (rt->gc.isBackgroundSweeping()) - maybeLock.emplace(rt); - - if (rt->gc.isBackgroundSweeping()) - zone->threshold.updateForRemovedArena(rt->gc.tunables); - zone->usage.removeGCArena(); aheader->setAsNotAllocated(); addArenaToFreeList(rt, aheader); @@ -1060,12 +1005,10 @@ Chunk::releaseArena(ArenaHeader *aheader) } else if (!unused()) { MOZ_ASSERT(info.prevp); } else { - if (maybeLock.isNothing()) - maybeLock.emplace(rt); MOZ_ASSERT(unused()); removeFromAvailableList(); decommitAllArenas(rt); - rt->gc.moveChunkToFreePool(this, maybeLock.ref()); + rt->gc.moveChunkToFreePool(this, lock); } } @@ -1168,6 +1111,46 @@ GCRuntime::pickChunk(const AutoLockGC &lock, return chunk; } +ArenaHeader * +GCRuntime::allocateArena(Chunk *chunk, Zone *zone, AllocKind thingKind, const AutoLockGC &lock) +{ + MOZ_ASSERT(chunk->hasAvailableArenas()); + + // Fail the allocation if we are over our heap size limits. + if (!isHeapMinorCollecting() && + !isHeapCompacting() && + usage.gcBytes() >= tunables.gcMaxBytes()) + { +#ifdef JSGC_FJGENERATIONAL + // This is an approximation to the best test, which would check that + // this thread is currently promoting into the tenured area. I doubt + // the better test would make much difference. + if (!isFJMinorCollecting()) + return nullptr; +#else + return nullptr; +#endif + } + + ArenaHeader *aheader = chunk->allocateArena(rt, zone, thingKind, lock); + zone->usage.addGCArena(); + + // Trigger an incremental slice if needed. + if (!isHeapMinorCollecting() && !isHeapCompacting()) + maybeAllocTriggerZoneGC(zone, lock); + + return aheader; +} + +void +GCRuntime::releaseArena(ArenaHeader *aheader, const AutoLockGC &lock) +{ + aheader->zone->usage.removeGCArena(); + if (isBackgroundSweeping()) + aheader->zone->threshold.updateForRemovedArena(tunables); + return aheader->chunk()->releaseArena(rt, aheader, lock); +} + GCRuntime::GCRuntime(JSRuntime *rt) : rt(rt), systemZone(nullptr), @@ -1913,7 +1896,8 @@ ZoneHeapThreshold::updateForRemovedArena(const GCSchedulingTunables &tunables) } Allocator::Allocator(Zone *zone) - : zone_(zone) + : arenas(zone->runtimeFromMainThread()), + zone_(zone) {} inline void @@ -1999,7 +1983,7 @@ ArenaLists::allocateFromArena(JS::Zone *zone, AllocKind thingKind, // Although our chunk should definitely have enough space for another arena, // there are other valid reasons why Chunk::allocateArena() may fail. - aheader = chunk->allocateArena(zone, thingKind); + aheader = rt->gc.allocateArena(chunk, zone, thingKind, maybeLock.ref()); if (!aheader) return nullptr; @@ -2560,6 +2544,7 @@ void GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) { // Release the relocated arenas, now containing only forwarding pointers + AutoLockGC lock(rt); unsigned count = 0; while (relocatedList) { @@ -2582,7 +2567,7 @@ GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) JS_MOVED_TENURED_PATTERN, Arena::thingsSpan(thingSize)); #endif - aheader->chunk()->releaseArena(aheader); + releaseArena(aheader, lock); ++count; } @@ -2592,6 +2577,35 @@ GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) #endif // JSGC_COMPACTING +void +ReleaseArenaList(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) +{ + ArenaHeader *next; + for (; aheader; aheader = next) { + next = aheader->next; + rt->gc.releaseArena(aheader, lock); + } +} + +ArenaLists::~ArenaLists() +{ + AutoLockGC lock(runtime_); + + for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { + /* + * We can only call this during the shutdown after the last GC when + * the background finalization is disabled. + */ + MOZ_ASSERT(backgroundFinalizeState[i] == BFS_DONE); + ReleaseArenaList(runtime_, arenaLists[i].head(), lock); + } + ReleaseArenaList(runtime_, incrementalSweptArenas.head(), lock); + + for (size_t i = 0; i < FINALIZE_OBJECT_LIMIT; i++) + ReleaseArenaList(runtime_, savedObjectArenas[i].head(), lock); + ReleaseArenaList(runtime_, savedEmptyObjectArenas, lock); +} + void ArenaLists::finalizeNow(FreeOp *fop, const FinalizePhase& phase) { @@ -2758,7 +2772,8 @@ ArenaLists::queueForegroundObjectsForSweep(FreeOp *fop) void ArenaLists::mergeForegroundSweptObjectArenas() { - ReleaseArenaList(savedEmptyObjectArenas); + AutoLockGC lock(runtime_); + ReleaseArenaList(runtime_, savedEmptyObjectArenas, lock); savedEmptyObjectArenas = nullptr; mergeSweptArenas(FINALIZE_OBJECT0); @@ -3030,6 +3045,40 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason) return true; } +void +GCRuntime::maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock) +{ + size_t usedBytes = zone->usage.gcBytes(); + size_t thresholdBytes = zone->threshold.gcTriggerBytes(); + size_t igcThresholdBytes = thresholdBytes * tunables.zoneAllocThresholdFactor(); + + if (usedBytes >= thresholdBytes) { + // The threshold has been surpassed, immediately trigger a GC, + // which will be done non-incrementally. + AutoUnlockGC unlock(rt); + triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + } else if (usedBytes >= igcThresholdBytes) { + // Reduce the delay to the start of the next incremental slice. + if (zone->gcDelayBytes < ArenaSize) + zone->gcDelayBytes = 0; + else + zone->gcDelayBytes -= ArenaSize; + + if (!zone->gcDelayBytes) { + // Start or continue an in progress incremental GC. We do this + // to try to avoid performing non-incremental GCs on zones + // which allocate a lot of data, even when incremental slices + // can't be triggered via scheduling in the event loop. + AutoUnlockGC unlock(rt); + triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + + // Delay the next slice until a certain amount of allocation + // has been performed. + zone->gcDelayBytes = tunables.zoneAllocDelayBytes(); + } + } +} + bool GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) { @@ -3149,8 +3198,9 @@ GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC &lock) } void -GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) +GCRuntime::decommitArenas(const AutoLockGC &lock) { + Chunk **availableListHeadp = &availableChunkListHead; Chunk *chunk = *availableListHeadp; if (!chunk) return; @@ -3257,12 +3307,6 @@ GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) } } -void -GCRuntime::decommitArenas() -{ - decommitArenasFromAvailableList(&availableChunkListHead); -} - void GCRuntime::expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock) { @@ -3276,7 +3320,7 @@ GCRuntime::expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock) } if (shouldShrink) - decommitArenas(); + decommitArenas(lock); } void @@ -6651,7 +6695,7 @@ ArenaLists::adoptArenas(JSRuntime *rt, ArenaLists *fromArenaLists) // Therefore, if fromHeader is empty, send it back to the // chunk now. Otherwise, attach to |toList|. if (fromHeader->isEmpty()) - fromHeader->chunk()->releaseArena(fromHeader); + rt->gc.releaseArena(fromHeader, lock); else toList->insertAtCursor(fromHeader); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index f273f35c4c2..ec51d5709e9 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -595,6 +595,8 @@ class SortedArenaList class ArenaLists { + JSRuntime *runtime_; + /* * For each arena kind its free list is represented as the first span with * free things. Initially all the spans are initialized as empty. After we @@ -639,7 +641,7 @@ class ArenaLists ArenaHeader *savedEmptyObjectArenas; public: - ArenaLists() { + ArenaLists(JSRuntime *rt) : runtime_(rt) { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) freeLists[i].initAsEmpty(); for (size_t i = 0; i != FINALIZE_LIMIT; ++i) @@ -654,21 +656,7 @@ class ArenaLists savedEmptyObjectArenas = nullptr; } - ~ArenaLists() { - for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { - /* - * We can only call this during the shutdown after the last GC when - * the background finalization is disabled. - */ - MOZ_ASSERT(backgroundFinalizeState[i] == BFS_DONE); - ReleaseArenaList(arenaLists[i].head()); - } - ReleaseArenaList(incrementalSweptArenas.head()); - - for (size_t i = 0; i < FINALIZE_OBJECT_LIMIT; i++) - ReleaseArenaList(savedObjectArenas[i].head()); - ReleaseArenaList(savedEmptyObjectArenas); - } + ~ArenaLists(); static uintptr_t getFreeListOffset(AllocKind thingKind) { uintptr_t offset = offsetof(ArenaLists, freeLists); From 533acd176a18c2eae29ddabb7d86405f01cca71b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 10 Nov 2014 16:48:52 -0500 Subject: [PATCH 23/71] Bug 1094803 - Update the APZ docs a bit to describe input event flow. r=botond DONTBUILD because this is NPOTB. --- gfx/doc/AsyncPanZoom.md | 117 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/gfx/doc/AsyncPanZoom.md b/gfx/doc/AsyncPanZoom.md index 0e36ea0e77f..7a7850a900e 100644 --- a/gfx/doc/AsyncPanZoom.md +++ b/gfx/doc/AsyncPanZoom.md @@ -148,7 +148,9 @@ However, on the main thread, web content might be running Javascript code that p Scroll changes driven from the main thread are just as legitimate and need to be propagated to the compositor thread, so that the visual display updates in response. Because the cross-thread messaging is asynchronous, reconciling the two types of scroll changes is a tricky problem. -Our design solves this using various flags and generation counters that ensures compositor-driven scroll changes never overwrite content-driven scroll changes - this behaviour is usually the desired outcome. +Our design solves this using various flags and generation counters. +The general heuristic we have is that content-driven scroll position changes (e.g. scrollTo from JS) are never lost. +For instance, if the user is doing an async scroll with their finger and content does a scrollTo in the middle, then some of the async scroll would occur before the "jump" and the rest after the "jump". ### Content preventing default behaviour of input events @@ -165,3 +167,116 @@ The way the APZ implementation deals with this is that upon receiving a touch ev It also schedules a 300ms timeout during which content is allowed to prevent scrolling. There is an API that allows the main-thread event dispatching code to notify the APZ as to whether or not the default action should be prevented. If the APZ content response timeout expires, or if the main-thread event dispatching code notifies the APZ of the preventDefault status, then the APZ continues with the processing of the events (which may involve discarding the events). + +## Technical details + +This section describes various pieces of the APZ code, and goes into more specific detail on APIs and code than the previous sections. +The primary purpose of this section is to help people who plan on making changes to the code, while also not going into so much detail that it needs to be updated with every patch. + +### Overall flow of input events + +This section describes how input events flow through the APZ code. +
    +
  1. +Input events arrive from the hardware/widget code into the APZ via APZCTreeManager::ReceiveInputEvent. +The thread that invokes this is called the input thread, and may or may not be the same as the Gecko main thread. +
  2. +
  3. +Conceptually the first thing that the APZCTreeManager does is to group these events into "input blocks". +An input block is a contiguous set of events that get handled together. +For example with touch events, all events following a touchstart up to but not including the next touchstart are in the same block. +All of the events in a given block will go to the same APZC instance and will either all be processed or all be dropped. +
  4. +
  5. +Using the first event in the input block, the APZCTreeManager does a hit-test to see which APZC it hits. +If no APZC is hit, the events are discarded and we jump to step 6. +Otherwise, the input block is tagged with the APZC and put into a global APZ input queue. +
  6. +
  7. +
      +
    1. + If the input events are not touch events, or if the APZC is for content without touch listeners, any available events in the input block are processed. + These may trigger behaviours like scrolling or tap gestures. +
    2. +
    3. + If the input events are touch events and the APZC is for content with touch listeners, the events are left in the queue and a 300ms timeout is initiated. + If the timeout expires before step 9 is completed, the APZ assumes the input block was not cancelled and processes them as part of step 10. +
    4. +
    +
  8. +
  9. +The call stack unwinds back to APZCTreeManager::ReceiveInputEvent, which does an in-place modification of the input event so that any async transforms are removed. +
  10. +
  11. +The call stack unwinds back to the widget code that called ReceiveInputEvent. +This code now has the event in the coordinate space Gecko is expecting, and so can dispatch it to the Gecko main thread. +
  12. +
  13. +Gecko performs its own usual hit-testing and event dispatching for the event. +As part of this, it records whether any touch listeners cancelled the input block by calling preventDefault(). +
  14. +
  15. +The call stack unwinds back to the widget code, which sends a notification to the APZ code by calling APZCTreeManager::ContentReceivedTouch on the input thread. +This happens only once per input block. +
  16. +
  17. +
      +
    1. + If the events were processed as part of step 4(i), the call to ContentReceivedTouch is ignored and step 10 is skipped. +
    2. +
    3. + If events were queued as part of step 4(ii), and steps 5-8 take less than 300ms, the ContentReceivedTouch call marks the input block ready for processing. +
    4. +
    5. + If events were queued as part of step 4(ii), but steps 5-8 take longer than 300ms, the ContentReceivedTouch will be ignored and step 10 will already have happened. +
    6. +
    +
  18. +
  19. +If events were queued as part of step 4(ii) they are now either processed (if the input block was not cancelled, or if the timeout expired) or dropped (if it was cancelled). +Processing the events may trigger behaviours like scrolling or tap gestures. +
  20. +
+ +If the CSS touch-action property is enabled, the above steps are modified as follows: +
    +
  • + In step 4, the APZC also requires the allowed touch-action behaviours for the input event. This is not available yet, so the events are always queued. +
  • +
  • + In step 6, the widget code determines the content element at the point under the input element, and notifies the APZ code of the allowed touch-action behaviours. + This is done via a call to APZCTreeManager::SetAllowedTouchBehavior on the input thread. +
  • +
+ +#### Threading considerations + +The bulk of the input processing in the APZ code happens on what we call "the input thread". +In practice the input thread could be the Gecko main thread, the compositor thread, or some other thread. +There are obvious downsides to using the Gecko main thread - that is, "asynchronous" panning and zooming is not really asynchronous as input events can only be processed while Gecko is idle. +However, this is the current state of things on B2G and Metro. +Using the compositor thread as the input thread could work on some platforms, but may be inefficient on others. +For example, on Android (Fennec) we receive input events from the system on a dedicated UI thread. +We would have to redispatch the input events to the compositor thread if we wanted to the input thread to be the same as the compositor thread. +This introduces a potential for higher latency, particularly if the compositor does any blocking operations - blocking SwapBuffers operations, for example. +As a result, the APZ code itself does not assume that the input thread will be the same as the Gecko main thread or the compositor thread. + +#### Active vs. inactive scrollframes + +The number of scrollframes on a page is potentially unbounded. +However, we do not want to create a separate layer for each scrollframe right away, as this would require large amounts of memory. +Therefore, scrollframes as designated as either "active" or "inactive". +Active scrollframes are the ones that do have their contents put on a separate layer (or set of layers), and inactive ones do not. + +Consider a page with a scrollframe that is initially inactive. +When layout generates the layers for this page, it inserts a "scrollinfo" layer into the layer tree to let the APZ know that there is potentially scrollable content there. +The scrollinfo layer is an empty ContainerLayer, which does not require much extra memory. +The composition bounds of this scrollinfo layer are used on the compositor for hit-testing, and a "placeholder" APZC is created for this scrollframe. +When the user starts interacting with that content, the hit-test in the APZ code finds the placeholder APZC and starts routing it the events as usual. +The APZC eventually sends a repaint request to the main thread, and that repaint request sets a displayport on the scrollframe. +Setting the displayport activates the scrollframe and causes it to get pushed onto a separate layer (or set of layers). + +This model imples that when the user initially attempts to scroll an inactive scrollframe, it will not initially scroll visually. +(This is because although the APZC is tracking the events and updating scroll position, there is no layer to which it can apply the async scroll offset.) +Only after the round-trip to the gecko thread is complete is there a layer for async scrolling to actually occur. +At that point the scrollframe will visually "jump" to the correct scroll offset. From da599d44645097df0086ed91f0eb76d8272c2f5e Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Mon, 10 Nov 2014 22:06:24 +0000 Subject: [PATCH 24/71] Bug 1013211 - Use the final resource URI after redirects etc as the source URI when dragging an image. r=roc --- dom/base/nsContentAreaDragDrop.cpp | 30 +++++++++++---------- image/public/imgIRequest.idl | 7 ++++- image/src/imgRequest.cpp | 42 ++++++++++++++++++++++++------ image/src/imgRequest.h | 1 + image/src/imgRequestProxy.cpp | 8 ++++++ 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/dom/base/nsContentAreaDragDrop.cpp b/dom/base/nsContentAreaDragDrop.cpp index 1e8719f4d7d..6be452b1a9b 100644 --- a/dom/base/nsContentAreaDragDrop.cpp +++ b/dom/base/nsContentAreaDragDrop.cpp @@ -515,14 +515,6 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer, // grab the href as the url, use alt text as the title of the // area if it's there. the drag data is the image tag and src // attribute. - nsCOMPtr imageURI; - image->GetCurrentURI(getter_AddRefs(imageURI)); - if (imageURI) { - nsAutoCString spec; - imageURI->GetSpec(spec); - CopyUTF8toUTF16(spec, mUrlString); - } - nsCOMPtr imageElement(do_QueryInterface(image)); // XXXbz Shouldn't we use the "title" attr for title? Using // "alt" seems very wrong.... @@ -530,13 +522,10 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer, imageElement->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString); } - if (mTitleString.IsEmpty()) { - mTitleString = mUrlString; - } - - nsCOMPtr imgRequest; + mUrlString.Truncate(); // grab the image data, and its request. + nsCOMPtr imgRequest; nsCOMPtr img = nsContentUtils::GetImageFromContent(image, getter_AddRefs(imgRequest)); @@ -547,7 +536,7 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer, // Fix the file extension in the URL if necessary if (imgRequest && mimeService) { nsCOMPtr imgUri; - imgRequest->GetURI(getter_AddRefs(imgUri)); + imgRequest->GetCurrentURI(getter_AddRefs(imgUri)); nsCOMPtr imgUrl(do_QueryInterface(imgUri)); @@ -568,6 +557,7 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer, // pass out the image source string CopyUTF8toUTF16(spec, mImageSourceString); + mUrlString = mImageSourceString; bool validExtension; if (extension.IsEmpty() || @@ -602,6 +592,18 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer, } } } + if (mUrlString.IsEmpty()) { + nsCOMPtr imageURI; + image->GetCurrentURI(getter_AddRefs(imageURI)); + if (imageURI) { + nsAutoCString spec; + imageURI->GetSpec(spec); + CopyUTF8toUTF16(spec, mUrlString); + } + } + if (mTitleString.IsEmpty()) { + mTitleString = mUrlString; + } if (parentLink) { // If we are dragging around an image in an anchor, then we diff --git a/image/public/imgIRequest.idl b/image/public/imgIRequest.idl index 61e3e4342b9..2c8a25ca154 100644 --- a/image/public/imgIRequest.idl +++ b/image/public/imgIRequest.idl @@ -19,7 +19,7 @@ interface nsIPrincipal; * @version 0.1 * @see imagelib2 */ -[scriptable, builtinclass, uuid(710f22f0-558b-11e4-8ed6-0800200c9a66)] +[scriptable, builtinclass, uuid(dc61f0ea-4139-4c2a-ae69-cec82d33e089)] interface imgIRequest : nsIRequest { /** @@ -83,6 +83,11 @@ interface imgIRequest : nsIRequest */ readonly attribute nsIURI URI; + /** + * The URI of the resource we ended up loading after all redirects, etc. + */ + readonly attribute nsIURI currentURI; + readonly attribute imgINotificationObserver notificationObserver; readonly attribute string mimeType; diff --git a/image/src/imgRequest.cpp b/image/src/imgRequest.cpp index 3bca07711e3..533c46c2385 100644 --- a/image/src/imgRequest.cpp +++ b/image/src/imgRequest.cpp @@ -40,14 +40,17 @@ using namespace mozilla; using namespace mozilla::image; #if defined(PR_LOGGING) -PRLogModuleInfo * +PRLogModuleInfo* GetImgLog() { - static PRLogModuleInfo *sImgLog; + static PRLogModuleInfo* sImgLog; if (!sImgLog) sImgLog = PR_NewLogModule("imgRequest"); return sImgLog; } +#define LOG_TEST(level) (GetImgLog() && PR_LOG_TEST(GetImgLog(), (level))) +#else +#define LOG_TEST(level) false #endif NS_IMPL_ISUPPORTS(imgRequest, @@ -367,6 +370,21 @@ nsresult imgRequest::GetURI(ImageURL **aURI) return NS_ERROR_FAILURE; } +nsresult imgRequest::GetCurrentURI(nsIURI **aURI) +{ + MOZ_ASSERT(aURI); + + LOG_FUNC(GetImgLog(), "imgRequest::GetCurrentURI"); + + if (mCurrentURI) { + *aURI = mCurrentURI; + NS_ADDREF(*aURI); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + nsresult imgRequest::GetImageErrorCode() { return mImageErrorCode; @@ -1064,16 +1082,24 @@ imgRequest::OnRedirectVerifyCallback(nsresult result) mTimedChannel = do_QueryInterface(mChannel); mNewRedirectChannel = nullptr; -#if defined(PR_LOGGING) - nsAutoCString oldspec; - if (mCurrentURI) - mCurrentURI->GetSpec(oldspec); - LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnChannelRedirect", "old", oldspec.get()); -#endif + if (LOG_TEST(PR_LOG_DEBUG)) { + nsAutoCString spec; + if (mCurrentURI) + mCurrentURI->GetSpec(spec); + LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnChannelRedirect", "old", spec.get()); + } // make sure we have a protocol that returns data rather than opens // an external application, e.g. mailto: mChannel->GetURI(getter_AddRefs(mCurrentURI)); + + if (LOG_TEST(PR_LOG_DEBUG)) { + nsAutoCString spec; + if (mCurrentURI) + mCurrentURI->GetSpec(spec); + LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnChannelRedirect", "new", spec.get()); + } + bool doesNotReturnData = false; nsresult rv = NS_URIChainHasFlags(mCurrentURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, diff --git a/image/src/imgRequest.h b/image/src/imgRequest.h index 895d6787402..565e6491483 100644 --- a/image/src/imgRequest.h +++ b/image/src/imgRequest.h @@ -137,6 +137,7 @@ public: // OK to use on any thread. nsresult GetURI(ImageURL **aURI); + nsresult GetCurrentURI(nsIURI **aURI); nsresult GetImageErrorCode(void); diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp index 17fbe76563d..a941554f318 100644 --- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -537,6 +537,14 @@ NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI) return NS_OK; } +nsresult imgRequestProxy::GetCurrentURI(nsIURI **aURI) +{ + if (!GetOwner()) + return NS_ERROR_FAILURE; + + return GetOwner()->GetCurrentURI(aURI); +} + nsresult imgRequestProxy::GetURI(ImageURL **aURI) { if (!mURI) From f4f4964baf95d14f20e03b4b9e18f92e4c7c6249 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Tue, 11 Nov 2014 07:29:44 +0900 Subject: [PATCH 25/71] Bug 1093595 - Treat SSL3 and RC4 as broken. r=keeler --- security/manager/ssl/src/nsNSSCallbacks.cpp | 172 ++++++++++---------- 1 file changed, 89 insertions(+), 83 deletions(-) diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp index 91b3a1d3d5f..75b3935b1b3 100644 --- a/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -1172,6 +1172,92 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { infoObject->GetPort(), versions.max); + bool weakEncryption = false; + SSLChannelInfo channelInfo; + rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)); + MOZ_ASSERT(rv == SECSuccess); + if (rv == SECSuccess) { + // Get the protocol version for telemetry + // 0=ssl3, 1=tls1, 2=tls1.1, 3=tls1.2 + unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; + Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum); + AccumulateCipherSuite( + infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL + : Telemetry::SSL_CIPHER_SUITE_RESUMED, + channelInfo); + + SSLCipherSuiteInfo cipherInfo; + rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof cipherInfo); + MOZ_ASSERT(rv == SECSuccess); + if (rv == SECSuccess) { + weakEncryption = + (channelInfo.protocolVersion <= SSL_LIBRARY_VERSION_3_0) || + (cipherInfo.symCipher == ssl_calg_rc4); + + // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4 + Telemetry::Accumulate( + infoObject->IsFullHandshake() + ? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL + : Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED, + cipherInfo.keaType); + + DebugOnly KEAUsed; + MOZ_ASSERT(NS_SUCCEEDED(infoObject->GetKEAUsed(&KEAUsed)) && + (KEAUsed == cipherInfo.keaType)); + + if (infoObject->IsFullHandshake()) { + switch (cipherInfo.keaType) { + case ssl_kea_rsa: + AccumulateNonECCKeySize(Telemetry::SSL_KEA_RSA_KEY_SIZE_FULL, + channelInfo.keaKeyBits); + break; + case ssl_kea_dh: + AccumulateNonECCKeySize(Telemetry::SSL_KEA_DHE_KEY_SIZE_FULL, + channelInfo.keaKeyBits); + break; + case ssl_kea_ecdh: + AccumulateECCCurve(Telemetry::SSL_KEA_ECDHE_CURVE_FULL, + channelInfo.keaKeyBits); + break; + default: + MOZ_CRASH("impossible KEA"); + break; + } + + Telemetry::Accumulate(Telemetry::SSL_AUTH_ALGORITHM_FULL, + cipherInfo.authAlgorithm); + + // RSA key exchange doesn't use a signature for auth. + if (cipherInfo.keaType != ssl_kea_rsa) { + switch (cipherInfo.authAlgorithm) { + case ssl_auth_rsa: + AccumulateNonECCKeySize(Telemetry::SSL_AUTH_RSA_KEY_SIZE_FULL, + channelInfo.authKeyBits); + break; + case ssl_auth_dsa: + AccumulateNonECCKeySize(Telemetry::SSL_AUTH_DSA_KEY_SIZE_FULL, + channelInfo.authKeyBits); + break; + case ssl_auth_ecdsa: + AccumulateECCCurve(Telemetry::SSL_AUTH_ECDSA_CURVE_FULL, + channelInfo.authKeyBits); + break; + default: + MOZ_CRASH("impossible auth algorithm"); + break; + } + } + } + + Telemetry::Accumulate( + infoObject->IsFullHandshake() + ? Telemetry::SSL_SYMMETRIC_CIPHER_FULL + : Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED, + cipherInfo.symCipher); + } + } + PRBool siteSupportsSafeRenego; rv = SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn, &siteSupportsSafeRenego); @@ -1180,8 +1266,9 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { siteSupportsSafeRenego = false; } - if (siteSupportsSafeRenego || - !ioLayerHelpers.treatUnsafeNegotiationAsBroken()) { + if (!weakEncryption && + (siteSupportsSafeRenego || + !ioLayerHelpers.treatUnsafeNegotiationAsBroken())) { infoObject->SetSecurityState(nsIWebProgressListener::STATE_IS_SECURE | nsIWebProgressListener::STATE_SECURE_HIGH); } else { @@ -1246,87 +1333,6 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { } } - SSLChannelInfo channelInfo; - rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)); - MOZ_ASSERT(rv == SECSuccess); - if (rv == SECSuccess) { - // Get the protocol version for telemetry - // 0=ssl3, 1=tls1, 2=tls1.1, 3=tls1.2 - unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; - Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum); - AccumulateCipherSuite( - infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL - : Telemetry::SSL_CIPHER_SUITE_RESUMED, - channelInfo); - - SSLCipherSuiteInfo cipherInfo; - rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, - sizeof cipherInfo); - MOZ_ASSERT(rv == SECSuccess); - if (rv == SECSuccess) { - // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4 - Telemetry::Accumulate( - infoObject->IsFullHandshake() - ? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL - : Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED, - cipherInfo.keaType); - - DebugOnly KEAUsed; - MOZ_ASSERT(NS_SUCCEEDED(infoObject->GetKEAUsed(&KEAUsed)) && - (KEAUsed == cipherInfo.keaType)); - - if (infoObject->IsFullHandshake()) { - switch (cipherInfo.keaType) { - case ssl_kea_rsa: - AccumulateNonECCKeySize(Telemetry::SSL_KEA_RSA_KEY_SIZE_FULL, - channelInfo.keaKeyBits); - break; - case ssl_kea_dh: - AccumulateNonECCKeySize(Telemetry::SSL_KEA_DHE_KEY_SIZE_FULL, - channelInfo.keaKeyBits); - break; - case ssl_kea_ecdh: - AccumulateECCCurve(Telemetry::SSL_KEA_ECDHE_CURVE_FULL, - channelInfo.keaKeyBits); - break; - default: - MOZ_CRASH("impossible KEA"); - break; - } - - Telemetry::Accumulate(Telemetry::SSL_AUTH_ALGORITHM_FULL, - cipherInfo.authAlgorithm); - - // RSA key exchange doesn't use a signature for auth. - if (cipherInfo.keaType != ssl_kea_rsa) { - switch (cipherInfo.authAlgorithm) { - case ssl_auth_rsa: - AccumulateNonECCKeySize(Telemetry::SSL_AUTH_RSA_KEY_SIZE_FULL, - channelInfo.authKeyBits); - break; - case ssl_auth_dsa: - AccumulateNonECCKeySize(Telemetry::SSL_AUTH_DSA_KEY_SIZE_FULL, - channelInfo.authKeyBits); - break; - case ssl_auth_ecdsa: - AccumulateECCCurve(Telemetry::SSL_AUTH_ECDSA_CURVE_FULL, - channelInfo.authKeyBits); - break; - default: - MOZ_CRASH("impossible auth algorithm"); - break; - } - } - } - - Telemetry::Accumulate( - infoObject->IsFullHandshake() - ? Telemetry::SSL_SYMMETRIC_CIPHER_FULL - : Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED, - cipherInfo.symCipher); - } - } - infoObject->NoteTimeUntilReady(); infoObject->SetHandshakeCompleted(); } From 55d966ec5f3dfdad417d1822bd437dbb4225667e Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Tue, 11 Nov 2014 07:29:44 +0900 Subject: [PATCH 26/71] Bug 1093595 - Change strings to add a description about weak encryption. r=dolske --- browser/base/content/browser.js | 4 ++-- browser/base/content/pageinfo/security.js | 2 +- browser/locales/en-US/chrome/browser/browser.properties | 2 +- .../manager/locales/en-US/chrome/pippki/pippki.properties | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index dbdba9a10d6..69f7b7b8fa2 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -6682,11 +6682,11 @@ var gIdentityHandler = { this._encryptionLabel[this.IDENTITY_MODE_UNKNOWN] = gNavigatorBundle.getString("identity.unencrypted"); this._encryptionLabel[this.IDENTITY_MODE_MIXED_DISPLAY_LOADED] = - gNavigatorBundle.getString("identity.mixed_display_loaded"); + gNavigatorBundle.getString("identity.broken_loaded"); this._encryptionLabel[this.IDENTITY_MODE_MIXED_ACTIVE_LOADED] = gNavigatorBundle.getString("identity.mixed_active_loaded2"); this._encryptionLabel[this.IDENTITY_MODE_MIXED_DISPLAY_LOADED_ACTIVE_BLOCKED] = - gNavigatorBundle.getString("identity.mixed_display_loaded"); + gNavigatorBundle.getString("identity.broken_loaded"); return this._encryptionLabel; }, get _identityPopup () { diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js index 811c57fe041..055c0379ed6 100644 --- a/browser/base/content/pageinfo/security.js +++ b/browser/base/content/pageinfo/security.js @@ -254,7 +254,7 @@ function securityOnLoad() { if (info.isBroken) { hdr = pkiBundle.getString("pageInfo_MixedContent"); - msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1"); + msg1 = pkiBundle.getString("pageInfo_Privacy_Broken1"); msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); } else if (info.encryptionStrength > 0) { diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties index c7fdc70c737..1a51d075575 100644 --- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -295,7 +295,7 @@ identity.identified.verified_by_you=You have added a security exception for this identity.identified.state_and_country=%S, %S identity.encrypted2=The connection to this website is secure. -identity.mixed_display_loaded=The connection to this website is not fully secure because it contains unencrypted elements (such as images). +identity.broken_loaded=The connection to this website is not fully secure because it contains unencrypted elements (such as images) or the encryption is not strong enough. identity.mixed_active_loaded2=This website contains interactive content that isn't encrypted (such as scripts). Other people can view your information or modify the website's behavior. identity.unencrypted=Your connection to this website is not encrypted. diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 961e7e461ad..23f0be0dd8d 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -80,7 +80,7 @@ pageInfo_EncryptionWithBitsAndProtocol=Connection Encrypted (%1$S, %2$S bit keys pageInfo_Privacy_Encrypted1=The page you are viewing was encrypted before being transmitted over the Internet. pageInfo_Privacy_Encrypted2=Encryption makes it difficult for unauthorized people to view information traveling between computers. It is therefore unlikely that anyone read this page as it traveled across the network. pageInfo_MixedContent=Connection Partially Encrypted -pageInfo_Privacy_Mixed1=Parts of the page you are viewing were not encrypted before being transmitted over the Internet. +pageInfo_Privacy_Broken1=Parts of the page you are viewing were not encrypted or the encryption is not strong enough before being transmitted over the Internet. #Cert Viewer certDetails=Certificate Viewer: From 8f5483146c9244accd0a86333c77acf11bd07e51 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 10 Nov 2014 14:37:25 -0800 Subject: [PATCH 27/71] Backed out changeset fdcf11277625 (bug 1074961) for ggc bustage on a CLOSED TREE --- js/src/gc/GCRuntime.h | 8 +- js/src/gc/Heap.h | 17 +++- js/src/jsgc.cpp | 226 +++++++++++++++++------------------------- js/src/jsgc.h | 20 +++- 4 files changed, 122 insertions(+), 149 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index b91c25a2b30..33643a212b8 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -271,7 +271,6 @@ class GCRuntime void decFJMinorCollecting() { fjCollectionCounter--; } bool triggerGC(JS::gcreason::Reason reason); - void maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock); bool triggerZoneGC(Zone *zone, JS::gcreason::Reason reason); bool maybeGC(Zone *zone); void maybePeriodicFullGC(); @@ -482,15 +481,11 @@ class GCRuntime void freeUnusedLifoBlocksAfterSweeping(LifoAlloc *lifo); void freeAllLifoBlocksAfterSweeping(LifoAlloc *lifo); - // Public here for ReleaseArenaLists and FinalizeTypedArenas. - void releaseArena(ArenaHeader *aheader, const AutoLockGC &lock); - private: // For ArenaLists::allocateFromArena() friend class ArenaLists; Chunk *pickChunk(const AutoLockGC &lock, AutoMaybeStartBackgroundAllocation &maybeStartBGAlloc); - ArenaHeader *allocateArena(Chunk *chunk, Zone *zone, AllocKind kind, const AutoLockGC &lock); inline void arenaAllocatedDuringGC(JS::Zone *zone, ArenaHeader *arena); template @@ -549,7 +544,8 @@ class GCRuntime void endSweepPhase(bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); void decommitAllWithoutUnlocking(const AutoLockGC &lock); - void decommitArenas(const AutoLockGC &lock); + void decommitArenasFromAvailableList(Chunk **availableListHeadp); + void decommitArenas(); void expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock); void sweepBackgroundThings(); void assertBackgroundSweepingFinished(); diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index ae6c8a17678..43041baf01f 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -37,7 +37,6 @@ struct Runtime; namespace js { -class AutoLockGC; class FreeOp; #ifdef DEBUG @@ -946,10 +945,9 @@ struct Chunk inline void insertToAvailableList(Chunk **insertPoint); inline void removeFromAvailableList(); - ArenaHeader *allocateArena(JSRuntime *rt, JS::Zone *zone, AllocKind kind, - const AutoLockGC &lock); + ArenaHeader *allocateArena(JS::Zone *zone, AllocKind kind); - void releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock); + void releaseArena(ArenaHeader *aheader); void recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thingKind, size_t thingsPerArena); @@ -1149,6 +1147,17 @@ ArenaHeader::unsetAllocDuringSweep() auxNextLink = 0; } +inline void +ReleaseArenaList(ArenaHeader *aheader) +{ + ArenaHeader *next; + for (; aheader; aheader = next) { + // Copy aheader->next before releasing. + next = aheader->next; + aheader->chunk()->releaseArena(aheader); + } +} + static void AssertValidColor(const TenuredCell *thing, uint32_t color) { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 55e9e561619..ca9059feb11 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -545,9 +545,6 @@ Arena::finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize) return nmarked; } -// Finalize arenas from src list, releasing empty arenas if keepArenas wasn't -// specified and inserting the others into the appropriate destination size -// bins. template static inline bool FinalizeTypedArenas(FreeOp *fop, @@ -557,10 +554,11 @@ FinalizeTypedArenas(FreeOp *fop, SliceBudget &budget, ArenaLists::KeepArenasEnum keepArenas) { - // When operating in the foreground, take the lock at the top. - Maybe maybeLock; - if (!fop->runtime()->gc.isBackgroundSweeping()) - maybeLock.emplace(fop->runtime()); + /* + * Finalize arenas from src list, releasing empty arenas if keepArenas + * wasn't specified and inserting the others into the appropriate + * destination size bins. + */ /* * During parallel sections, we sometimes finalize the parallel arenas, @@ -577,18 +575,12 @@ FinalizeTypedArenas(FreeOp *fop, size_t nmarked = aheader->getArena()->finalize(fop, thingKind, thingSize); size_t nfree = thingsPerArena - nmarked; - if (nmarked) { + if (nmarked) dest.insertAt(aheader, nfree); - } else if (keepArenas) { + else if (keepArenas) aheader->chunk()->recycleArena(aheader, dest, thingKind, thingsPerArena); - } else if (fop->runtime()->gc.isBackgroundSweeping()) { - // When background sweeping, take the lock around each release so - // that we do not block the foreground for extended periods. - AutoLockGC lock(fop->runtime()); - fop->runtime()->gc.releaseArena(aheader, lock); - } else { - fop->runtime()->gc.releaseArena(aheader, maybeLock.ref()); - } + else + aheader->chunk()->releaseArena(aheader); budget.step(thingsPerArena); if (budget.isOverBudget()) @@ -953,14 +945,67 @@ Chunk::fetchNextFreeArena(JSRuntime *rt) } ArenaHeader * -Chunk::allocateArena(JSRuntime *rt, Zone *zone, AllocKind thingKind, const AutoLockGC &lock) +Chunk::allocateArena(Zone *zone, AllocKind thingKind) { - ArenaHeader *aheader = info.numArenasFreeCommitted > 0 + MOZ_ASSERT(hasAvailableArenas()); + + JSRuntime *rt = zone->runtimeFromAnyThread(); + if (!rt->isHeapMinorCollecting() && + !rt->isHeapCompacting() && + rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) + { +#ifdef JSGC_FJGENERATIONAL + // This is an approximation to the best test, which would check that + // this thread is currently promoting into the tenured area. I doubt + // the better test would make much difference. + if (!rt->isFJMinorCollecting()) + return nullptr; +#else + return nullptr; +#endif + } + + ArenaHeader *aheader = MOZ_LIKELY(info.numArenasFreeCommitted > 0) ? fetchNextFreeArena(rt) : fetchNextDecommittedArena(); aheader->init(zone, thingKind); if (MOZ_UNLIKELY(!hasAvailableArenas())) removeFromAvailableList(); + + zone->usage.addGCArena(); + + if (!rt->isHeapCompacting()) { + size_t usedBytes = zone->usage.gcBytes(); + size_t thresholdBytes = zone->threshold.gcTriggerBytes(); + size_t igcThresholdBytes = thresholdBytes * rt->gc.tunables.zoneAllocThresholdFactor(); + + if (usedBytes >= thresholdBytes) { + // The threshold has been surpassed, immediately trigger a GC, + // which will be done non-incrementally. + AutoUnlockGC unlock(rt); + rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + } else if (usedBytes >= igcThresholdBytes) { + // Reduce the delay to the start of the next incremental slice. + if (zone->gcDelayBytes < ArenaSize) + zone->gcDelayBytes = 0; + else + zone->gcDelayBytes -= ArenaSize; + + if (!zone->gcDelayBytes) { + // Start or continue an in progress incremental GC. We do this + // to try to avoid performing non-incremental GCs on zones + // which allocate a lot of data, even when incremental slices + // can't be triggered via scheduling in the event loop. + AutoUnlockGC unlock(rt); + rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + + // Delay the next slice until a certain amount of allocation + // has been performed. + zone->gcDelayBytes = rt->gc.tunables.zoneAllocDelayBytes(); + } + } + } + return aheader; } @@ -990,10 +1035,20 @@ Chunk::recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thing } void -Chunk::releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) +Chunk::releaseArena(ArenaHeader *aheader) { MOZ_ASSERT(aheader->allocated()); MOZ_ASSERT(!aheader->hasDelayedMarking); + Zone *zone = aheader->zone; + JSRuntime *rt = zone->runtimeFromAnyThread(); + + Maybe maybeLock; + if (rt->gc.isBackgroundSweeping()) + maybeLock.emplace(rt); + + if (rt->gc.isBackgroundSweeping()) + zone->threshold.updateForRemovedArena(rt->gc.tunables); + zone->usage.removeGCArena(); aheader->setAsNotAllocated(); addArenaToFreeList(rt, aheader); @@ -1005,10 +1060,12 @@ Chunk::releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) } else if (!unused()) { MOZ_ASSERT(info.prevp); } else { + if (maybeLock.isNothing()) + maybeLock.emplace(rt); MOZ_ASSERT(unused()); removeFromAvailableList(); decommitAllArenas(rt); - rt->gc.moveChunkToFreePool(this, lock); + rt->gc.moveChunkToFreePool(this, maybeLock.ref()); } } @@ -1111,46 +1168,6 @@ GCRuntime::pickChunk(const AutoLockGC &lock, return chunk; } -ArenaHeader * -GCRuntime::allocateArena(Chunk *chunk, Zone *zone, AllocKind thingKind, const AutoLockGC &lock) -{ - MOZ_ASSERT(chunk->hasAvailableArenas()); - - // Fail the allocation if we are over our heap size limits. - if (!isHeapMinorCollecting() && - !isHeapCompacting() && - usage.gcBytes() >= tunables.gcMaxBytes()) - { -#ifdef JSGC_FJGENERATIONAL - // This is an approximation to the best test, which would check that - // this thread is currently promoting into the tenured area. I doubt - // the better test would make much difference. - if (!isFJMinorCollecting()) - return nullptr; -#else - return nullptr; -#endif - } - - ArenaHeader *aheader = chunk->allocateArena(rt, zone, thingKind, lock); - zone->usage.addGCArena(); - - // Trigger an incremental slice if needed. - if (!isHeapMinorCollecting() && !isHeapCompacting()) - maybeAllocTriggerZoneGC(zone, lock); - - return aheader; -} - -void -GCRuntime::releaseArena(ArenaHeader *aheader, const AutoLockGC &lock) -{ - aheader->zone->usage.removeGCArena(); - if (isBackgroundSweeping()) - aheader->zone->threshold.updateForRemovedArena(tunables); - return aheader->chunk()->releaseArena(rt, aheader, lock); -} - GCRuntime::GCRuntime(JSRuntime *rt) : rt(rt), systemZone(nullptr), @@ -1896,8 +1913,7 @@ ZoneHeapThreshold::updateForRemovedArena(const GCSchedulingTunables &tunables) } Allocator::Allocator(Zone *zone) - : arenas(zone->runtimeFromMainThread()), - zone_(zone) + : zone_(zone) {} inline void @@ -1983,7 +1999,7 @@ ArenaLists::allocateFromArena(JS::Zone *zone, AllocKind thingKind, // Although our chunk should definitely have enough space for another arena, // there are other valid reasons why Chunk::allocateArena() may fail. - aheader = rt->gc.allocateArena(chunk, zone, thingKind, maybeLock.ref()); + aheader = chunk->allocateArena(zone, thingKind); if (!aheader) return nullptr; @@ -2544,7 +2560,6 @@ void GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) { // Release the relocated arenas, now containing only forwarding pointers - AutoLockGC lock(rt); unsigned count = 0; while (relocatedList) { @@ -2567,7 +2582,7 @@ GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) JS_MOVED_TENURED_PATTERN, Arena::thingsSpan(thingSize)); #endif - releaseArena(aheader, lock); + aheader->chunk()->releaseArena(aheader); ++count; } @@ -2577,35 +2592,6 @@ GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) #endif // JSGC_COMPACTING -void -ReleaseArenaList(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) -{ - ArenaHeader *next; - for (; aheader; aheader = next) { - next = aheader->next; - rt->gc.releaseArena(aheader, lock); - } -} - -ArenaLists::~ArenaLists() -{ - AutoLockGC lock(runtime_); - - for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { - /* - * We can only call this during the shutdown after the last GC when - * the background finalization is disabled. - */ - MOZ_ASSERT(backgroundFinalizeState[i] == BFS_DONE); - ReleaseArenaList(runtime_, arenaLists[i].head(), lock); - } - ReleaseArenaList(runtime_, incrementalSweptArenas.head(), lock); - - for (size_t i = 0; i < FINALIZE_OBJECT_LIMIT; i++) - ReleaseArenaList(runtime_, savedObjectArenas[i].head(), lock); - ReleaseArenaList(runtime_, savedEmptyObjectArenas, lock); -} - void ArenaLists::finalizeNow(FreeOp *fop, const FinalizePhase& phase) { @@ -2772,8 +2758,7 @@ ArenaLists::queueForegroundObjectsForSweep(FreeOp *fop) void ArenaLists::mergeForegroundSweptObjectArenas() { - AutoLockGC lock(runtime_); - ReleaseArenaList(runtime_, savedEmptyObjectArenas, lock); + ReleaseArenaList(savedEmptyObjectArenas); savedEmptyObjectArenas = nullptr; mergeSweptArenas(FINALIZE_OBJECT0); @@ -3045,40 +3030,6 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason) return true; } -void -GCRuntime::maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock) -{ - size_t usedBytes = zone->usage.gcBytes(); - size_t thresholdBytes = zone->threshold.gcTriggerBytes(); - size_t igcThresholdBytes = thresholdBytes * tunables.zoneAllocThresholdFactor(); - - if (usedBytes >= thresholdBytes) { - // The threshold has been surpassed, immediately trigger a GC, - // which will be done non-incrementally. - AutoUnlockGC unlock(rt); - triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); - } else if (usedBytes >= igcThresholdBytes) { - // Reduce the delay to the start of the next incremental slice. - if (zone->gcDelayBytes < ArenaSize) - zone->gcDelayBytes = 0; - else - zone->gcDelayBytes -= ArenaSize; - - if (!zone->gcDelayBytes) { - // Start or continue an in progress incremental GC. We do this - // to try to avoid performing non-incremental GCs on zones - // which allocate a lot of data, even when incremental slices - // can't be triggered via scheduling in the event loop. - AutoUnlockGC unlock(rt); - triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); - - // Delay the next slice until a certain amount of allocation - // has been performed. - zone->gcDelayBytes = tunables.zoneAllocDelayBytes(); - } - } -} - bool GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) { @@ -3198,9 +3149,8 @@ GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC &lock) } void -GCRuntime::decommitArenas(const AutoLockGC &lock) +GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) { - Chunk **availableListHeadp = &availableChunkListHead; Chunk *chunk = *availableListHeadp; if (!chunk) return; @@ -3307,6 +3257,12 @@ GCRuntime::decommitArenas(const AutoLockGC &lock) } } +void +GCRuntime::decommitArenas() +{ + decommitArenasFromAvailableList(&availableChunkListHead); +} + void GCRuntime::expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock) { @@ -3320,7 +3276,7 @@ GCRuntime::expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock) } if (shouldShrink) - decommitArenas(lock); + decommitArenas(); } void @@ -6695,7 +6651,7 @@ ArenaLists::adoptArenas(JSRuntime *rt, ArenaLists *fromArenaLists) // Therefore, if fromHeader is empty, send it back to the // chunk now. Otherwise, attach to |toList|. if (fromHeader->isEmpty()) - rt->gc.releaseArena(fromHeader, lock); + fromHeader->chunk()->releaseArena(fromHeader); else toList->insertAtCursor(fromHeader); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index ec51d5709e9..f273f35c4c2 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -595,8 +595,6 @@ class SortedArenaList class ArenaLists { - JSRuntime *runtime_; - /* * For each arena kind its free list is represented as the first span with * free things. Initially all the spans are initialized as empty. After we @@ -641,7 +639,7 @@ class ArenaLists ArenaHeader *savedEmptyObjectArenas; public: - ArenaLists(JSRuntime *rt) : runtime_(rt) { + ArenaLists() { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) freeLists[i].initAsEmpty(); for (size_t i = 0; i != FINALIZE_LIMIT; ++i) @@ -656,7 +654,21 @@ class ArenaLists savedEmptyObjectArenas = nullptr; } - ~ArenaLists(); + ~ArenaLists() { + for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { + /* + * We can only call this during the shutdown after the last GC when + * the background finalization is disabled. + */ + MOZ_ASSERT(backgroundFinalizeState[i] == BFS_DONE); + ReleaseArenaList(arenaLists[i].head()); + } + ReleaseArenaList(incrementalSweptArenas.head()); + + for (size_t i = 0; i < FINALIZE_OBJECT_LIMIT; i++) + ReleaseArenaList(savedObjectArenas[i].head()); + ReleaseArenaList(savedEmptyObjectArenas); + } static uintptr_t getFreeListOffset(AllocKind thingKind) { uintptr_t offset = offsetof(ArenaLists, freeLists); From f3e280bba47e0dd6cbce770ff088d5f612a6c517 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 10 Nov 2014 14:40:59 -0800 Subject: [PATCH 28/71] Backed out changeset 6a96e15c810c (bug 1093307) for ggc bustage on a CLOSED TREE --- js/src/gc/GCRuntime.h | 3 +-- js/src/jsgc.cpp | 41 +++++------------------------------------ 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 33643a212b8..4d4715adf46 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -498,7 +498,7 @@ class GCRuntime * Must be called either during the GC or with the GC lock taken. */ Chunk *expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock); - void freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock); + void freeEmptyChunks(JSRuntime *rt); void freeChunkList(Chunk *chunkListHead); void prepareToFreeChunk(ChunkInfo &info); void releaseChunk(Chunk *chunk); @@ -543,7 +543,6 @@ class GCRuntime bool sweepPhase(SliceBudget &sliceBudget); void endSweepPhase(bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); - void decommitAllWithoutUnlocking(const AutoLockGC &lock); void decommitArenasFromAvailableList(Chunk **availableListHeadp); void decommitArenas(); void expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index ca9059feb11..5864700694e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -744,22 +744,15 @@ GCRuntime::expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock) return freeList; } -static void -FreeChunkPool(JSRuntime *rt, ChunkPool &pool) +void +GCRuntime::freeEmptyChunks(JSRuntime *rt) { - for (ChunkPool::Enum e(pool); !e.empty();) { + for (ChunkPool::Enum e(emptyChunks_); !e.empty();) { Chunk *chunk = e.front(); e.removeAndPopFront(); MOZ_ASSERT(!chunk->info.numArenasFreeCommitted); FreeChunk(rt, chunk); } - MOZ_ASSERT(pool.count() == 0); -} - -void -GCRuntime::freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock) -{ - FreeChunkPool(rt, emptyChunks(lock)); } void @@ -1429,7 +1422,7 @@ GCRuntime::finish() chunkSet.clear(); } - FreeChunkPool(rt, emptyChunks_); + freeEmptyChunks(rt); if (rootsHash.initialized()) rootsHash.clear(); @@ -3129,25 +3122,6 @@ GCRuntime::maybePeriodicFullGC() #endif } -// Do all possible decommit immediately from the current thread without -// releasing the GC lock or allocating any memory. -void -GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC &lock) -{ - MOZ_ASSERT(emptyChunks(lock).count() == 0); - for (Chunk *chunk = *getAvailableChunkList(); chunk; chunk = chunk->info.next) { - for (size_t i = 0; i < ArenasPerChunk; ++i) { - if (chunk->decommittedArenas.get(i) || chunk->arenas[i].aheader.allocated()) - continue; - - if (MarkPagesUnused(&chunk->arenas[i], ArenaSize)) { - chunk->info.numArenasFreeCommitted--; - chunk->decommittedArenas.set(i); - } - } - } -} - void GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) { @@ -6242,12 +6216,7 @@ GCRuntime::onOutOfMallocMemory() // Throw away any excess chunks we have lying around. AutoLockGC lock(rt); - freeEmptyChunks(rt, lock); - - // Immediately decommit as many arenas as possible in the hopes that this - // might let the OS scrape together enough pages to satisfy the failing - // malloc request. - decommitAllWithoutUnlocking(lock); + expireChunksAndArenas(true, lock); } void From 7cb16d80945f0f63bdb1c0012ef5f19203e91ce0 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 10 Nov 2014 14:47:52 -0800 Subject: [PATCH 29/71] Backed out 3 changesets (bug 1092888) for marionette bustage on a CLOSED TREE Backed out changeset eeff2ff03d39 (bug 1092888) Backed out changeset c25a6fd7903f (bug 1092888) Backed out changeset e4e735cdd665 (bug 1092888) --- editor/reftests/reftest.list | 8 ++--- layout/base/SelectionCarets.cpp | 54 ++++++++++++++++----------------- modules/libpref/init/all.js | 1 + 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/editor/reftests/reftest.list b/editor/reftests/reftest.list index 345c1308897..835ca50fb17 100644 --- a/editor/reftests/reftest.list +++ b/editor/reftests/reftest.list @@ -98,12 +98,12 @@ skip-if(Android||B2G) needs-focus == 462758-grabbers-resizers.html 462758-grabbe == 388980-1.html 388980-1-ref.html needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html skip-if(B2G) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658 -needs-focus pref(selectioncaret.enabled,false) == 824080-1.html 824080-1-ref.html +needs-focus == 824080-1.html 824080-1-ref.html needs-focus == 824080-2.html 824080-2-ref.html -needs-focus pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html +needs-focus test-pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html needs-focus != 824080-2.html 824080-3.html -needs-focus pref(selectioncaret.enabled,false) == 824080-4.html 824080-4-ref.html -needs-focus pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html +needs-focus == 824080-4.html 824080-4-ref.html +needs-focus test-pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html needs-focus != 824080-4.html 824080-5.html needs-focus == 824080-6.html 824080-6-ref.html needs-focus pref(selectioncaret.enabled,false) == 824080-7.html 824080-7-ref.html diff --git a/layout/base/SelectionCarets.cpp b/layout/base/SelectionCarets.cpp index 434999e1c81..6c6437b8192 100644 --- a/layout/base/SelectionCarets.cpp +++ b/layout/base/SelectionCarets.cpp @@ -62,6 +62,13 @@ static const char* kSelectionCaretsLogModuleName = "SelectionCarets"; static const int32_t kMoveStartTolerancePx = 5; // Time for trigger scroll end event, in miliseconds. static const int32_t kScrollEndTimerDelay = 300; +// Read from preference "selectioncaret.noneditable". Indicate whether support +// non-editable fields selection or not. We have stable state for editable +// fields selection now. And we don't want to break this stable state when +// enabling non-editable support. So I add a pref to control to support or +// not. Once non-editable fields support is stable. We should remove this +// pref. +static bool kSupportNonEditableFields = false; NS_IMPL_ISUPPORTS(SelectionCarets, nsIReflowObserver, @@ -95,6 +102,8 @@ SelectionCarets::SelectionCarets(nsIPresShell* aPresShell) if (!addedPref) { Preferences::AddIntVarCache(&sSelectionCaretsInflateSize, "selectioncaret.inflatesize.threshold"); + Preferences::AddBoolVarCache(&kSupportNonEditableFields, + "selectioncaret.noneditable"); addedPref = true; } } @@ -480,11 +489,6 @@ SelectionCarets::UpdateSelectionCarets() // Check start and end frame is rtl or ltr text nsRefPtr fs = GetFrameSelection(); - if (!fs) { - SetVisibility(false); - return; - } - int32_t startOffset; nsIFrame* startFrame = FindFirstNodeWithFrame(mPresShell->GetDocument(), firstRange, fs, false, startOffset); @@ -498,6 +502,14 @@ SelectionCarets::UpdateSelectionCarets() return; } + // If frame isn't editable and we don't support non-editable fields, bail + // out. + if (!kSupportNonEditableFields && + (!startFrame->GetContent()->IsEditable() || + !endFrame->GetContent()->IsEditable())) { + return; + } + // Check if startFrame is after endFrame. if (nsLayoutUtils::CompareTreePosition(startFrame, endFrame) > 0) { SetVisibility(false); @@ -603,6 +615,12 @@ SelectionCarets::SelectWord() return NS_OK; } + // If frame isn't editable and we don't support non-editable fields, bail + // out. + if (!kSupportNonEditableFields && !ptFrame->GetContent()->IsEditable()) { + return NS_OK; + } + nsPoint ptInFrame = mDownPoint; nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame); @@ -642,9 +660,7 @@ SelectionCarets::SelectWord() // Clear maintain selection otherwise we cannot select less than a word nsRefPtr fs = GetFrameSelection(); - if (fs) { - fs->MaintainSelection(); - } + fs->MaintainSelection(); return rs; } @@ -734,9 +750,6 @@ SelectionCarets::DragSelection(const nsPoint &movePoint) } nsRefPtr fs = GetFrameSelection(); - if (!fs) { - return nsEventStatus_eConsumeNoDefault; - } nsresult result; nsIFrame *newFrame = nullptr; @@ -761,10 +774,6 @@ SelectionCarets::DragSelection(const nsPoint &movePoint) } nsRefPtr selection = GetSelection(); - if (!selection) { - return nsEventStatus_eConsumeNoDefault; - } - int32_t rangeCount = selection->GetRangeCount(); if (rangeCount <= 0) { return nsEventStatus_eConsumeNoDefault; @@ -815,19 +824,12 @@ SelectionCarets::GetCaretYCenterPosition() } nsRefPtr selection = GetSelection(); - if (!selection) { - return 0; - } - int32_t rangeCount = selection->GetRangeCount(); if (rangeCount <= 0) { return 0; } nsRefPtr fs = GetFrameSelection(); - if (!fs) { - return 0; - } MOZ_ASSERT(mDragMode != NONE); nsCOMPtr node; @@ -860,18 +862,14 @@ void SelectionCarets::SetSelectionDragState(bool aState) { nsRefPtr fs = GetFrameSelection(); - if (fs) { - fs->SetDragState(aState); - } + fs->SetDragState(aState); } void SelectionCarets::SetSelectionDirection(bool aForward) { nsRefPtr selection = GetSelection(); - if (selection) { - selection->SetDirection(aForward ? eDirNext : eDirPrevious); - } + selection->SetDirection(aForward ? eDirNext : eDirPrevious); } static void diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 733c33ae2c2..767f1b9bf72 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4364,6 +4364,7 @@ pref("touchcaret.expiration.time", 3000); // Turn off selection caret by default pref("selectioncaret.enabled", false); +pref("selectioncaret.noneditable", false); // This will inflate size of selection caret frame when we checking if // user click on selection caret or not. In app units. From ad212a20949c3546c7b9ab9a21cb09ed15d8855a Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 10 Nov 2014 14:55:29 -0800 Subject: [PATCH 30/71] Bug 1074961 - Part 12: Simplify the locking in releaseArena; r=sfink --HG-- extra : amend_source : 45ad5e52ee44ca41216ee15f9c6142c37a5cd106 --- js/src/gc/GCRuntime.h | 8 +- js/src/gc/Heap.h | 17 +--- js/src/jsgc.cpp | 227 +++++++++++++++++++++++++----------------- js/src/jsgc.h | 20 +--- 4 files changed, 149 insertions(+), 123 deletions(-) diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 4d4715adf46..d2f561a08c4 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -271,6 +271,7 @@ class GCRuntime void decFJMinorCollecting() { fjCollectionCounter--; } bool triggerGC(JS::gcreason::Reason reason); + void maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock); bool triggerZoneGC(Zone *zone, JS::gcreason::Reason reason); bool maybeGC(Zone *zone); void maybePeriodicFullGC(); @@ -481,11 +482,15 @@ class GCRuntime void freeUnusedLifoBlocksAfterSweeping(LifoAlloc *lifo); void freeAllLifoBlocksAfterSweeping(LifoAlloc *lifo); + // Public here for ReleaseArenaLists and FinalizeTypedArenas. + void releaseArena(ArenaHeader *aheader, const AutoLockGC &lock); + private: // For ArenaLists::allocateFromArena() friend class ArenaLists; Chunk *pickChunk(const AutoLockGC &lock, AutoMaybeStartBackgroundAllocation &maybeStartBGAlloc); + ArenaHeader *allocateArena(Chunk *chunk, Zone *zone, AllocKind kind, const AutoLockGC &lock); inline void arenaAllocatedDuringGC(JS::Zone *zone, ArenaHeader *arena); template @@ -543,8 +548,7 @@ class GCRuntime bool sweepPhase(SliceBudget &sliceBudget); void endSweepPhase(bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); - void decommitArenasFromAvailableList(Chunk **availableListHeadp); - void decommitArenas(); + void decommitArenas(const AutoLockGC &lock); void expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock); void sweepBackgroundThings(); void assertBackgroundSweepingFinished(); diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index 43041baf01f..ae6c8a17678 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -37,6 +37,7 @@ struct Runtime; namespace js { +class AutoLockGC; class FreeOp; #ifdef DEBUG @@ -945,9 +946,10 @@ struct Chunk inline void insertToAvailableList(Chunk **insertPoint); inline void removeFromAvailableList(); - ArenaHeader *allocateArena(JS::Zone *zone, AllocKind kind); + ArenaHeader *allocateArena(JSRuntime *rt, JS::Zone *zone, AllocKind kind, + const AutoLockGC &lock); - void releaseArena(ArenaHeader *aheader); + void releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock); void recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thingKind, size_t thingsPerArena); @@ -1147,17 +1149,6 @@ ArenaHeader::unsetAllocDuringSweep() auxNextLink = 0; } -inline void -ReleaseArenaList(ArenaHeader *aheader) -{ - ArenaHeader *next; - for (; aheader; aheader = next) { - // Copy aheader->next before releasing. - next = aheader->next; - aheader->chunk()->releaseArena(aheader); - } -} - static void AssertValidColor(const TenuredCell *thing, uint32_t color) { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 5864700694e..49d40c03900 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -545,6 +545,9 @@ Arena::finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize) return nmarked; } +// Finalize arenas from src list, releasing empty arenas if keepArenas wasn't +// specified and inserting the others into the appropriate destination size +// bins. template static inline bool FinalizeTypedArenas(FreeOp *fop, @@ -554,11 +557,10 @@ FinalizeTypedArenas(FreeOp *fop, SliceBudget &budget, ArenaLists::KeepArenasEnum keepArenas) { - /* - * Finalize arenas from src list, releasing empty arenas if keepArenas - * wasn't specified and inserting the others into the appropriate - * destination size bins. - */ + // When operating in the foreground, take the lock at the top. + Maybe maybeLock; + if (!fop->runtime()->gc.isBackgroundSweeping()) + maybeLock.emplace(fop->runtime()); /* * During parallel sections, we sometimes finalize the parallel arenas, @@ -575,12 +577,18 @@ FinalizeTypedArenas(FreeOp *fop, size_t nmarked = aheader->getArena()->finalize(fop, thingKind, thingSize); size_t nfree = thingsPerArena - nmarked; - if (nmarked) + if (nmarked) { dest.insertAt(aheader, nfree); - else if (keepArenas) + } else if (keepArenas) { aheader->chunk()->recycleArena(aheader, dest, thingKind, thingsPerArena); - else - aheader->chunk()->releaseArena(aheader); + } else if (fop->runtime()->gc.isBackgroundSweeping()) { + // When background sweeping, take the lock around each release so + // that we do not block the foreground for extended periods. + AutoLockGC lock(fop->runtime()); + fop->runtime()->gc.releaseArena(aheader, lock); + } else { + fop->runtime()->gc.releaseArena(aheader, maybeLock.ref()); + } budget.step(thingsPerArena); if (budget.isOverBudget()) @@ -938,67 +946,14 @@ Chunk::fetchNextFreeArena(JSRuntime *rt) } ArenaHeader * -Chunk::allocateArena(Zone *zone, AllocKind thingKind) +Chunk::allocateArena(JSRuntime *rt, Zone *zone, AllocKind thingKind, const AutoLockGC &lock) { - MOZ_ASSERT(hasAvailableArenas()); - - JSRuntime *rt = zone->runtimeFromAnyThread(); - if (!rt->isHeapMinorCollecting() && - !rt->isHeapCompacting() && - rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) - { -#ifdef JSGC_FJGENERATIONAL - // This is an approximation to the best test, which would check that - // this thread is currently promoting into the tenured area. I doubt - // the better test would make much difference. - if (!rt->isFJMinorCollecting()) - return nullptr; -#else - return nullptr; -#endif - } - - ArenaHeader *aheader = MOZ_LIKELY(info.numArenasFreeCommitted > 0) + ArenaHeader *aheader = info.numArenasFreeCommitted > 0 ? fetchNextFreeArena(rt) : fetchNextDecommittedArena(); aheader->init(zone, thingKind); if (MOZ_UNLIKELY(!hasAvailableArenas())) removeFromAvailableList(); - - zone->usage.addGCArena(); - - if (!rt->isHeapCompacting()) { - size_t usedBytes = zone->usage.gcBytes(); - size_t thresholdBytes = zone->threshold.gcTriggerBytes(); - size_t igcThresholdBytes = thresholdBytes * rt->gc.tunables.zoneAllocThresholdFactor(); - - if (usedBytes >= thresholdBytes) { - // The threshold has been surpassed, immediately trigger a GC, - // which will be done non-incrementally. - AutoUnlockGC unlock(rt); - rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); - } else if (usedBytes >= igcThresholdBytes) { - // Reduce the delay to the start of the next incremental slice. - if (zone->gcDelayBytes < ArenaSize) - zone->gcDelayBytes = 0; - else - zone->gcDelayBytes -= ArenaSize; - - if (!zone->gcDelayBytes) { - // Start or continue an in progress incremental GC. We do this - // to try to avoid performing non-incremental GCs on zones - // which allocate a lot of data, even when incremental slices - // can't be triggered via scheduling in the event loop. - AutoUnlockGC unlock(rt); - rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); - - // Delay the next slice until a certain amount of allocation - // has been performed. - zone->gcDelayBytes = rt->gc.tunables.zoneAllocDelayBytes(); - } - } - } - return aheader; } @@ -1028,20 +983,10 @@ Chunk::recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thing } void -Chunk::releaseArena(ArenaHeader *aheader) +Chunk::releaseArena(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) { MOZ_ASSERT(aheader->allocated()); MOZ_ASSERT(!aheader->hasDelayedMarking); - Zone *zone = aheader->zone; - JSRuntime *rt = zone->runtimeFromAnyThread(); - - Maybe maybeLock; - if (rt->gc.isBackgroundSweeping()) - maybeLock.emplace(rt); - - if (rt->gc.isBackgroundSweeping()) - zone->threshold.updateForRemovedArena(rt->gc.tunables); - zone->usage.removeGCArena(); aheader->setAsNotAllocated(); addArenaToFreeList(rt, aheader); @@ -1053,12 +998,10 @@ Chunk::releaseArena(ArenaHeader *aheader) } else if (!unused()) { MOZ_ASSERT(info.prevp); } else { - if (maybeLock.isNothing()) - maybeLock.emplace(rt); MOZ_ASSERT(unused()); removeFromAvailableList(); decommitAllArenas(rt); - rt->gc.moveChunkToFreePool(this, maybeLock.ref()); + rt->gc.moveChunkToFreePool(this, lock); } } @@ -1161,6 +1104,46 @@ GCRuntime::pickChunk(const AutoLockGC &lock, return chunk; } +ArenaHeader * +GCRuntime::allocateArena(Chunk *chunk, Zone *zone, AllocKind thingKind, const AutoLockGC &lock) +{ + MOZ_ASSERT(chunk->hasAvailableArenas()); + + // Fail the allocation if we are over our heap size limits. + if (!isHeapMinorCollecting() && + !isHeapCompacting() && + usage.gcBytes() >= tunables.gcMaxBytes()) + { +#ifdef JSGC_FJGENERATIONAL + // This is an approximation to the best test, which would check that + // this thread is currently promoting into the tenured area. I doubt + // the better test would make much difference. + if (!isFJMinorCollecting()) + return nullptr; +#else + return nullptr; +#endif + } + + ArenaHeader *aheader = chunk->allocateArena(rt, zone, thingKind, lock); + zone->usage.addGCArena(); + + // Trigger an incremental slice if needed. + if (!isHeapMinorCollecting() && !isHeapCompacting()) + maybeAllocTriggerZoneGC(zone, lock); + + return aheader; +} + +void +GCRuntime::releaseArena(ArenaHeader *aheader, const AutoLockGC &lock) +{ + aheader->zone->usage.removeGCArena(); + if (isBackgroundSweeping()) + aheader->zone->threshold.updateForRemovedArena(tunables); + return aheader->chunk()->releaseArena(rt, aheader, lock); +} + GCRuntime::GCRuntime(JSRuntime *rt) : rt(rt), systemZone(nullptr), @@ -1906,7 +1889,8 @@ ZoneHeapThreshold::updateForRemovedArena(const GCSchedulingTunables &tunables) } Allocator::Allocator(Zone *zone) - : zone_(zone) + : arenas(zone->runtimeFromMainThread()), + zone_(zone) {} inline void @@ -1992,7 +1976,7 @@ ArenaLists::allocateFromArena(JS::Zone *zone, AllocKind thingKind, // Although our chunk should definitely have enough space for another arena, // there are other valid reasons why Chunk::allocateArena() may fail. - aheader = chunk->allocateArena(zone, thingKind); + aheader = rt->gc.allocateArena(chunk, zone, thingKind, maybeLock.ref()); if (!aheader) return nullptr; @@ -2553,6 +2537,7 @@ void GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) { // Release the relocated arenas, now containing only forwarding pointers + AutoLockGC lock(rt); unsigned count = 0; while (relocatedList) { @@ -2575,16 +2560,44 @@ GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) JS_MOVED_TENURED_PATTERN, Arena::thingsSpan(thingSize)); #endif - aheader->chunk()->releaseArena(aheader); + releaseArena(aheader, lock); ++count; } - AutoLockGC lock(rt); expireChunksAndArenas(true, lock); } #endif // JSGC_COMPACTING +void +ReleaseArenaList(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock) +{ + ArenaHeader *next; + for (; aheader; aheader = next) { + next = aheader->next; + rt->gc.releaseArena(aheader, lock); + } +} + +ArenaLists::~ArenaLists() +{ + AutoLockGC lock(runtime_); + + for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { + /* + * We can only call this during the shutdown after the last GC when + * the background finalization is disabled. + */ + MOZ_ASSERT(backgroundFinalizeState[i] == BFS_DONE); + ReleaseArenaList(runtime_, arenaLists[i].head(), lock); + } + ReleaseArenaList(runtime_, incrementalSweptArenas.head(), lock); + + for (size_t i = 0; i < FINALIZE_OBJECT_LIMIT; i++) + ReleaseArenaList(runtime_, savedObjectArenas[i].head(), lock); + ReleaseArenaList(runtime_, savedEmptyObjectArenas, lock); +} + void ArenaLists::finalizeNow(FreeOp *fop, const FinalizePhase& phase) { @@ -2751,7 +2764,8 @@ ArenaLists::queueForegroundObjectsForSweep(FreeOp *fop) void ArenaLists::mergeForegroundSweptObjectArenas() { - ReleaseArenaList(savedEmptyObjectArenas); + AutoLockGC lock(runtime_); + ReleaseArenaList(runtime_, savedEmptyObjectArenas, lock); savedEmptyObjectArenas = nullptr; mergeSweptArenas(FINALIZE_OBJECT0); @@ -3023,6 +3037,40 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason) return true; } +void +GCRuntime::maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock) +{ + size_t usedBytes = zone->usage.gcBytes(); + size_t thresholdBytes = zone->threshold.gcTriggerBytes(); + size_t igcThresholdBytes = thresholdBytes * tunables.zoneAllocThresholdFactor(); + + if (usedBytes >= thresholdBytes) { + // The threshold has been surpassed, immediately trigger a GC, + // which will be done non-incrementally. + AutoUnlockGC unlock(rt); + triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + } else if (usedBytes >= igcThresholdBytes) { + // Reduce the delay to the start of the next incremental slice. + if (zone->gcDelayBytes < ArenaSize) + zone->gcDelayBytes = 0; + else + zone->gcDelayBytes -= ArenaSize; + + if (!zone->gcDelayBytes) { + // Start or continue an in progress incremental GC. We do this + // to try to avoid performing non-incremental GCs on zones + // which allocate a lot of data, even when incremental slices + // can't be triggered via scheduling in the event loop. + AutoUnlockGC unlock(rt); + triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + + // Delay the next slice until a certain amount of allocation + // has been performed. + zone->gcDelayBytes = tunables.zoneAllocDelayBytes(); + } + } +} + bool GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) { @@ -3123,8 +3171,9 @@ GCRuntime::maybePeriodicFullGC() } void -GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) +GCRuntime::decommitArenas(const AutoLockGC &lock) { + Chunk **availableListHeadp = &availableChunkListHead; Chunk *chunk = *availableListHeadp; if (!chunk) return; @@ -3231,12 +3280,6 @@ GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp) } } -void -GCRuntime::decommitArenas() -{ - decommitArenasFromAvailableList(&availableChunkListHead); -} - void GCRuntime::expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock) { @@ -3250,7 +3293,7 @@ GCRuntime::expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock) } if (shouldShrink) - decommitArenas(); + decommitArenas(lock); } void @@ -6620,7 +6663,7 @@ ArenaLists::adoptArenas(JSRuntime *rt, ArenaLists *fromArenaLists) // Therefore, if fromHeader is empty, send it back to the // chunk now. Otherwise, attach to |toList|. if (fromHeader->isEmpty()) - fromHeader->chunk()->releaseArena(fromHeader); + rt->gc.releaseArena(fromHeader, lock); else toList->insertAtCursor(fromHeader); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index f273f35c4c2..ec51d5709e9 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -595,6 +595,8 @@ class SortedArenaList class ArenaLists { + JSRuntime *runtime_; + /* * For each arena kind its free list is represented as the first span with * free things. Initially all the spans are initialized as empty. After we @@ -639,7 +641,7 @@ class ArenaLists ArenaHeader *savedEmptyObjectArenas; public: - ArenaLists() { + ArenaLists(JSRuntime *rt) : runtime_(rt) { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) freeLists[i].initAsEmpty(); for (size_t i = 0; i != FINALIZE_LIMIT; ++i) @@ -654,21 +656,7 @@ class ArenaLists savedEmptyObjectArenas = nullptr; } - ~ArenaLists() { - for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { - /* - * We can only call this during the shutdown after the last GC when - * the background finalization is disabled. - */ - MOZ_ASSERT(backgroundFinalizeState[i] == BFS_DONE); - ReleaseArenaList(arenaLists[i].head()); - } - ReleaseArenaList(incrementalSweptArenas.head()); - - for (size_t i = 0; i < FINALIZE_OBJECT_LIMIT; i++) - ReleaseArenaList(savedObjectArenas[i].head()); - ReleaseArenaList(savedEmptyObjectArenas); - } + ~ArenaLists(); static uintptr_t getFreeListOffset(AllocKind thingKind) { uintptr_t offset = offsetof(ArenaLists, freeLists); From 03538a225ee0bcf00567cfea36a727af85fde49e Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Tue, 11 Nov 2014 14:17:09 +1300 Subject: [PATCH 31/71] Bug 1091704 - Delay buffer frame calculation in WMF audio decoder until after UpdateOutputType to avoid using obsolete rate/channel values. r=cpearce --- dom/media/fmp4/wmf/WMFAudioMFTManager.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp b/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp index 157d73e0df8..51be5cc3b19 100644 --- a/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp +++ b/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp @@ -221,9 +221,6 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset, hr = buffer->Lock(&data, &maxLength, ¤tLength); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - int32_t numSamples = currentLength / mAudioBytesPerSample; - int32_t numFrames = numSamples / mAudioChannels; - // Sometimes when starting decoding, the AAC decoder gives us samples // with a negative timestamp. AAC does usually have preroll (or encoder // delay) encoded into its bitstream, but the amount encoded to the stream @@ -245,6 +242,13 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset, int32_t numFramesToStrip = 0; sample->GetUINT32(MFSampleExtension_Discontinuity, &discontinuity); if (mMustRecaptureAudioPosition || discontinuity) { + // Update the output type, in case this segment has a different + // rate. This also triggers on the first sample, which can have a + // different rate than is advertised in the container, and sometimes we + // don't get a MF_E_TRANSFORM_STREAM_CHANGE when the rate changes. + hr = UpdateOutputType(); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + mAudioFrameSum = 0; LONGLONG timestampHns = 0; hr = sample->GetSampleTime(×tampHns); @@ -258,15 +262,10 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset, mAudioFrameOffset = 0; } mMustRecaptureAudioPosition = false; - - // Also update the output type, in case this segment has a different - // rate. This also triggers on the first sample, which can have a - // different rate than is advertised in the container, and sometimes - // we don't get a MF_E_TRANSFORM_STREAM_CHANGE when the rate changes. - hr = UpdateOutputType(); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); } MOZ_ASSERT(numFramesToStrip >= 0); + int32_t numSamples = currentLength / mAudioBytesPerSample; + int32_t numFrames = numSamples / mAudioChannels; int32_t offset = std::min(numFramesToStrip, numFrames); numFrames -= offset; numSamples -= offset * mAudioChannels; From 0e506710a9c5c56dd9c02d8f615572d6ac4ba74b Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 11 Nov 2014 15:00:02 +1300 Subject: [PATCH 32/71] Bug 1096125 - Backout c129289d32d6 as Adobe/EME doesn't actually need those DLLs for OPM handshake. r=backout. --- dom/media/gmp/GMPChild.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp index 08ab3c0320c..560ab8c2dae 100644 --- a/dom/media/gmp/GMPChild.cpp +++ b/dom/media/gmp/GMPChild.cpp @@ -341,8 +341,6 @@ GMPChild::PreLoadLibraries(const std::string& aPluginPath) // This must be in sorted order and lowercase! static const char* whitelist[] = { - "bcrypt.dll", // Used for OutputProtectionManager handshake - "crypt32.dll", // Used for OutputProtectionManager handshake "d3d9.dll", // Create an `IDirect3D9` to get adapter information "dxva2.dll", // Get monitor information "msauddecmft.dll", // AAC decoder (on Windows 8) From 50be117679bdfae502844809c05fce775844ffe9 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Tue, 11 Nov 2014 11:01:28 +0900 Subject: [PATCH 33/71] Bug 1095315 - Fix the order of applying pending updates and getting the effective transform in BasicLayerManager; r=mattwoodrow --- gfx/layers/basic/BasicLayerManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index e3bd29c6d1b..992184dc8b0 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -485,6 +485,12 @@ BasicLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback, mTransactionIncomplete = false; if (mRoot) { + if (aFlags & END_NO_COMPOSITE) { + // Apply pending tree updates before recomputing effective + // properties. + mRoot->ApplyPendingUpdatesToSubtree(); + } + // Need to do this before we call ApplyDoubleBuffering, // which depends on correct effective transforms if (mTarget) { @@ -499,12 +505,6 @@ BasicLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback, if (mRoot->GetMaskLayer()) { ToData(mRoot->GetMaskLayer())->Validate(aCallback, aCallbackData, nullptr); } - - if (aFlags & END_NO_COMPOSITE) { - // Apply pending tree updates before recomputing effective - // properties. - mRoot->ApplyPendingUpdatesToSubtree(); - } } if (mTarget && mRoot && From 5e52aa2468182fb3e14c24871f1613710f9cead6 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Tue, 11 Nov 2014 14:53:55 +1100 Subject: [PATCH 34/71] Bug 1092570 - Avoid exposing FontFace(Set) constructors when the Font Loading API pref is not set. r=bzbarsky --- layout/style/FontFace.cpp | 5 ++++- layout/style/FontFaceSet.cpp | 21 +++++++++++++++++++-- layout/style/FontFaceSet.h | 5 +++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/layout/style/FontFace.cpp b/layout/style/FontFace.cpp index a3cb2e7b70f..23ccbf1ec8b 100644 --- a/layout/style/FontFace.cpp +++ b/layout/style/FontFace.cpp @@ -226,7 +226,10 @@ FontFace::FontFace(nsISupports* aParent, nsPresContext* aPresContext) nsCOMPtr global = do_QueryInterface(aParent); - if (global) { + // If the pref is not set, don't create the Promise (which the page wouldn't + // be able to get to anyway) as it causes the window.FontFace constructor + // to be created. + if (global && FontFaceSet::PrefEnabled()) { ErrorResult rv; mLoaded = Promise::Create(global, rv); } diff --git a/layout/style/FontFaceSet.cpp b/layout/style/FontFaceSet.cpp index 6cfd7e97fd4..98b1b94f257 100644 --- a/layout/style/FontFaceSet.cpp +++ b/layout/style/FontFaceSet.cpp @@ -39,6 +39,8 @@ using namespace mozilla::dom; #define LOG_ENABLED() PR_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), \ PR_LOG_DEBUG) +#define FONT_LOADING_API_ENABLED_PREF "layout.css.font-loading-api.enabled" + NS_IMPL_CYCLE_COLLECTION_CLASS(FontFaceSet) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FontFaceSet, DOMEventTargetHelper) @@ -83,7 +85,10 @@ FontFaceSet::FontFaceSet(nsPIDOMWindow* aWindow, nsPresContext* aPresContext) nsCOMPtr global = do_QueryInterface(aWindow); - if (global) { + // If the pref is not set, don't create the Promise (which the page wouldn't + // be able to get to anyway) as it causes the window.FontFaceSet constructor + // to be created. + if (global && PrefEnabled()) { ErrorResult rv; mReady = Promise::Create(global, rv); } @@ -1337,7 +1342,7 @@ FontFaceSet::CheckLoadingStarted() false))->RunDOMEventWhenSafe(); } - if (mReadyIsResolved) { + if (mReadyIsResolved && PrefEnabled()) { nsRefPtr ready; if (GetParentObject()) { ErrorResult rv; @@ -1496,6 +1501,18 @@ FontFaceSet::HandleEvent(nsIDOMEvent* aEvent) return NS_OK; } +/* static */ bool +FontFaceSet::PrefEnabled() +{ + static bool initialized = false; + static bool enabled; + if (!initialized) { + initialized = true; + Preferences::AddBoolVarCache(&enabled, FONT_LOADING_API_ENABLED_PREF); + } + return enabled; +} + // nsICSSLoaderObserver NS_IMETHODIMP diff --git a/layout/style/FontFaceSet.h b/layout/style/FontFaceSet.h index 3ec9e4f0bd1..4b0bd9717ab 100644 --- a/layout/style/FontFaceSet.h +++ b/layout/style/FontFaceSet.h @@ -157,6 +157,11 @@ public: */ void DidRefresh(); + /** + * Returns whether the "layout.css.font-loading-api.enabled" pref is true. + */ + static bool PrefEnabled(); + // nsICSSLoaderObserver NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet, bool aWasAlternate, From 52334af11728cba4714d6b5438b041f903fa427e Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 30 Oct 2014 17:35:35 -0500 Subject: [PATCH 35/71] Bug 1091916 - simplify the interrupt/jitStackLimit situation (r=bhackett) --- js/src/asmjs/AsmJSModule.cpp | 6 +- .../irregexp/NativeRegExpMacroAssembler.cpp | 4 +- js/src/jit/BaselineCompiler.cpp | 4 +- js/src/jit/CodeGenerator.cpp | 8 +- js/src/jit/CompileWrappers.cpp | 10 +- js/src/jit/CompileWrappers.h | 4 +- js/src/jit/Ion.cpp | 4 +- js/src/jit/IonMacroAssembler.cpp | 2 +- js/src/jit/ParallelFunctions.cpp | 2 +- js/src/jit/VMFunctions.cpp | 29 +--- js/src/jit/shared/Assembler-shared.h | 2 +- js/src/jsapi.cpp | 54 +++---- js/src/jsapi.h | 3 + js/src/jscntxt.cpp | 85 ----------- js/src/jscntxt.h | 32 +--- js/src/jsgcinlines.h | 2 +- js/src/jsnativestack.h | 1 + js/src/vm/ForkJoin.cpp | 17 +-- js/src/vm/ForkJoin.h | 2 - js/src/vm/RegExpObject.cpp | 10 +- js/src/vm/Runtime.cpp | 143 +++++++++++++----- js/src/vm/Runtime.h | 105 ++++++++----- 22 files changed, 239 insertions(+), 290 deletions(-) diff --git a/js/src/asmjs/AsmJSModule.cpp b/js/src/asmjs/AsmJSModule.cpp index bdceba091af..ae86f8fb05c 100644 --- a/js/src/asmjs/AsmJSModule.cpp +++ b/js/src/asmjs/AsmJSModule.cpp @@ -500,7 +500,7 @@ AsmJSHandleExecutionInterrupt() { AsmJSActivation *act = PerThreadData::innermostAsmJSActivation(); act->module().setInterrupted(true); - bool ret = HandleExecutionInterrupt(act->cx()); + bool ret = CheckForInterrupt(act->cx()); act->module().setInterrupted(false); return ret; } @@ -673,8 +673,8 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx) switch (kind) { case AsmJSImm_Runtime: return cx->runtimeAddressForJit(); - case AsmJSImm_RuntimeInterrupt: - return cx->runtimeAddressOfInterrupt(); + case AsmJSImm_RuntimeInterruptUint32: + return cx->runtimeAddressOfInterruptUint32(); case AsmJSImm_StackLimit: return cx->stackLimitAddressForJitCode(StackForUntrustedScript); case AsmJSImm_ReportOverRecursed: diff --git a/js/src/irregexp/NativeRegExpMacroAssembler.cpp b/js/src/irregexp/NativeRegExpMacroAssembler.cpp index 8cce4ee744b..ea6a71ab333 100644 --- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp +++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp @@ -152,7 +152,7 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext *cx, bool match_only) // Check if we have space on the stack. Label stack_ok; - void *stack_limit = &runtime->mainThread.jitStackLimit; + void *stack_limit = runtime->mainThread.addressOfJitStackLimit(); masm.branchPtr(Assembler::Below, AbsoluteAddress(stack_limit), StackPointer, &stack_ok); // Exit with an exception. There is not enough space on the stack @@ -502,7 +502,7 @@ NativeRegExpMacroAssembler::Backtrack() // Check for an interrupt. Label noInterrupt; masm.branch32(Assembler::Equal, - AbsoluteAddress(&runtime->interrupt), Imm32(0), + AbsoluteAddress(runtime->addressOfInterruptUint32()), Imm32(0), &noInterrupt); masm.movePtr(ImmWord(RegExpRunStatus_Error), temp0); masm.jump(&exit_label_); diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 9986acbcd30..8491db46ea1 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -496,7 +496,7 @@ bool BaselineCompiler::emitStackCheck(bool earlyCheck) { Label skipCall; - uintptr_t *limitAddr = &cx->runtime()->mainThread.jitStackLimit; + void *limitAddr = cx->runtime()->mainThread.addressOfJitStackLimit(); uint32_t slotsSize = script->nslots() * sizeof(Value); uint32_t tolerance = earlyCheck ? slotsSize : 0; @@ -646,7 +646,7 @@ BaselineCompiler::emitInterruptCheck() frame.syncStack(0); Label done; - void *interrupt = (void *)&cx->runtime()->interrupt; + void *interrupt = cx->runtimeAddressOfInterruptUint32(); masm.branch32(Assembler::Equal, AbsoluteAddress(interrupt), Imm32(0), &done); prepareVMCall(); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index b9b45e213d0..be05db38ac5 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -3772,7 +3772,7 @@ CodeGenerator::visitCheckOverRecursedPar(LCheckOverRecursedPar *lir) Register tempReg = ToRegister(lir->getTempReg()); masm.loadPtr(Address(cxReg, offsetof(ForkJoinContext, perThreadData)), tempReg); - masm.loadPtr(Address(tempReg, offsetof(PerThreadData, jitStackLimit)), tempReg); + masm.loadPtr(Address(tempReg, PerThreadData::offsetOfJitStackLimit()), tempReg); // Conditional forward (unlikely) branch to failure. CheckOverRecursedFailure *ool = new(alloc()) CheckOverRecursedFailure(lir); @@ -9950,7 +9950,7 @@ CodeGenerator::visitInterruptCheck(LInterruptCheck *lir) if (!ool) return false; - AbsoluteAddress interruptAddr(GetIonContext()->runtime->addressOfInterrupt()); + AbsoluteAddress interruptAddr(GetIonContext()->runtime->addressOfInterruptUint32()); masm.branch32(Assembler::NotEqual, interruptAddr, Imm32(0), ool->entry()); masm.bind(ool->rejoin()); return true; @@ -9960,8 +9960,8 @@ bool CodeGenerator::visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir) { Register scratch = ToRegister(lir->scratch()); - masm.movePtr(AsmJSImmPtr(AsmJSImm_RuntimeInterrupt), scratch); - masm.load8ZeroExtend(Address(scratch, 0), scratch); + masm.movePtr(AsmJSImmPtr(AsmJSImm_RuntimeInterruptUint32), scratch); + masm.load32(Address(scratch, 0), scratch); Label rejoin; masm.branch32(Assembler::Equal, scratch, Imm32(0), &rejoin); { diff --git a/js/src/jit/CompileWrappers.cpp b/js/src/jit/CompileWrappers.cpp index 0030b92b26d..210eaf97c56 100644 --- a/js/src/jit/CompileWrappers.cpp +++ b/js/src/jit/CompileWrappers.cpp @@ -43,7 +43,7 @@ CompileRuntime::addressOfJitTop() const void * CompileRuntime::addressOfJitStackLimit() { - return &runtime()->mainThread.jitStackLimit; + return runtime()->mainThread.addressOfJitStackLimit(); } const void * @@ -73,15 +73,15 @@ CompileRuntime::addressOfGCZeal() #endif const void * -CompileRuntime::addressOfInterrupt() +CompileRuntime::addressOfInterruptUint32() { - return &runtime()->interrupt; + return runtime()->addressOfInterruptUint32(); } const void * -CompileRuntime::addressOfInterruptPar() +CompileRuntime::addressOfInterruptParUint32() { - return &runtime()->interruptPar; + return runtime()->addressOfInterruptParUint32(); } const void * diff --git a/js/src/jit/CompileWrappers.h b/js/src/jit/CompileWrappers.h index fe896315d0e..879bca9e8f4 100644 --- a/js/src/jit/CompileWrappers.h +++ b/js/src/jit/CompileWrappers.h @@ -50,8 +50,8 @@ class CompileRuntime const void *addressOfGCZeal(); #endif - const void *addressOfInterrupt(); - const void *addressOfInterruptPar(); + const void *addressOfInterruptUint32(); + const void *addressOfInterruptParUint32(); const void *addressOfThreadPool(); diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index e4cfb888f7f..7dfeb7e5240 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -428,7 +428,7 @@ JitRuntime::ensureIonCodeAccessible(JSRuntime *rt) ionCodeProtected_ = false; } - if (rt->interrupt) { + if (rt->hasPendingInterrupt()) { // The interrupt handler needs to be invoked by this thread, but we may // be inside a signal handler and have no idea what is above us on the // stack (probably we are executing Ion code at an arbitrary point, but @@ -1162,7 +1162,7 @@ IonScript::copyPatchableBackedges(JSContext *cx, JitCode *code, // whether an interrupt is currently desired, matching the targets // established by ensureIonCodeAccessible() above. We don't handle the // interrupt immediately as the interrupt lock is held here. - if (cx->runtime()->interrupt) + if (cx->runtime()->hasPendingInterrupt()) PatchBackedge(backedge, interruptCheck, JitRuntime::BackedgeInterruptCheck); else PatchBackedge(backedge, loopHeader, JitRuntime::BackedgeLoopHeader); diff --git a/js/src/jit/IonMacroAssembler.cpp b/js/src/jit/IonMacroAssembler.cpp index 11b8701b38f..086f2807180 100644 --- a/js/src/jit/IonMacroAssembler.cpp +++ b/js/src/jit/IonMacroAssembler.cpp @@ -1238,7 +1238,7 @@ MacroAssembler::loadStringChar(Register str, Register index, Register output) void MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail) { - movePtr(ImmPtr(GetIonContext()->runtime->addressOfInterruptPar()), tempReg); + movePtr(ImmPtr(GetIonContext()->runtime->addressOfInterruptParUint32()), tempReg); branch32(Assembler::NonZero, Address(tempReg, 0), Imm32(0), fail); } diff --git a/js/src/jit/ParallelFunctions.cpp b/js/src/jit/ParallelFunctions.cpp index 2080bb959ad..58df34db82c 100644 --- a/js/src/jit/ParallelFunctions.cpp +++ b/js/src/jit/ParallelFunctions.cpp @@ -147,7 +147,7 @@ jit::CheckOverRecursedPar(ForkJoinContext *cx) } #endif - if (!JS_CHECK_STACK_SIZE(cx->perThreadData->jitStackLimit, &stackDummy_)) { + if (!JS_CHECK_STACK_SIZE(cx->perThreadData->jitStackLimit(), &stackDummy_)) { cx->bailoutRecord->joinCause(ParallelBailoutOverRecursed); return false; } diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index c0a7523cf1e..164c7542d08 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -113,28 +113,17 @@ NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap) bool CheckOverRecursed(JSContext *cx) { - // IonMonkey's stackLimit is equal to nativeStackLimit by default. When we - // request an interrupt, we set the jitStackLimit to nullptr, which causes - // the stack limit check to fail. - // - // There are two states we're concerned about here: - // (1) The interrupt bit is set, and we need to fire the interrupt callback. - // (2) The stack limit has been exceeded, and we need to throw an error. - // - // Note that we can reach here if jitStackLimit is MAXADDR, but interrupt - // has not yet been set to 1. That's okay; it will be set to 1 very shortly, - // and in the interim we might just fire a few useless calls to - // CheckOverRecursed. + // We just failed the jitStackLimit check. There are two possible reasons: + // - jitStackLimit was the real stack limit and we're over-recursed + // - jitStackLimit was set to UINTPTR_MAX by JSRuntime::requestInterrupt + // and we need to call JSRuntime::handleInterrupt. #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR) JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, 0, return false); #else JS_CHECK_RECURSION(cx, return false); #endif - - if (cx->runtime()->interrupt) - return InterruptCheck(cx); - - return true; + gc::MaybeVerifyBarriers(cx); + return cx->runtime()->handleInterrupt(cx); } // This function can get called in two contexts. In the usual context, it's @@ -178,10 +167,8 @@ CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame, JS_CHECK_RECURSION_WITH_SP(cx, checkSp, return false); #endif - if (cx->runtime()->interrupt) - return InterruptCheck(cx); - - return true; + gc::MaybeVerifyBarriers(cx); + return cx->runtime()->handleInterrupt(cx); } bool diff --git a/js/src/jit/shared/Assembler-shared.h b/js/src/jit/shared/Assembler-shared.h index 2144df9b0be..9b54186df22 100644 --- a/js/src/jit/shared/Assembler-shared.h +++ b/js/src/jit/shared/Assembler-shared.h @@ -783,7 +783,7 @@ enum AsmJSImmKind AsmJSImm_PowD = AsmJSExit::Builtin_PowD, AsmJSImm_ATan2D = AsmJSExit::Builtin_ATan2D, AsmJSImm_Runtime, - AsmJSImm_RuntimeInterrupt, + AsmJSImm_RuntimeInterruptUint32, AsmJSImm_StackLimit, AsmJSImm_ReportOverRecursed, AsmJSImm_OnDetached, diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 0bec32dca66..a913b3d7958 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2031,68 +2031,48 @@ JS_GetExternalStringFinalizer(JSString *str) } static void -SetNativeStackQuota(JSRuntime *rt, StackKind kind, size_t stackSize) +SetNativeStackQuotaAndLimit(JSRuntime *rt, StackKind kind, size_t stackSize) { rt->nativeStackQuota[kind] = stackSize; - if (rt->nativeStackBase) - RecomputeStackLimit(rt, kind); -} -void -js::RecomputeStackLimit(JSRuntime *rt, StackKind kind) -{ - size_t stackSize = rt->nativeStackQuota[kind]; #if JS_STACK_GROWTH_DIRECTION > 0 if (stackSize == 0) { rt->mainThread.nativeStackLimit[kind] = UINTPTR_MAX; } else { MOZ_ASSERT(rt->nativeStackBase <= size_t(-1) - stackSize); - rt->mainThread.nativeStackLimit[kind] = - rt->nativeStackBase + stackSize - 1; + rt->mainThread.nativeStackLimit[kind] = rt->nativeStackBase + stackSize - 1; } #else if (stackSize == 0) { rt->mainThread.nativeStackLimit[kind] = 0; } else { MOZ_ASSERT(rt->nativeStackBase >= stackSize); - rt->mainThread.nativeStackLimit[kind] = - rt->nativeStackBase - (stackSize - 1); + rt->mainThread.nativeStackLimit[kind] = rt->nativeStackBase - (stackSize - 1); } #endif - - // If there's no pending interrupt request set on the runtime's main thread's - // jitStackLimit, then update it so that it reflects the new nativeStacklimit. - // - // Note that, for now, we use the untrusted limit for ion. This is fine, - // because it's the most conservative limit, and if we hit it, we'll bail - // out of ion into the interpeter, which will do a proper recursion check. - if (kind == StackForUntrustedScript) { - JSRuntime::AutoLockForInterrupt lock(rt); - if (rt->mainThread.jitStackLimit != uintptr_t(-1)) { - rt->mainThread.jitStackLimit = rt->mainThread.nativeStackLimit[kind]; -#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR) - rt->mainThread.jitStackLimit = jit::Simulator::StackLimit(); -#endif - } - } } JS_PUBLIC_API(void) -JS_SetNativeStackQuota(JSRuntime *rt, size_t systemCodeStackSize, - size_t trustedScriptStackSize, +JS_SetNativeStackQuota(JSRuntime *rt, size_t systemCodeStackSize, size_t trustedScriptStackSize, size_t untrustedScriptStackSize) { - MOZ_ASSERT_IF(trustedScriptStackSize, - trustedScriptStackSize < systemCodeStackSize); + MOZ_ASSERT(rt->requestDepth == 0); + if (!trustedScriptStackSize) trustedScriptStackSize = systemCodeStackSize; - MOZ_ASSERT_IF(untrustedScriptStackSize, - untrustedScriptStackSize < trustedScriptStackSize); + else + MOZ_ASSERT(trustedScriptStackSize < systemCodeStackSize); + if (!untrustedScriptStackSize) untrustedScriptStackSize = trustedScriptStackSize; - SetNativeStackQuota(rt, StackForSystemCode, systemCodeStackSize); - SetNativeStackQuota(rt, StackForTrustedScript, trustedScriptStackSize); - SetNativeStackQuota(rt, StackForUntrustedScript, untrustedScriptStackSize); + else + MOZ_ASSERT(untrustedScriptStackSize < trustedScriptStackSize); + + SetNativeStackQuotaAndLimit(rt, StackForSystemCode, systemCodeStackSize); + SetNativeStackQuotaAndLimit(rt, StackForTrustedScript, trustedScriptStackSize); + SetNativeStackQuotaAndLimit(rt, StackForUntrustedScript, untrustedScriptStackSize); + + rt->mainThread.initJitStackLimit(); } /************************************************************************/ diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 0b434a3ac58..3946eec97cd 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2272,6 +2272,9 @@ JS_GetExternalStringFinalizer(JSString *str); * The stack quotas for each kind of code should be monotonically descending, * and may be specified with this function. If 0 is passed for a given kind * of code, it defaults to the value of the next-highest-priority kind. + * + * This function may only be called immediately after the runtime is initialized + * and before any code is executed and/or interrupts requested. */ extern JS_PUBLIC_API(void) JS_SetNativeStackQuota(JSRuntime *cx, size_t systemCodeStackSize, diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index cb861567edf..412ae616d27 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -41,7 +41,6 @@ #include "gc/Marking.h" #include "jit/Ion.h" #include "js/CharacterEncoding.h" -#include "vm/Debugger.h" #include "vm/HelperThreads.h" #include "vm/Shape.h" @@ -971,90 +970,6 @@ js_GetErrorMessage(void *userRef, const unsigned errorNumber) return nullptr; } -bool -js::InvokeInterruptCallback(JSContext *cx) -{ - MOZ_ASSERT(cx->runtime()->requestDepth >= 1); - - JSRuntime *rt = cx->runtime(); - MOZ_ASSERT(rt->interrupt); - - // Reset the callback counter first, then run GC and yield. If another - // thread is racing us here we will accumulate another callback request - // which will be serviced at the next opportunity. - rt->interrupt = false; - - // IonMonkey sets its stack limit to UINTPTR_MAX to trigger interrupt - // callbacks. - rt->resetJitStackLimit(); - - cx->gcIfNeeded(); - - rt->interruptPar = false; - - // A worker thread may have requested an interrupt after finishing an Ion - // compilation. - jit::AttachFinishedCompilations(cx); - - // Important: Additional callbacks can occur inside the callback handler - // if it re-enters the JS engine. The embedding must ensure that the - // callback is disconnected before attempting such re-entry. - JSInterruptCallback cb = cx->runtime()->interruptCallback; - if (!cb) - return true; - - if (cb(cx)) { - // Debugger treats invoking the interrupt callback as a "step", so - // invoke the onStep handler. - if (cx->compartment()->debugMode()) { - ScriptFrameIter iter(cx); - if (iter.script()->stepModeEnabled()) { - RootedValue rval(cx); - switch (Debugger::onSingleStep(cx, &rval)) { - case JSTRAP_ERROR: - return false; - case JSTRAP_CONTINUE: - return true; - case JSTRAP_RETURN: - // See note in Debugger::propagateForcedReturn. - Debugger::propagateForcedReturn(cx, iter.abstractFramePtr(), rval); - return false; - case JSTRAP_THROW: - cx->setPendingException(rval); - return false; - default:; - } - } - } - - return true; - } - - // No need to set aside any pending exception here: ComputeStackString - // already does that. - JSString *stack = ComputeStackString(cx); - JSFlatString *flat = stack ? stack->ensureFlat(cx) : nullptr; - - const char16_t *chars; - AutoStableStringChars stableChars(cx); - if (flat && stableChars.initTwoByte(cx, flat)) - chars = stableChars.twoByteRange().start().get(); - else - chars = MOZ_UTF16("(stack not available)"); - JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, js_GetErrorMessage, nullptr, - JSMSG_TERMINATED, chars); - - return false; -} - -bool -js::HandleExecutionInterrupt(JSContext *cx) -{ - if (cx->runtime()->interrupt) - return InvokeInterruptCallback(cx); - return true; -} - ThreadSafeContext::ThreadSafeContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind) : ContextFriendFields(rt), contextKind_(kind), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 3fa252c061a..4c81f3febbd 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -289,7 +289,7 @@ struct ThreadSafeContext : ContextFriendFields, PropertyName *emptyString() { return runtime_->emptyString; } FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); } void *runtimeAddressForJit() { return runtime_; } - void *runtimeAddressOfInterrupt() { return &runtime_->interrupt; } + void *runtimeAddressOfInterruptUint32() { return runtime_->addressOfInterruptUint32(); } void *stackLimitAddress(StackKind kind) { return &runtime_->mainThread.nativeStackLimit[kind]; } void *stackLimitAddressForJitCode(StackKind kind); size_t gcSystemPageSize() { return gc::SystemPageSize(); } @@ -782,33 +782,15 @@ extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit]; namespace js { -/* - * Invoke the interrupt callback and return false if the current execution - * is to be terminated. - */ -bool -InvokeInterruptCallback(JSContext *cx); - -bool -HandleExecutionInterrupt(JSContext *cx); - -/* - * Process any pending interrupt requests. Long-running inner loops in C++ must - * call this periodically to make sure they are interruptible --- that is, to - * make sure they do not prevent the slow script dialog from appearing. - * - * This can run a full GC or call the interrupt callback, which could do - * anything. In the browser, it displays the slow script dialog. - * - * If this returns true, the caller can continue; if false, the caller must - * break out of its loop. This happens if, for example, the user clicks "Stop - * script" on the slow script dialog; treat it as an uncatchable error. - */ MOZ_ALWAYS_INLINE bool CheckForInterrupt(JSContext *cx) { - MOZ_ASSERT(cx->runtime()->requestDepth >= 1); - return !cx->runtime()->interrupt || InvokeInterruptCallback(cx); + // Add an inline fast-path since we have to check for interrupts in some hot + // C++ loops of library builtins. + JSRuntime *rt = cx->runtime(); + if (rt->hasPendingInterrupt()) + return rt->handleInterrupt(cx); + return true; } /************************************************************************/ diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 1921c6b8b77..bf4ec955c7f 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -526,7 +526,7 @@ CheckAllocatorState(ThreadSafeContext *cx, AllocKind kind) rt->gc.runDebugGC(); #endif - if (rt->interrupt) { + if (rt->hasPendingInterrupt()) { // Invoking the interrupt callback can fail and we can't usefully // handle that here. Just check in case we need to collect instead. ncx->gcIfNeeded(); diff --git a/js/src/jsnativestack.h b/js/src/jsnativestack.h index 86abcd08ac5..bcfe0ad88d2 100644 --- a/js/src/jsnativestack.h +++ b/js/src/jsnativestack.h @@ -18,6 +18,7 @@ inline uintptr_t GetNativeStackBase() { uintptr_t stackBase = reinterpret_cast(GetNativeStackBaseImpl()); + MOZ_ASSERT(stackBase != 0); MOZ_ASSERT(stackBase % sizeof(void *) == 0); return stackBase; } diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp index dd828fd771a..7e147131171 100644 --- a/js/src/vm/ForkJoin.cpp +++ b/js/src/vm/ForkJoin.cpp @@ -1440,7 +1440,7 @@ ForkJoinShared::execute() // Sometimes a GC request occurs *just before* we enter into the // parallel section. Rather than enter into the parallel section // and then abort, we just check here and abort early. - if (cx_->runtime()->interruptPar) + if (cx_->runtime()->hasPendingInterruptPar()) return TP_RETRY_SEQUENTIALLY; AutoLockMonitor lock(*this); @@ -1518,7 +1518,7 @@ ForkJoinShared::executeFromWorker(ThreadPoolWorker *worker, uintptr_t stackLimit // Don't use setIonStackLimit() because that acquires the ionStackLimitLock, and the // lock has not been initialized in these cases. - thisThread.jitStackLimit = stackLimit; + thisThread.initJitStackLimitPar(stackLimit); executePortion(&thisThread, worker); TlsPerThreadData.set(nullptr); @@ -1551,7 +1551,7 @@ ForkJoinShared::executeFromMainThread(ThreadPoolWorker *worker) // // Thus, use GetNativeStackLimit instead of just propagating the // main thread's. - thisThread.jitStackLimit = GetNativeStackLimit(cx_); + thisThread.initJitStackLimitPar(GetNativeStackLimit(cx_)); executePortion(&thisThread, worker); TlsPerThreadData.set(oldData); @@ -1647,7 +1647,7 @@ ForkJoinShared::executePortion(PerThreadData *perThread, ThreadPoolWorker *worke void ForkJoinShared::setAbortFlagDueToInterrupt(ForkJoinContext &cx) { - MOZ_ASSERT(cx_->runtime()->interruptPar); + MOZ_ASSERT(cx_->runtime()->hasPendingInterruptPar()); // The GC Needed flag should not be set during parallel // execution. Instead, one of the requestGC() or // requestZoneGC() methods should be invoked. @@ -1826,7 +1826,7 @@ ForkJoinContext::hasAcquiredJSContext() const bool ForkJoinContext::check() { - if (runtime()->interruptPar) { + if (runtime()->hasPendingInterruptPar()) { shared_->setAbortFlagDueToInterrupt(*this); return false; } @@ -2273,13 +2273,6 @@ js::ParallelTestsShouldPass(JSContext *cx) cx->runtime()->gcZeal() == 0; } -void -js::RequestInterruptForForkJoin(JSRuntime *rt, JSRuntime::InterruptMode mode) -{ - if (mode != JSRuntime::RequestInterruptAnyThreadDontStopIon) - rt->interruptPar = true; -} - bool js::intrinsic_SetForkJoinTargetRegion(JSContext *cx, unsigned argc, Value *vp) { diff --git a/js/src/vm/ForkJoin.h b/js/src/vm/ForkJoin.h index 55af6f09f7a..8554d4f87f7 100644 --- a/js/src/vm/ForkJoin.h +++ b/js/src/vm/ForkJoin.h @@ -546,8 +546,6 @@ bool InExclusiveParallelSection(); bool ParallelTestsShouldPass(JSContext *cx); -void RequestInterruptForForkJoin(JSRuntime *rt, JSRuntime::InterruptMode mode); - bool intrinsic_SetForkJoinTargetRegion(JSContext *cx, unsigned argc, Value *vp); extern const JSJitInfo intrinsic_SetForkJoinTargetRegionInfo; diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index 6e2ac67120d..6429469b750 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -621,14 +621,8 @@ RegExpShared::execute(JSContext *cx, HandleLinearString input, size_t start, // in the bytecode interpreter, which can execute while tolerating // future interrupts. Otherwise, if we keep getting interrupted we // will never finish executing the regexp. - bool interrupted; - { - JSRuntime::AutoLockForInterrupt lock(cx->runtime()); - interrupted = cx->runtime()->interrupt; - } - - if (interrupted) { - if (!InvokeInterruptCallback(cx)) + if (cx->runtime()->hasPendingInterrupt()) { + if (!cx->runtime()->handleInterrupt(cx)) return RegExpRunStatus_Error; break; } diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 105f3eccace..44b5516380e 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -36,6 +36,7 @@ #include "jit/PcScriptCache.h" #include "js/MemoryMetrics.h" #include "js/SliceBudget.h" +#include "vm/Debugger.h" #include "jscntxtinlines.h" #include "jsgcinlines.h" @@ -73,7 +74,7 @@ PerThreadData::PerThreadData(JSRuntime *runtime) runtime_(runtime), jitTop(nullptr), jitJSContext(nullptr), - jitStackLimit(0), + jitStackLimit_(0xbad), #ifdef JS_TRACE_LOGGING traceLogger(nullptr), #endif @@ -135,8 +136,8 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime) ), mainThread(this), parentRuntime(parentRuntime), - interrupt(false), - interruptPar(false), + interrupt_(false), + interruptPar_(false), handlingSignal(false), interruptCallback(nullptr), interruptLock(nullptr), @@ -155,7 +156,7 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime) execAlloc_(nullptr), jitRuntime_(nullptr), selfHostingGlobal_(nullptr), - nativeStackBase(0), + nativeStackBase(GetNativeStackBase()), cxCallback(nullptr), destroyCompartmentCallback(nullptr), destroyZoneCallback(nullptr), @@ -321,8 +322,6 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes) return false; #endif - nativeStackBase = GetNativeStackBase(); - jitSupportsFloatingPoint = js::jit::JitSupportsFloatingPoint(); jitSupportsSimd = js::jit::JitSupportsSimd(); @@ -464,17 +463,6 @@ NewObjectCache::clearNurseryObjects(JSRuntime *rt) #endif } -void -JSRuntime::resetJitStackLimit() -{ - AutoLockForInterrupt lock(this); - mainThread.setJitStackLimit(mainThread.nativeStackLimit[js::StackForUntrustedScript]); - -#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR) - mainThread.setJitStackLimit(js::jit::Simulator::StackLimit()); -#endif -} - void JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes) { @@ -529,33 +517,120 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim #endif } +static bool +InvokeInterruptCallback(JSContext *cx) +{ + MOZ_ASSERT(cx->runtime()->requestDepth >= 1); + + cx->gcIfNeeded(); + + // A worker thread may have requested an interrupt after finishing an Ion + // compilation. + jit::AttachFinishedCompilations(cx); + + // Important: Additional callbacks can occur inside the callback handler + // if it re-enters the JS engine. The embedding must ensure that the + // callback is disconnected before attempting such re-entry. + JSInterruptCallback cb = cx->runtime()->interruptCallback; + if (!cb) + return true; + + if (cb(cx)) { + // Debugger treats invoking the interrupt callback as a "step", so + // invoke the onStep handler. + if (cx->compartment()->debugMode()) { + ScriptFrameIter iter(cx); + if (iter.script()->stepModeEnabled()) { + RootedValue rval(cx); + switch (Debugger::onSingleStep(cx, &rval)) { + case JSTRAP_ERROR: + return false; + case JSTRAP_CONTINUE: + return true; + case JSTRAP_RETURN: + // See note in Debugger::propagateForcedReturn. + Debugger::propagateForcedReturn(cx, iter.abstractFramePtr(), rval); + return false; + case JSTRAP_THROW: + cx->setPendingException(rval); + return false; + default:; + } + } + } + + return true; + } + + // No need to set aside any pending exception here: ComputeStackString + // already does that. + JSString *stack = ComputeStackString(cx); + JSFlatString *flat = stack ? stack->ensureFlat(cx) : nullptr; + + const char16_t *chars; + AutoStableStringChars stableChars(cx); + if (flat && stableChars.initTwoByte(cx, flat)) + chars = stableChars.twoByteRange().start().get(); + else + chars = MOZ_UTF16("(stack not available)"); + JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, js_GetErrorMessage, nullptr, + JSMSG_TERMINATED, chars); + + return false; +} + +void +PerThreadData::resetJitStackLimit() +{ + // Note that, for now, we use the untrusted limit for ion. This is fine, + // because it's the most conservative limit, and if we hit it, we'll bail + // out of ion into the interpeter, which will do a proper recursion check. +#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR) + jitStackLimit_ = jit::Simulator::StackLimit(); +#else + jitStackLimit_ = nativeStackLimit[StackForUntrustedScript]; +#endif +} + +void +PerThreadData::initJitStackLimit() +{ + resetJitStackLimit(); +} + +void +PerThreadData::initJitStackLimitPar(uintptr_t limit) +{ + jitStackLimit_ = limit; +} + void JSRuntime::requestInterrupt(InterruptMode mode) { - AutoLockForInterrupt lock(this); + interrupt_ = true; + interruptPar_ = true; + mainThread.jitStackLimit_ = UINTPTR_MAX; - /* - * Invalidate ionTop to trigger its over-recursion check. Note this must be - * set before interrupt, to avoid racing with js::InvokeInterruptCallback, - * into a weird state where interrupt is stuck at 0 but jitStackLimit is - * MAXADDR. - */ - mainThread.setJitStackLimit(-1); - - interrupt = true; - - RequestInterruptForForkJoin(this, mode); - - /* - * asm.js and normal Ion code optionally use memory protection and signal - * handlers to halt running code. - */ if (canUseSignalHandlers()) { + AutoLockForInterrupt lock(this); RequestInterruptForAsmJSCode(this, mode); jit::RequestInterruptForIonCode(this, mode); } } +bool +JSRuntime::handleInterrupt(JSContext *cx) +{ + MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); + if (interrupt_ || mainThread.jitStackLimit_ == UINTPTR_MAX) { + interrupt_ = false; + interruptPar_ = false; + mainThread.resetJitStackLimit(); + return InvokeInterruptCallback(cx); + } + return true; +} + jit::ExecutableAllocator * JSRuntime::createExecutableAllocator(JSContext *cx) { diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 7c883a686db..3735e3140fe 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -519,13 +519,20 @@ class PerThreadData : public PerThreadDataFriendFields */ JSContext *jitJSContext; - /* - * The stack limit checked by JIT code. This stack limit may be temporarily - * set to null to force JIT code to exit (e.g., for the operation callback). - */ - uintptr_t jitStackLimit; + /* See comment for JSRuntime::interrupt_. */ + private: + mozilla::Atomic jitStackLimit_; + void resetJitStackLimit(); + friend struct ::JSRuntime; + public: + void initJitStackLimit(); + void initJitStackLimitPar(uintptr_t limit); - inline void setJitStackLimit(uintptr_t limit); + uintptr_t jitStackLimit() const { return jitStackLimit_; } + + // For read-only JIT use: + void *addressOfJitStackLimit() { return &jitStackLimit_; } + static size_t offsetOfJitStackLimit() { return offsetof(PerThreadData, jitStackLimit_); } // Information about the heap allocated backtrack stack used by RegExp JIT code. irregexp::RegExpStack regexpStack; @@ -678,8 +685,6 @@ class PerThreadData : public PerThreadDataFriendFields class AutoLockForExclusiveAccess; -void RecomputeStackLimit(JSRuntime *rt, StackKind kind); - } // namespace js struct JSRuntime : public JS::shadow::Runtime, @@ -703,18 +708,56 @@ struct JSRuntime : public JS::shadow::Runtime, */ JSRuntime *parentRuntime; - /* - * If true, we've been asked to call the interrupt callback as soon as - * possible. - */ - mozilla::Atomic interrupt; + private: + mozilla::Atomic interrupt_; + mozilla::Atomic interruptPar_; + public: - /* - * If non-zero, ForkJoin should service an interrupt. This is a separate - * flag from |interrupt| because we cannot use the mprotect trick with PJS - * code and ignore the TriggerCallbackAnyThreadDontStopIon trigger. - */ - mozilla::Atomic interruptPar; + enum InterruptMode { + RequestInterruptMainThread, + RequestInterruptAnyThread, + RequestInterruptAnyThreadDontStopIon, + RequestInterruptAnyThreadForkJoin + }; + + // Any thread can call requestInterrupt() to request that the main JS thread + // stop running and call the interrupt callback (allowing the interrupt + // callback to halt execution). To stop the main JS thread, requestInterrupt + // sets two fields: interrupt_ (set to true) and jitStackLimit_ (set to + // UINTPTR_MAX). The JS engine must continually poll one of these fields + // and call handleInterrupt if either field has the interrupt value. (The + // point of setting jitStackLimit_ to UINTPTR_MAX is that JIT code already + // needs to guard on jitStackLimit_ in every function prologue to avoid + // stack overflow, so we avoid a second branch on interrupt_ by setting + // jitStackLimit_ to a value that is guaranteed to fail the guard.) + // + // Note that the writes to interrupt_ and jitStackLimit_ use a Relaxed + // Atomic so, while the writes are guaranteed to eventually be visible to + // the main thread, it can happen in any order. handleInterrupt calls the + // interrupt callback if either is set, so it really doesn't matter as long + // as the JS engine is continually polling at least one field. In corner + // cases, this relaxed ordering could lead to an interrupt handler being + // called twice in succession after a single requestInterrupt call, but + // that's fine. + void requestInterrupt(InterruptMode mode); + bool handleInterrupt(JSContext *cx); + + MOZ_ALWAYS_INLINE bool hasPendingInterrupt() const { + return interrupt_; + } + MOZ_ALWAYS_INLINE bool hasPendingInterruptPar() const { + return interruptPar_; + } + + // For read-only JIT use: + void *addressOfInterruptUint32() { + static_assert(sizeof(interrupt_) == sizeof(uint32_t), "Assumed by JIT callers"); + return &interrupt_; + } + void *addressOfInterruptParUint32() { + static_assert(sizeof(interruptPar_) == sizeof(uint32_t), "Assumed by JIT callers"); + return &interruptPar_; + } /* Set when handling a signal for a thread associated with this runtime. */ bool handlingSignal; @@ -900,7 +943,7 @@ struct JSRuntime : public JS::shadow::Runtime, void setDefaultVersion(JSVersion v) { defaultVersion_ = v; } /* Base address of the native stack for the current thread. */ - uintptr_t nativeStackBase; + const uintptr_t nativeStackBase; /* The native stack size limit that runtime should not exceed. */ size_t nativeStackQuota[js::StackKindCount]; @@ -1266,10 +1309,6 @@ struct JSRuntime : public JS::shadow::Runtime, bool jitSupportsFloatingPoint; bool jitSupportsSimd; - // Used to reset stack limit after a signaled interrupt (i.e. jitStackLimit_ = -1) - // has been noticed by Ion/Baseline. - void resetJitStackLimit(); - // Cache for jit::GetPcScript(). js::jit::PcScriptCache *ionPcScriptCache; @@ -1330,17 +1369,6 @@ struct JSRuntime : public JS::shadow::Runtime, /* onOutOfMemory but can call the largeAllocationFailureCallback. */ JS_FRIEND_API(void *) onOutOfMemoryCanGC(void *p, size_t bytes); - // Ways in which the interrupt callback on the runtime can be triggered, - // varying based on which thread is triggering the callback. - enum InterruptMode { - RequestInterruptMainThread, - RequestInterruptAnyThread, - RequestInterruptAnyThreadDontStopIon, - RequestInterruptAnyThreadForkJoin - }; - - void requestInterrupt(InterruptMode mode); - void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *runtime); private: @@ -1564,13 +1592,6 @@ class MOZ_STACK_CLASS AutoKeepAtoms } }; -inline void -PerThreadData::setJitStackLimit(uintptr_t limit) -{ - MOZ_ASSERT(runtime_->currentThreadOwnsInterruptLock()); - jitStackLimit = limit; -} - inline JSRuntime * PerThreadData::runtimeFromMainThread() { From 04352f1e00a5594e1620338dbba91cc39b338f0f Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 11 Nov 2014 13:55:02 +0900 Subject: [PATCH 36/71] Bug 1094000 part.1 Ensure that nsHTMLEditRules::InsertBRIfNeeded() runs after a text node is removed at handling Backspace key r=roc --- editor/libeditor/nsHTMLEditRules.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/editor/libeditor/nsHTMLEditRules.cpp b/editor/libeditor/nsHTMLEditRules.cpp index c2920ca6461..adeb5e482a2 100644 --- a/editor/libeditor/nsHTMLEditRules.cpp +++ b/editor/libeditor/nsHTMLEditRules.cpp @@ -447,7 +447,8 @@ nsHTMLEditRules::AfterEditInner(EditAction action, res = PromoteRange(mDocChangeRange, action); NS_ENSURE_SUCCESS(res, res); - // if we did a ranged deletion, make sure we have a place to put caret. + // if we did a ranged deletion or handling backspace key, make sure we have + // a place to put caret. // Note we only want to do this if the overall operation was deletion, // not if deletion was done along the way for EditAction::loadHTML, EditAction::insertText, etc. // That's why this is here rather than DidDeleteSelection(). @@ -2045,6 +2046,10 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection, res = InsertBRIfNeeded(aSelection); NS_ENSURE_SUCCESS(res, res); + // Remember that we did a ranged delete for the benefit of + // AfterEditInner(). + mDidRangedDelete = true; + return NS_OK; } From 810c426d81711c204b2f50393ff1c17cf2358b05 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 11 Nov 2014 13:55:02 +0900 Subject: [PATCH 37/71] Bug 1094000 part.2 Add tests of HTML editor inserting
node at removing a last character r=roc --- editor/libeditor/tests/mochitest.ini | 1 + editor/libeditor/tests/test_bug1094000.html | 104 ++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 editor/libeditor/tests/test_bug1094000.html diff --git a/editor/libeditor/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini index 6599c3e5481..c8bbeb14232 100644 --- a/editor/libeditor/tests/mochitest.ini +++ b/editor/libeditor/tests/mochitest.ini @@ -140,6 +140,7 @@ skip-if = os != "win" [test_bug998188.html] [test_bug1026397.html] [test_bug1067255.html] +[test_bug1094000.html] skip-if = e10s [test_CF_HTML_clipboard.html] [test_contenteditable_focus.html] diff --git a/editor/libeditor/tests/test_bug1094000.html b/editor/libeditor/tests/test_bug1094000.html new file mode 100644 index 00000000000..cc27cc67533 --- /dev/null +++ b/editor/libeditor/tests/test_bug1094000.html @@ -0,0 +1,104 @@ + + + + + Test for Bug 1094000 + + + + + +Mozilla Bug 1094000 +

+
+
+

+
a
+
b
+
c
+
d
+
e
+
+
+
+
+ + From 59930567cd9db3122e0b972b36544a0e30d24375 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Tue, 11 Nov 2014 16:41:58 +1100 Subject: [PATCH 38/71] Bug 1083004 - Create anonymous ruby base container when necessary. r=bz --- layout/base/nsCSSFrameConstructor.cpp | 57 ++++++++++++++++++++++++--- layout/base/nsCSSFrameConstructor.h | 15 +++++-- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 322af2dc809..822f650a594 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -2282,8 +2282,8 @@ NeedFrameFor(const nsFrameConstructorState& aState, // should be considered ignorable just because they evaluate to // whitespace. - // We could handle all this in CreateNeededPseudos or some other place - // after we build our frame construction items, but that would involve + // We could handle all this in CreateNeededPseudoContainers or some other + // place after we build our frame construction items, but that would involve // creating frame construction items for whitespace kids of // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them // all anyway, and involve an extra walk down the frame construction item @@ -9347,9 +9347,10 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems( * contain only items for frames that can be direct kids of aParentFrame. */ void -nsCSSFrameConstructor::CreateNeededPseudos(nsFrameConstructorState& aState, - FrameConstructionItemList& aItems, - nsIFrame* aParentFrame) +nsCSSFrameConstructor::CreateNeededPseudoContainers( + nsFrameConstructorState& aState, + FrameConstructionItemList& aItems, + nsIFrame* aParentFrame) { ParentType ourParentType = GetParentType(aParentFrame); if (aItems.AllWantParentType(ourParentType)) { @@ -9622,14 +9623,58 @@ nsCSSFrameConstructor::CreateNeededPseudos(nsFrameConstructorState& aState, } while (!iter.IsDone()); } +void nsCSSFrameConstructor::CreateNeededPseudoSiblings( + nsFrameConstructorState& aState, + FrameConstructionItemList& aItems, + nsIFrame* aParentFrame) +{ + if (aItems.IsEmpty() || + GetParentType(aParentFrame) != eTypeRuby) { + return; + } + + FCItemIterator iter(aItems); + // XXX Use computed display value instead in bug 1096639. + auto creationFunc = reinterpret_cast( + iter.item().mFCData->mFunc.mCreationFunc); + if (creationFunc == NS_NewRubyBaseContainerFrame) { + return; + } + + NS_ASSERTION(creationFunc == NS_NewRubyTextContainerFrame, + "Child of ruby frame should either a rbc or a rtc"); + + const PseudoParentData& pseudoData = + sPseudoParentData[eTypeRubyBaseContainer]; + already_AddRefed pseudoStyle = mPresShell->StyleSet()-> + ResolveAnonymousBoxStyle(*pseudoData.mPseudoType, + aParentFrame->StyleContext()); + FrameConstructionItem* newItem = + new FrameConstructionItem(&pseudoData.mFCData, + // Use the content of the parent frame + aParentFrame->GetContent(), + // Tag type + *pseudoData.mPseudoType, + // Use the namespace of the rtc frame + iter.item().mNameSpaceID, + // no pending binding + nullptr, + pseudoStyle, + true, nullptr); + newItem->mIsAllInline = true; + newItem->mChildItems.SetParentHasNoXBLChildren(true); + iter.InsertItem(newItem); +} + inline void nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState, FrameConstructionItemList& aItems, nsContainerFrame* aParentFrame, nsFrameItems& aFrameItems) { - CreateNeededPseudos(aState, aItems, aParentFrame); + CreateNeededPseudoContainers(aState, aItems, aParentFrame); CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame); + CreateNeededPseudoSiblings(aState, aItems, aParentFrame); aItems.SetTriedConstructingFrames(); for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) { diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 0cc1a3399de..cad3d664965 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -1097,13 +1097,20 @@ private: nsIFrame* aParentFrame); /** - * Function to create the table pseudo items we need. + * Function to create the pseudo intermediate containers we need. * @param aItems the child frame construction items before pseudo creation * @param aParentFrame the parent frame we're creating pseudos for */ - inline void CreateNeededPseudos(nsFrameConstructorState& aState, - FrameConstructionItemList& aItems, - nsIFrame* aParentFrame); + inline void CreateNeededPseudoContainers(nsFrameConstructorState& aState, + FrameConstructionItemList& aItems, + nsIFrame* aParentFrame); + + /** + * Function to create the pseudo siblings we need. + */ + inline void CreateNeededPseudoSiblings(nsFrameConstructorState& aState, + FrameConstructionItemList& aItems, + nsIFrame* aParentFrame); /** * Function to adjust aParentFrame to deal with captions. From 9c2178e1e83c71d097a36cca5e45cc686118d9ce Mon Sep 17 00:00:00 2001 From: Shian-Yow Wu Date: Tue, 11 Nov 2014 14:12:47 +0800 Subject: [PATCH 39/71] Bug 1091002 - Drop loadend event to worker thread XHR if it's triggered by abort event from worker. r=khuey --- dom/workers/XMLHttpRequest.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index ff316b88dfa..60df050bcd5 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -1279,6 +1279,10 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) mProxy->mSeenUploadLoadStart = false; } else { + if (!mProxy->mSeenLoadStart) { + // We've already dispatched premature abort events. + return true; + } mProxy->mSeenLoadStart = false; } } @@ -2404,7 +2408,9 @@ XMLHttpRequest::UpdateState(const StateData& aStateData, bool aUseCachedArrayBufferResponse) { if (aUseCachedArrayBufferResponse) { - MOZ_ASSERT(JS_IsArrayBufferObject(mStateData.mResponse.toObjectOrNull())); + MOZ_ASSERT(mStateData.mResponse.isObject() && + JS_IsArrayBufferObject(&mStateData.mResponse.toObject())); + JS::Rooted response(mWorkerPrivate->GetJSContext(), mStateData.mResponse); mStateData = aStateData; From edad0ff5345171a9aaac78562599b72ca1cc1f44 Mon Sep 17 00:00:00 2001 From: Max Li Date: Sun, 2 Nov 2014 20:20:11 -0800 Subject: [PATCH 40/71] Bug 1071777 - Use the contextmenu event target as a fallback for building context menus. r=kats --- mobile/android/chrome/content/browser.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index a2b86b2335a..beb7af159a6 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -2482,8 +2482,9 @@ var NativeWindow = { return; } - // Use the highlighted element for the context menu target. - this._target = BrowserEventHandler._highlightElement; + // Use the highlighted element for the context menu target. When accessibility is + // enabled, elements may not be highlighted so use the event target instead. + this._target = BrowserEventHandler._highlightElement || event.target; if (!this._target) { return; } From 8a948d3e4805ec1d00b758d250e52ea489149220 Mon Sep 17 00:00:00 2001 From: Max Li Date: Sun, 9 Nov 2014 16:37:16 -0800 Subject: [PATCH 41/71] Bug 1071777 - Send a context menu event on braille long press. r=eeejay --- accessible/jsat/AccessFu.jsm | 17 ----------------- accessible/jsat/content-script.js | 9 +++++++-- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/accessible/jsat/AccessFu.jsm b/accessible/jsat/AccessFu.jsm index cc66258288d..fa04330d59e 100644 --- a/accessible/jsat/AccessFu.jsm +++ b/accessible/jsat/AccessFu.jsm @@ -234,9 +234,6 @@ this.AccessFu = { // jshint ignore:line case 'AccessFu:Input': this.Input.setEditState(aMessage.json); break; - case 'AccessFu:ActivateContextMenu': - this.Input.activateContextMenu(aMessage.json); - break; case 'AccessFu:DoScroll': this.Input.doScroll(aMessage.json); break; @@ -283,7 +280,6 @@ this.AccessFu = { // jshint ignore:line aMessageManager.addMessageListener('AccessFu:Present', this); aMessageManager.addMessageListener('AccessFu:Input', this); aMessageManager.addMessageListener('AccessFu:Ready', this); - aMessageManager.addMessageListener('AccessFu:ActivateContextMenu', this); aMessageManager.addMessageListener('AccessFu:DoScroll', this); }, @@ -291,7 +287,6 @@ this.AccessFu = { // jshint ignore:line aMessageManager.removeMessageListener('AccessFu:Present', this); aMessageManager.removeMessageListener('AccessFu:Input', this); aMessageManager.removeMessageListener('AccessFu:Ready', this); - aMessageManager.removeMessageListener('AccessFu:ActivateContextMenu', this); aMessageManager.removeMessageListener('AccessFu:DoScroll', this); }, @@ -673,9 +668,6 @@ var Input = { case 'doubletap1': this.activateCurrent(); break; - case 'taphold1': - this.sendContextMenuMessage(); - break; case 'doubletaphold1': Utils.dispatchChromeEvent('accessibility-control', 'quicknav-menu'); break; @@ -883,15 +875,6 @@ var Input = { mm.sendAsyncMessage('AccessFu:ContextMenu', {}); }, - activateContextMenu: function activateContextMenu(aDetails) { - if (Utils.MozBuildApp === 'mobile/android') { - let p = AccessFu.adjustContentBounds(aDetails.bounds, - Utils.CurrentBrowser, true).center(); - Services.obs.notifyObservers(null, 'Gesture:LongPress', - JSON.stringify({x: p.x, y: p.y})); - } - }, - setEditState: function setEditState(aEditState) { Logger.debug(() => { return ['setEditState', JSON.stringify(aEditState)] }); this.editState = aEditState; diff --git a/accessible/jsat/content-script.js b/accessible/jsat/content-script.js index bf06b09b65b..3342532f862 100644 --- a/accessible/jsat/content-script.js +++ b/accessible/jsat/content-script.js @@ -69,8 +69,13 @@ function forwardToChild(aMessage, aListener, aVCPosition) { function activateContextMenu(aMessage) { let position = Utils.getVirtualCursor(content.document).position; if (!forwardToChild(aMessage, activateContextMenu, position)) { - sendAsyncMessage('AccessFu:ActivateContextMenu', - { bounds: Utils.getBounds(position, true) }); + let center = Utils.getBounds(position, true).center(); + + let evt = content.document.createEvent('HTMLEvents'); + evt.initEvent('contextmenu', true, true); + evt.clientX = center.x; + evt.clientY = center.y; + position.DOMNode.dispatchEvent(evt); } } From 091cb9a3e8a4265e9f935596eda83ea3e999d824 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 15:20:15 -0800 Subject: [PATCH 42/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/9f8cebdcb4c8 Author: Ghislain 'Aus' Lacroix Desc: Merge pull request #25973 from KevinGrandon/bug_1095187_debug_download_intermittent_test Bug 1095187 - Software Home Button - File Open Error Proper layout for file error dialog - Wait for download success +autoland ======== https://hg.mozilla.org/integration/gaia-central/rev/fc2c35c6f236 Author: Kevin Grandon Desc: Bug 1095187 - Make SHB file test wait until download complete --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 1fe31f67df0..7d88c9981c6 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "65b7d35ad078b90133481983950c64ad8fd27dd4", + "revision": "9f8cebdcb4c8b7d49a703515e9e084a55bf35ff2", "repo_path": "/integration/gaia-central" } From 87f515ee7e1367df533603633459f4f41ec5c4fc Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 15:22:10 -0800 Subject: [PATCH 43/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 4 ++-- b2g/config/emulator-ics/sources.xml | 4 ++-- b2g/config/emulator-jb/sources.xml | 4 ++-- b2g/config/emulator-kk/sources.xml | 4 ++-- b2g/config/emulator/sources.xml | 4 ++-- b2g/config/flame-kk/sources.xml | 4 ++-- b2g/config/flame/sources.xml | 4 ++-- b2g/config/hamachi/sources.xml | 4 ++-- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 4 ++-- b2g/config/wasabi/sources.xml | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index b8bb31bcd2d..ce1a3e40dc6 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index ebf71029dab..a4a80233f73 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 79b8a47638a..d2030e71030 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,10 +17,10 @@ - + - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 38d9874a51d..e3b607151c0 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index ebf71029dab..a4a80233f73 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 799fcb66e17..b979130af39 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index c3f2212ca31..ba2a7c46afe 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,10 +17,10 @@ - + - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 6fdae0d266a..938e701d174 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,12 +17,12 @@ - + - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index f65302ad503..af9f5b52339 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 0745223635c..ac0bdddfee1 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,10 +17,10 @@ - + - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index ddb03d0276a..2a59e51ba77 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,12 +17,12 @@ - + - + From 7c8bafad2be0835e949762a82b69417b27287376 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 17:30:15 -0800 Subject: [PATCH 44/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/ae4479c59e51 Author: Michael Henretty Desc: Merge pull request #25971 from pasupulaphani/patch_936823_3 Bug 936823 - [FTE] on last attempt for correct PUK, two messages with sa... ======== https://hg.mozilla.org/integration/gaia-central/rev/8baf8c9e082a Author: pasupulaphani Desc: Bug 936823 - [FTE] on last attempt for correct PUK, two messages with same meaning shown/concatenated (r=fcampo) --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7d88c9981c6..ff4ca225a09 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "9f8cebdcb4c8b7d49a703515e9e084a55bf35ff2", + "revision": "ae4479c59e51ecf86498bddf788822b53c2a477c", "repo_path": "/integration/gaia-central" } From 3e9034cb09e31fd05f7165fd80c5c98a09e0177b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 17:37:07 -0800 Subject: [PATCH 45/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index ce1a3e40dc6..15b74e6746b 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index a4a80233f73..fb226e9dd60 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index d2030e71030..7e66d82e857 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index e3b607151c0..9a73936f593 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index a4a80233f73..fb226e9dd60 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index b979130af39..2d83cdb0cb6 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index ba2a7c46afe..d45d3fce0b3 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 938e701d174..1a2e28643fa 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index af9f5b52339..569b2d83567 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index ac0bdddfee1..9bd8c554c57 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 2a59e51ba77..23ff83169d0 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 084ab7eb10d58c52b22fc8d451c3f59b9de5c23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kan-Ru=20Chen=20=28=E9=99=B3=E4=BE=83=E5=A6=82=29?= Date: Tue, 11 Nov 2014 10:25:36 +0800 Subject: [PATCH 46/71] Bug 1059662 - Disallow OOP app to embed in-proc apps. r=fabrice Some mochitest that use embed-apps in an oop context is disabled. --HG-- extra : rebase_source : 72de2cdae86eb8d55e642529cd4aae0af97e4e96 --- dom/apps/tests/mochitest.ini | 2 + .../browserElement_DisallowEmbedAppsInOOP.js | 42 +++++++++++++++++++ ...browserElement_DisallowEmbedAppsInOOP.html | 19 +++++++++ .../mochitest/mochitest-oop.ini | 1 + dom/browser-element/mochitest/mochitest.ini | 4 ++ ...Element_inproc_DisallowEmbedAppsInOOP.html | 13 ++++++ ...serElement_oop_DisallowEmbedAppsInOOP.html | 13 ++++++ dom/datastore/tests/mochitest.ini | 1 + dom/html/nsGenericHTMLFrameElement.cpp | 6 +++ .../mochitest/localstorage/mochitest.ini | 2 +- dom/tv/test/mochitest/mochitest.ini | 1 + 11 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 dom/browser-element/mochitest/browserElement_DisallowEmbedAppsInOOP.js create mode 100644 dom/browser-element/mochitest/file_browserElement_DisallowEmbedAppsInOOP.html create mode 100644 dom/browser-element/mochitest/test_browserElement_inproc_DisallowEmbedAppsInOOP.html create mode 100644 dom/browser-element/mochitest/test_browserElement_oop_DisallowEmbedAppsInOOP.html diff --git a/dom/apps/tests/mochitest.ini b/dom/apps/tests/mochitest.ini index 9cd1be3ac93..d6b6a296ec7 100644 --- a/dom/apps/tests/mochitest.ini +++ b/dom/apps/tests/mochitest.ini @@ -26,6 +26,7 @@ support-files = [test_app_enabled.html] [test_app_update.html] +skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app [test_bug_795164.html] [test_import_export.html] [test_install_multiple_apps_origin.html] @@ -42,3 +43,4 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only [test_theme_role.html] [test_web_app_install.html] [test_widget.html] +skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app diff --git a/dom/browser-element/mochitest/browserElement_DisallowEmbedAppsInOOP.js b/dom/browser-element/mochitest/browserElement_DisallowEmbedAppsInOOP.js new file mode 100644 index 00000000000..8c9b1ba811f --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_DisallowEmbedAppsInOOP.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1059662 - Only allow a app to embed others apps when it runs +// in-process. +// +// The "inproc" version of this test should successfully embed the +// app, and the "oop" version of this test should fail to embed the +// app. + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +SpecialPowers.setAllAppsLaunchable(true); + +function runTest() { + var canEmbedApp = !browserElementTestHelpers.getOOPByDefaultPref(); + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + + iframe.addEventListener('mozbrowsershowmodalprompt', function(e) { + is(e.detail.message == 'app', canEmbedApp, e.detail.message); + SimpleTest.finish(); + }); + + document.body.appendChild(iframe); + + var context = { 'url': 'http://example.org', + 'appId': SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID, + 'isInBrowserElement': true }; + SpecialPowers.pushPermissions([ + {'type': 'browser', 'allow': 1, 'context': context}, + {'type': 'embed-apps', 'allow': 1, 'context': context} + ], function() { + iframe.src = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_DisallowEmbedAppsInOOP.html'; + }); +} + +addEventListener('testready', runTest); diff --git a/dom/browser-element/mochitest/file_browserElement_DisallowEmbedAppsInOOP.html b/dom/browser-element/mochitest/file_browserElement_DisallowEmbedAppsInOOP.html new file mode 100644 index 00000000000..d8635ee96f2 --- /dev/null +++ b/dom/browser-element/mochitest/file_browserElement_DisallowEmbedAppsInOOP.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/dom/browser-element/mochitest/mochitest-oop.ini b/dom/browser-element/mochitest/mochitest-oop.ini index 405687dda6b..1958b65fe0d 100644 --- a/dom/browser-element/mochitest/mochitest-oop.ini +++ b/dom/browser-element/mochitest/mochitest-oop.ini @@ -31,6 +31,7 @@ skip-if = (toolkit == 'gonk' && !debug) [test_browserElement_oop_CopyPaste.html] [test_browserElement_oop_DOMRequestError.html] [test_browserElement_oop_DataURI.html] +[test_browserElement_oop_DisallowEmbedAppsInOOP.html] [test_browserElement_oop_DocumentFirstPaint.html] [test_browserElement_oop_Download.html] disabled = bug 1022281 diff --git a/dom/browser-element/mochitest/mochitest.ini b/dom/browser-element/mochitest/mochitest.ini index 0cbdc669af3..50af96cd3f7 100644 --- a/dom/browser-element/mochitest/mochitest.ini +++ b/dom/browser-element/mochitest/mochitest.ini @@ -22,6 +22,7 @@ support-files = browserElement_CopyPaste.js browserElement_DOMRequestError.js browserElement_DataURI.js + browserElement_DisallowEmbedAppsInOOP.js browserElement_DocumentFirstPaint.js browserElement_Download.js browserElement_ErrorSecurity.js @@ -77,6 +78,7 @@ support-files = file_browserElement_CloseApp.html file_browserElement_CloseFromOpener.html file_browserElement_CookiesNotThirdParty.html + file_browserElement_DisallowEmbedAppsInOOP.html file_browserElement_ForwardName.html file_browserElement_FrameWrongURI.html file_browserElement_LoadEvents.html @@ -143,6 +145,8 @@ skip-if = buildapp == 'b2g' [test_browserElement_inproc_CopyPaste.html] [test_browserElement_inproc_DOMRequestError.html] [test_browserElement_inproc_DataURI.html] +[test_browserElement_inproc_DisallowEmbedAppsInOOP.html] +skip-if = os == "android" || toolkit == 'gonk' # embed-apps doesn't work in the mochitest app [test_browserElement_inproc_DocumentFirstPaint.html] [test_browserElement_inproc_Download.html] disabled = bug 1022281 diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_DisallowEmbedAppsInOOP.html b/dom/browser-element/mochitest/test_browserElement_inproc_DisallowEmbedAppsInOOP.html new file mode 100644 index 00000000000..efc5fb4410e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_DisallowEmbedAppsInOOP.html @@ -0,0 +1,13 @@ + + + + Test for Bug 1059662 + + + + + + + + \ No newline at end of file diff --git a/dom/browser-element/mochitest/test_browserElement_oop_DisallowEmbedAppsInOOP.html b/dom/browser-element/mochitest/test_browserElement_oop_DisallowEmbedAppsInOOP.html new file mode 100644 index 00000000000..efc5fb4410e --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_DisallowEmbedAppsInOOP.html @@ -0,0 +1,13 @@ + + + + Test for Bug 1059662 + + + + + + + + \ No newline at end of file diff --git a/dom/datastore/tests/mochitest.ini b/dom/datastore/tests/mochitest.ini index 24931b18e77..e9e8b813992 100644 --- a/dom/datastore/tests/mochitest.ini +++ b/dom/datastore/tests/mochitest.ini @@ -34,6 +34,7 @@ support-files = file_notify_system_message.html [test_app_install.html] +skip-if = toolkit == 'gonk' # embed-apps doesn't work in the mochitest app [test_readonly.html] skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226 [test_basic.html] diff --git a/dom/html/nsGenericHTMLFrameElement.cpp b/dom/html/nsGenericHTMLFrameElement.cpp index c947c7933e3..8b17fe7d57b 100644 --- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -7,6 +7,7 @@ #include "nsGenericHTMLFrameElement.h" +#include "mozilla/dom/ContentChild.h" #include "mozilla/Preferences.h" #include "mozilla/ErrorResult.h" #include "GeckoProfiler.h" @@ -437,6 +438,11 @@ nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut) return NS_OK; } + if (XRE_GetProcessType() != GeckoProcessType_Default) { + NS_WARNING("Can't embed-apps. Embed-apps is restricted to in-proc apps, see bug 1059662"); + return NS_OK; + } + nsAutoString appManifestURL; nsAutoString widgetManifestURL; diff --git a/dom/tests/mochitest/localstorage/mochitest.ini b/dom/tests/mochitest/localstorage/mochitest.ini index 1be37ddfcd6..aa0343261cf 100644 --- a/dom/tests/mochitest/localstorage/mochitest.ini +++ b/dom/tests/mochitest/localstorage/mochitest.ini @@ -17,7 +17,7 @@ support-files = localStorageCommon.js [test_appIsolation.html] -skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 793211 # b2g(needs https to work) b2g-debug(needs https to work) b2g-desktop(needs https to work) +skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 793211 # b2g(needs https to work) b2g-debug(needs https to work) b2g-desktop(needs https to work) [test_brokenUTF-16.html] [test_bug600307-DBOps.html] [test_bug746272-1.html] diff --git a/dom/tv/test/mochitest/mochitest.ini b/dom/tv/test/mochitest/mochitest.ini index eaa39eb8963..570133729db 100644 --- a/dom/tv/test/mochitest/mochitest.ini +++ b/dom/tv/test/mochitest/mochitest.ini @@ -1,5 +1,6 @@ [DEFAULT] skip-if = os == "linux" && e10s && debug # bug 1091322 - wallpaper over an e10s crash +skip-if = os == "android" || toolkit == "gonk" || e10s support-files = file_app.sjs file_app.template.webapp From f37b7f673d64e40a7e0226d1dee6b8d1bf53b4d3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 20:00:54 -0800 Subject: [PATCH 47/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/949e3ca4671a Author: autolander Desc: Bug 1095805 - merge pull request #25994 from KevinGrandon:bug_1095805_shb_crash_dialog to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/060dee78c9ab Author: Kevin Grandon Desc: Bug 1095805 - [System][SHB] Enable software home styles for crash dialog r=mhenretty --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ff4ca225a09..2f9c53ed7b5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "ae4479c59e51ecf86498bddf788822b53c2a477c", - "repo_path": "/integration/gaia-central" + "revision": "949e3ca4671ad0aa619cd7118f81c4fc7ea91701", + "repo_path": "integration/gaia-central" } From 91a692e02888fdf8942b2ada4f7755af8b962258 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 20:07:17 -0800 Subject: [PATCH 48/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 15b74e6746b..910d75f67f3 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index fb226e9dd60..f6cad45ee02 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 7e66d82e857..fa0808c0873 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 9a73936f593..320fe20de82 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index fb226e9dd60..f6cad45ee02 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 2d83cdb0cb6..e8cafe04efd 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index d45d3fce0b3..071e871a9bb 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 1a2e28643fa..fac9801f05d 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 569b2d83567..1b952628d26 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 9bd8c554c57..5ada07171af 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 23ff83169d0..8f08367ca10 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 66fb532bac14e573d541022945c96ba9c675a0fd Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 21:00:55 -0800 Subject: [PATCH 49/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/9a1b8914d3ac Author: Timothy Guan-tin Chien Desc: Merge pull request #25998 from mcepl/cs_qwerty-layout Bug 1096057 - Added cs-qwerty layout, r=timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/7849d6c659fb Author: Matěj Cepl Desc: Bug 1096057 - Added cs-qwerty layout The only difference from cs.js is that it is QWERTY, not QWERTZ. Although, this is not an official layout according to the Czech technical norms, it is very widely used “in the wild”. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 2f9c53ed7b5..ae6658e4278 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "949e3ca4671ad0aa619cd7118f81c4fc7ea91701", + "revision": "9a1b8914d3acc6d7eab18779b9a8e4b0a3fc52ea", "repo_path": "integration/gaia-central" } From 0162981d136d7967188bae507319d0e1f622bf94 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 21:07:19 -0800 Subject: [PATCH 50/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 910d75f67f3..013a9f2c853 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f6cad45ee02..685c4aa938c 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index fa0808c0873..9e5f9c9e76e 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 320fe20de82..fadb088116b 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f6cad45ee02..685c4aa938c 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index e8cafe04efd..6008a6351f8 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 071e871a9bb..6e787ffa9ad 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index fac9801f05d..39047b7b2c5 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 1b952628d26..66ffaf757db 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 5ada07171af..6a7730e651b 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 8f08367ca10..6bc22d04da6 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 37790ff4d6d64a3ff3876a741024ed785f90e566 Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Mon, 10 Nov 2014 18:55:11 +0800 Subject: [PATCH 51/71] Bug 1079649: Use a temporary (.part) file to store incoming file. (bluetooth/bluez) r=btian --- dom/bluetooth/bluez/BluetoothOppManager.cpp | 75 +++++++++++++++++---- dom/bluetooth/bluez/BluetoothOppManager.h | 3 + 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/dom/bluetooth/bluez/BluetoothOppManager.cpp b/dom/bluetooth/bluez/BluetoothOppManager.cpp index 021a706a9e3..a8aefec2973 100644 --- a/dom/bluetooth/bluez/BluetoothOppManager.cpp +++ b/dom/bluetooth/bluez/BluetoothOppManager.cpp @@ -553,6 +553,7 @@ BluetoothOppManager::AfterOppDisconnected() mLastCommand = 0; mPutPacketReceivedLength = 0; mDsFile = nullptr; + mDummyDsFile = nullptr; // We can't reset mSuccessFlag here since this function may be called // before we send system message of transfer complete @@ -579,6 +580,34 @@ BluetoothOppManager::AfterOppDisconnected() } } +void +BluetoothOppManager::RecoverFileName() +{ + // Remove the trailing ".part" file name from mDsFile by two steps + // 1. mDsFile->SetPath() so that the notification sent to Gaia will carry + // correct information of the file. + // 2. mDsFile->mFile->RenameTo() so that the file name would actually be + // changed in file system. + if (mDsFile && mDsFile->mFile) { + nsString path; + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + + mDsFile->SetPath(path); + mDsFile->mFile->RenameTo(nullptr, mFileName); + } +} + +void +BluetoothOppManager::DeleteDummyFile() +{ + // Remove the empty temp file + if (mDummyDsFile && mDummyDsFile->mFile) { + mDummyDsFile->mFile->Remove(false); + mDummyDsFile = nullptr; + } +} + void BluetoothOppManager::DeleteReceivedFile() { @@ -591,6 +620,8 @@ BluetoothOppManager::DeleteReceivedFile() mDsFile->mFile->Remove(false); mDsFile = nullptr; } + + DeleteDummyFile(); } bool @@ -598,25 +629,39 @@ BluetoothOppManager::CreateFile() { MOZ_ASSERT(mPutPacketReceivedLength == mPacketLength); + // Create one dummy file to be a placeholder for the target file name, and + // create another file with a meaningless file extension to write the received + // data. By doing this, we can prevent applications from parsing incomplete + // data in the middle of the receiving process. nsString path; path.AssignLiteral(TARGET_SUBDIR); path.Append(mFileName); - mDsFile = DeviceStorageFile::CreateUnique( - path, nsIFile::NORMAL_FILE_TYPE, 0644); + // Use an empty dummy file object to occupy the file name, so that after the + // whole file has been received successfully by using mDsFile, we could just + // remove mDummyDsFile and rename mDsFile to the file name of mDummyDsFile. + mDummyDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_TRUE(mDummyDsFile, false); + + // The function CreateUnique() may create a file with a different file + // name from the original mFileName. Therefore we have to retrieve + // the file name again. + mDummyDsFile->mFile->GetLeafName(mFileName); + + BT_LOGR("mFileName: %s", NS_ConvertUTF16toUTF8(mFileName).get()); + + // Prepare the entire file path for the .part file + path.Truncate(); + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + path.AppendLiteral(".part"); + + mDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); NS_ENSURE_TRUE(mDsFile, false); - nsCOMPtr f; - mDsFile->mFile->Clone(getter_AddRefs(f)); - - /* - * The function CreateUnique() may create a file with a different file - * name from the original mFileName. Therefore we have to retrieve - * the file name again. - */ - f->GetLeafName(mFileName); - - NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f); + NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), mDsFile->mFile); NS_ENSURE_TRUE(mOutputStream, false); return true; @@ -932,6 +977,10 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage) // Success to receive a file and notify completion if (mPutFinalFlag) { mSuccessFlag = true; + + DeleteDummyFile(); + RecoverFileName(); + FileTransferComplete(); NotifyAboutFileChange(); } diff --git a/dom/bluetooth/bluez/BluetoothOppManager.h b/dom/bluetooth/bluez/BluetoothOppManager.h index d6e7bf6daa5..6d21d144eca 100644 --- a/dom/bluetooth/bluez/BluetoothOppManager.h +++ b/dom/bluetooth/bluez/BluetoothOppManager.h @@ -85,6 +85,8 @@ private: void ReceivingFileConfirmation(); bool CreateFile(); bool WriteToFile(const uint8_t* aData, int aDataLength); + void RecoverFileName(); + void DeleteDummyFile(); void DeleteReceivedFile(); void ReplyToConnect(); void ReplyToDisconnectOrAbort(); @@ -209,6 +211,7 @@ private: nsCOMPtr mInputStream; nsCOMPtr mMountLock; nsRefPtr mDsFile; + nsRefPtr mDummyDsFile; // If a connection has been established, mSocket will be the socket // communicating with the remote socket. We maintain the invariant that if From ddaada31b2c3e475924be3b8b04b5f26f9fc0ca6 Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Mon, 10 Nov 2014 18:53:21 +0800 Subject: [PATCH 52/71] Bug 1079649: Use a temporary (.part) file to store incoming file. (bluetooth/bluedroid) r=btian --- .../bluedroid/BluetoothOppManager.cpp | 75 +++++++++++++++---- dom/bluetooth/bluedroid/BluetoothOppManager.h | 3 + 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp index 555a9e9b1d2..ae7d25de7d3 100644 --- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp +++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp @@ -531,6 +531,7 @@ BluetoothOppManager::AfterOppDisconnected() mLastCommand = 0; mPutPacketReceivedLength = 0; mDsFile = nullptr; + mDummyDsFile = nullptr; // We can't reset mSuccessFlag here since this function may be called // before we send system message of transfer complete @@ -557,6 +558,34 @@ BluetoothOppManager::AfterOppDisconnected() } } +void +BluetoothOppManager::RecoverFileName() +{ + // Remove the trailing ".part" file name from mDsFile by two steps + // 1. mDsFile->SetPath() so that the notification sent to Gaia will carry + // correct information of the file. + // 2. mDsFile->mFile->RenameTo() so that the file name would actually be + // changed in file system. + if (mDsFile && mDsFile->mFile) { + nsString path; + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + + mDsFile->SetPath(path); + mDsFile->mFile->RenameTo(nullptr, mFileName); + } +} + +void +BluetoothOppManager::DeleteDummyFile() +{ + // Remove the empty temp file + if (mDummyDsFile && mDummyDsFile->mFile) { + mDummyDsFile->mFile->Remove(false); + mDummyDsFile = nullptr; + } +} + void BluetoothOppManager::DeleteReceivedFile() { @@ -569,6 +598,8 @@ BluetoothOppManager::DeleteReceivedFile() mDsFile->mFile->Remove(false); mDsFile = nullptr; } + + DeleteDummyFile(); } bool @@ -576,25 +607,39 @@ BluetoothOppManager::CreateFile() { MOZ_ASSERT(mPutPacketReceivedLength == mPacketLength); + // Create one dummy file to be a placeholder for the target file name, and + // create another file with a meaningless file extension to write the received + // data. By doing this, we can prevent applications from parsing incomplete + // data in the middle of the receiving process. nsString path; path.AssignLiteral(TARGET_SUBDIR); path.Append(mFileName); - mDsFile = DeviceStorageFile::CreateUnique( - path, nsIFile::NORMAL_FILE_TYPE, 0644); + // Use an empty dummy file object to occupy the file name, so that after the + // whole file has been received successfully by using mDsFile, we could just + // remove mDummyDsFile and rename mDsFile to the file name of mDummyDsFile. + mDummyDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_TRUE(mDummyDsFile, false); + + // The function CreateUnique() may create a file with a different file + // name from the original mFileName. Therefore we have to retrieve + // the file name again. + mDummyDsFile->mFile->GetLeafName(mFileName); + + BT_LOGR("mFileName: %s", NS_ConvertUTF16toUTF8(mFileName).get()); + + // Prepare the entire file path for the .part file + path.Truncate(); + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + path.AppendLiteral(".part"); + + mDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); NS_ENSURE_TRUE(mDsFile, false); - nsCOMPtr f; - mDsFile->mFile->Clone(getter_AddRefs(f)); - - /* - * The function CreateUnique() may create a file with a different file - * name from the original mFileName. Therefore we have to retrieve - * the file name again. - */ - f->GetLeafName(mFileName); - - NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f); + NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), mDsFile->mFile); NS_ENSURE_TRUE(mOutputStream, false); return true; @@ -911,6 +956,10 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage) // Success to receive a file and notify completion if (mPutFinalFlag) { mSuccessFlag = true; + + DeleteDummyFile(); + RecoverFileName(); + FileTransferComplete(); NotifyAboutFileChange(); } diff --git a/dom/bluetooth/bluedroid/BluetoothOppManager.h b/dom/bluetooth/bluedroid/BluetoothOppManager.h index fbfda2f294c..c751a17af5c 100644 --- a/dom/bluetooth/bluedroid/BluetoothOppManager.h +++ b/dom/bluetooth/bluedroid/BluetoothOppManager.h @@ -85,6 +85,8 @@ private: void ReceivingFileConfirmation(); bool CreateFile(); bool WriteToFile(const uint8_t* aData, int aDataLength); + void RecoverFileName(); + void DeleteDummyFile(); void DeleteReceivedFile(); void ReplyToConnect(); void ReplyToDisconnectOrAbort(); @@ -209,6 +211,7 @@ private: nsCOMPtr mInputStream; nsCOMPtr mMountLock; nsRefPtr mDsFile; + nsRefPtr mDummyDsFile; // If a connection has been established, mSocket will be the socket // communicating with the remote socket. We maintain the invariant that if From 2d7699124d2a7c33330bbb468d73c10c2b460d24 Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Mon, 10 Nov 2014 18:56:24 +0800 Subject: [PATCH 53/71] Bug 1079649: Use a temporary (.part) file to store incoming file. (bluetooth2/bluez) r=btian --- dom/bluetooth2/bluez/BluetoothOppManager.cpp | 75 ++++++++++++++++---- dom/bluetooth2/bluez/BluetoothOppManager.h | 3 + 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/dom/bluetooth2/bluez/BluetoothOppManager.cpp b/dom/bluetooth2/bluez/BluetoothOppManager.cpp index c42f55180b8..25337776958 100644 --- a/dom/bluetooth2/bluez/BluetoothOppManager.cpp +++ b/dom/bluetooth2/bluez/BluetoothOppManager.cpp @@ -553,6 +553,7 @@ BluetoothOppManager::AfterOppDisconnected() mLastCommand = 0; mPutPacketReceivedLength = 0; mDsFile = nullptr; + mDummyDsFile = nullptr; // We can't reset mSuccessFlag here since this function may be called // before we send system message of transfer complete @@ -579,6 +580,34 @@ BluetoothOppManager::AfterOppDisconnected() } } +void +BluetoothOppManager::RecoverFileName() +{ + // Remove the trailing ".part" file name from mDsFile by two steps + // 1. mDsFile->SetPath() so that the notification sent to Gaia will carry + // correct information of the file. + // 2. mDsFile->mFile->RenameTo() so that the file name would actually be + // changed in file system. + if (mDsFile && mDsFile->mFile) { + nsString path; + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + + mDsFile->SetPath(path); + mDsFile->mFile->RenameTo(nullptr, mFileName); + } +} + +void +BluetoothOppManager::DeleteDummyFile() +{ + // Remove the empty temp file + if (mDummyDsFile && mDummyDsFile->mFile) { + mDummyDsFile->mFile->Remove(false); + mDummyDsFile = nullptr; + } +} + void BluetoothOppManager::DeleteReceivedFile() { @@ -591,6 +620,8 @@ BluetoothOppManager::DeleteReceivedFile() mDsFile->mFile->Remove(false); mDsFile = nullptr; } + + DeleteDummyFile(); } bool @@ -598,25 +629,39 @@ BluetoothOppManager::CreateFile() { MOZ_ASSERT(mPutPacketReceivedLength == mPacketLength); + // Create one dummy file to be a placeholder for the target file name, and + // create another file with a meaningless file extension to write the received + // data. By doing this, we can prevent applications from parsing incomplete + // data in the middle of the receiving process. nsString path; path.AssignLiteral(TARGET_SUBDIR); path.Append(mFileName); - mDsFile = DeviceStorageFile::CreateUnique( - path, nsIFile::NORMAL_FILE_TYPE, 0644); + // Use an empty dummy file object to occupy the file name, so that after the + // whole file has been received successfully by using mDsFile, we could just + // remove mDummyDsFile and rename mDsFile to the file name of mDummyDsFile. + mDummyDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_TRUE(mDummyDsFile, false); + + // The function CreateUnique() may create a file with a different file + // name from the original mFileName. Therefore we have to retrieve + // the file name again. + mDummyDsFile->mFile->GetLeafName(mFileName); + + BT_LOGR("mFileName: %s", NS_ConvertUTF16toUTF8(mFileName).get()); + + // Prepare the entire file path for the .part file + path.Truncate(); + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + path.AppendLiteral(".part"); + + mDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); NS_ENSURE_TRUE(mDsFile, false); - nsCOMPtr f; - mDsFile->mFile->Clone(getter_AddRefs(f)); - - /* - * The function CreateUnique() may create a file with a different file - * name from the original mFileName. Therefore we have to retrieve - * the file name again. - */ - f->GetLeafName(mFileName); - - NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f); + NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), mDsFile->mFile); NS_ENSURE_TRUE(mOutputStream, false); return true; @@ -932,6 +977,10 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage) // Success to receive a file and notify completion if (mPutFinalFlag) { mSuccessFlag = true; + + DeleteDummyFile(); + RecoverFileName(); + FileTransferComplete(); NotifyAboutFileChange(); } diff --git a/dom/bluetooth2/bluez/BluetoothOppManager.h b/dom/bluetooth2/bluez/BluetoothOppManager.h index d6e7bf6daa5..6d21d144eca 100644 --- a/dom/bluetooth2/bluez/BluetoothOppManager.h +++ b/dom/bluetooth2/bluez/BluetoothOppManager.h @@ -85,6 +85,8 @@ private: void ReceivingFileConfirmation(); bool CreateFile(); bool WriteToFile(const uint8_t* aData, int aDataLength); + void RecoverFileName(); + void DeleteDummyFile(); void DeleteReceivedFile(); void ReplyToConnect(); void ReplyToDisconnectOrAbort(); @@ -209,6 +211,7 @@ private: nsCOMPtr mInputStream; nsCOMPtr mMountLock; nsRefPtr mDsFile; + nsRefPtr mDummyDsFile; // If a connection has been established, mSocket will be the socket // communicating with the remote socket. We maintain the invariant that if From ed3b797ccecf8152d6de3a697435ce9415a1ecfe Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Mon, 10 Nov 2014 18:55:50 +0800 Subject: [PATCH 54/71] Bug 1079649: Use a temporary (.part) file to store incoming file. (bluetooth2/bluedroid) r=btian --- .../bluedroid/BluetoothOppManager.cpp | 75 +++++++++++++++---- .../bluedroid/BluetoothOppManager.h | 3 + 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/dom/bluetooth2/bluedroid/BluetoothOppManager.cpp b/dom/bluetooth2/bluedroid/BluetoothOppManager.cpp index 555a9e9b1d2..ae7d25de7d3 100644 --- a/dom/bluetooth2/bluedroid/BluetoothOppManager.cpp +++ b/dom/bluetooth2/bluedroid/BluetoothOppManager.cpp @@ -531,6 +531,7 @@ BluetoothOppManager::AfterOppDisconnected() mLastCommand = 0; mPutPacketReceivedLength = 0; mDsFile = nullptr; + mDummyDsFile = nullptr; // We can't reset mSuccessFlag here since this function may be called // before we send system message of transfer complete @@ -557,6 +558,34 @@ BluetoothOppManager::AfterOppDisconnected() } } +void +BluetoothOppManager::RecoverFileName() +{ + // Remove the trailing ".part" file name from mDsFile by two steps + // 1. mDsFile->SetPath() so that the notification sent to Gaia will carry + // correct information of the file. + // 2. mDsFile->mFile->RenameTo() so that the file name would actually be + // changed in file system. + if (mDsFile && mDsFile->mFile) { + nsString path; + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + + mDsFile->SetPath(path); + mDsFile->mFile->RenameTo(nullptr, mFileName); + } +} + +void +BluetoothOppManager::DeleteDummyFile() +{ + // Remove the empty temp file + if (mDummyDsFile && mDummyDsFile->mFile) { + mDummyDsFile->mFile->Remove(false); + mDummyDsFile = nullptr; + } +} + void BluetoothOppManager::DeleteReceivedFile() { @@ -569,6 +598,8 @@ BluetoothOppManager::DeleteReceivedFile() mDsFile->mFile->Remove(false); mDsFile = nullptr; } + + DeleteDummyFile(); } bool @@ -576,25 +607,39 @@ BluetoothOppManager::CreateFile() { MOZ_ASSERT(mPutPacketReceivedLength == mPacketLength); + // Create one dummy file to be a placeholder for the target file name, and + // create another file with a meaningless file extension to write the received + // data. By doing this, we can prevent applications from parsing incomplete + // data in the middle of the receiving process. nsString path; path.AssignLiteral(TARGET_SUBDIR); path.Append(mFileName); - mDsFile = DeviceStorageFile::CreateUnique( - path, nsIFile::NORMAL_FILE_TYPE, 0644); + // Use an empty dummy file object to occupy the file name, so that after the + // whole file has been received successfully by using mDsFile, we could just + // remove mDummyDsFile and rename mDsFile to the file name of mDummyDsFile. + mDummyDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_TRUE(mDummyDsFile, false); + + // The function CreateUnique() may create a file with a different file + // name from the original mFileName. Therefore we have to retrieve + // the file name again. + mDummyDsFile->mFile->GetLeafName(mFileName); + + BT_LOGR("mFileName: %s", NS_ConvertUTF16toUTF8(mFileName).get()); + + // Prepare the entire file path for the .part file + path.Truncate(); + path.AssignLiteral(TARGET_SUBDIR); + path.Append(mFileName); + path.AppendLiteral(".part"); + + mDsFile = + DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644); NS_ENSURE_TRUE(mDsFile, false); - nsCOMPtr f; - mDsFile->mFile->Clone(getter_AddRefs(f)); - - /* - * The function CreateUnique() may create a file with a different file - * name from the original mFileName. Therefore we have to retrieve - * the file name again. - */ - f->GetLeafName(mFileName); - - NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f); + NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), mDsFile->mFile); NS_ENSURE_TRUE(mOutputStream, false); return true; @@ -911,6 +956,10 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage) // Success to receive a file and notify completion if (mPutFinalFlag) { mSuccessFlag = true; + + DeleteDummyFile(); + RecoverFileName(); + FileTransferComplete(); NotifyAboutFileChange(); } diff --git a/dom/bluetooth2/bluedroid/BluetoothOppManager.h b/dom/bluetooth2/bluedroid/BluetoothOppManager.h index fbfda2f294c..c751a17af5c 100644 --- a/dom/bluetooth2/bluedroid/BluetoothOppManager.h +++ b/dom/bluetooth2/bluedroid/BluetoothOppManager.h @@ -85,6 +85,8 @@ private: void ReceivingFileConfirmation(); bool CreateFile(); bool WriteToFile(const uint8_t* aData, int aDataLength); + void RecoverFileName(); + void DeleteDummyFile(); void DeleteReceivedFile(); void ReplyToConnect(); void ReplyToDisconnectOrAbort(); @@ -209,6 +211,7 @@ private: nsCOMPtr mInputStream; nsCOMPtr mMountLock; nsRefPtr mDsFile; + nsRefPtr mDummyDsFile; // If a connection has been established, mSocket will be the socket // communicating with the remote socket. We maintain the invariant that if From d457f5025048b5e5d3a9ffeb2860021312ee585e Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 22:16:00 -0800 Subject: [PATCH 55/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/0b567433bbdb Author: Greg Weng Desc: Merge pull request #26012 from snowmantw/bug1093424 Bug 1093424 - passcode entry on lockscreen no longer has delete key (jus... ======== https://hg.mozilla.org/integration/gaia-central/rev/c6f33a86622d Author: Greg Weng Desc: Bug 1093424 - passcode entry on lockscreen no longer has delete key (just Cancel) after entering one character --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ae6658e4278..7cc7a37c129 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "9a1b8914d3acc6d7eab18779b9a8e4b0a3fc52ea", + "revision": "0b567433bbdba511c50dea07497259f00ad4a483", "repo_path": "integration/gaia-central" } From f73f46779a25c998bd9b60a156f7a5c1bd2c8168 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 22:21:54 -0800 Subject: [PATCH 56/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 013a9f2c853..447a50a7ef6 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 685c4aa938c..000ea11ad20 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 9e5f9c9e76e..e64225f7d63 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index fadb088116b..7ee92c63916 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 685c4aa938c..000ea11ad20 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 6008a6351f8..01141e6d924 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 6e787ffa9ad..eac6b8d9cab 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 39047b7b2c5..b74067b6cff 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 66ffaf757db..e1c890cf0fa 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 6a7730e651b..a08659dfcad 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 6bc22d04da6..bf025458598 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 6fb4b9b1ea97c2d8fb6dc41a3f661d60bb04449f Mon Sep 17 00:00:00 2001 From: Yoshi Huang Date: Mon, 10 Nov 2014 18:58:03 +0800 Subject: [PATCH 57/71] Bug 1096230 - remove nfc-powerlevel-change system message. r=dimi From eaeb816ad7d11e9ee4434ad0d7d2eacc29264d3e Mon Sep 17 00:00:00 2001 --- dom/messages/SystemMessagePermissionsChecker.jsm | 3 --- 1 file changed, 3 deletions(-) --- dom/messages/SystemMessagePermissionsChecker.jsm | 3 --- 1 file changed, 3 deletions(-) diff --git a/dom/messages/SystemMessagePermissionsChecker.jsm b/dom/messages/SystemMessagePermissionsChecker.jsm index dfc18adbf23..eec8ba58909 100644 --- a/dom/messages/SystemMessagePermissionsChecker.jsm +++ b/dom/messages/SystemMessagePermissionsChecker.jsm @@ -123,9 +123,6 @@ this.SystemMessagePermissionsTable = { "nfc-manager-send-file": { "nfc-manager": [] }, - "nfc-powerlevel-change": { - "settings": ["read", "write"] - }, "wifip2p-pairing-request": { }, "first-run-with-sim": { "settings": ["read", "write"] From ef05c06bd34a0f38500f18c295c24952421f99f2 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Tue, 11 Nov 2014 08:14:42 +0100 Subject: [PATCH 58/71] Backed out changeset a263c8cfb04f (bug 1083004) for m5 test failures --- layout/base/nsCSSFrameConstructor.cpp | 57 +++------------------------ layout/base/nsCSSFrameConstructor.h | 15 ++----- 2 files changed, 10 insertions(+), 62 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 822f650a594..322af2dc809 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -2282,8 +2282,8 @@ NeedFrameFor(const nsFrameConstructorState& aState, // should be considered ignorable just because they evaluate to // whitespace. - // We could handle all this in CreateNeededPseudoContainers or some other - // place after we build our frame construction items, but that would involve + // We could handle all this in CreateNeededPseudos or some other place + // after we build our frame construction items, but that would involve // creating frame construction items for whitespace kids of // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them // all anyway, and involve an extra walk down the frame construction item @@ -9347,10 +9347,9 @@ nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems( * contain only items for frames that can be direct kids of aParentFrame. */ void -nsCSSFrameConstructor::CreateNeededPseudoContainers( - nsFrameConstructorState& aState, - FrameConstructionItemList& aItems, - nsIFrame* aParentFrame) +nsCSSFrameConstructor::CreateNeededPseudos(nsFrameConstructorState& aState, + FrameConstructionItemList& aItems, + nsIFrame* aParentFrame) { ParentType ourParentType = GetParentType(aParentFrame); if (aItems.AllWantParentType(ourParentType)) { @@ -9623,58 +9622,14 @@ nsCSSFrameConstructor::CreateNeededPseudoContainers( } while (!iter.IsDone()); } -void nsCSSFrameConstructor::CreateNeededPseudoSiblings( - nsFrameConstructorState& aState, - FrameConstructionItemList& aItems, - nsIFrame* aParentFrame) -{ - if (aItems.IsEmpty() || - GetParentType(aParentFrame) != eTypeRuby) { - return; - } - - FCItemIterator iter(aItems); - // XXX Use computed display value instead in bug 1096639. - auto creationFunc = reinterpret_cast( - iter.item().mFCData->mFunc.mCreationFunc); - if (creationFunc == NS_NewRubyBaseContainerFrame) { - return; - } - - NS_ASSERTION(creationFunc == NS_NewRubyTextContainerFrame, - "Child of ruby frame should either a rbc or a rtc"); - - const PseudoParentData& pseudoData = - sPseudoParentData[eTypeRubyBaseContainer]; - already_AddRefed pseudoStyle = mPresShell->StyleSet()-> - ResolveAnonymousBoxStyle(*pseudoData.mPseudoType, - aParentFrame->StyleContext()); - FrameConstructionItem* newItem = - new FrameConstructionItem(&pseudoData.mFCData, - // Use the content of the parent frame - aParentFrame->GetContent(), - // Tag type - *pseudoData.mPseudoType, - // Use the namespace of the rtc frame - iter.item().mNameSpaceID, - // no pending binding - nullptr, - pseudoStyle, - true, nullptr); - newItem->mIsAllInline = true; - newItem->mChildItems.SetParentHasNoXBLChildren(true); - iter.InsertItem(newItem); -} - inline void nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState, FrameConstructionItemList& aItems, nsContainerFrame* aParentFrame, nsFrameItems& aFrameItems) { - CreateNeededPseudoContainers(aState, aItems, aParentFrame); + CreateNeededPseudos(aState, aItems, aParentFrame); CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame); - CreateNeededPseudoSiblings(aState, aItems, aParentFrame); aItems.SetTriedConstructingFrames(); for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) { diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index cad3d664965..0cc1a3399de 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -1097,20 +1097,13 @@ private: nsIFrame* aParentFrame); /** - * Function to create the pseudo intermediate containers we need. + * Function to create the table pseudo items we need. * @param aItems the child frame construction items before pseudo creation * @param aParentFrame the parent frame we're creating pseudos for */ - inline void CreateNeededPseudoContainers(nsFrameConstructorState& aState, - FrameConstructionItemList& aItems, - nsIFrame* aParentFrame); - - /** - * Function to create the pseudo siblings we need. - */ - inline void CreateNeededPseudoSiblings(nsFrameConstructorState& aState, - FrameConstructionItemList& aItems, - nsIFrame* aParentFrame); + inline void CreateNeededPseudos(nsFrameConstructorState& aState, + FrameConstructionItemList& aItems, + nsIFrame* aParentFrame); /** * Function to adjust aParentFrame to deal with captions. From cdadb281c2b458ce2ab9db8437ea1a663ca22146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eddy=20Bru=C3=ABl?= Date: Mon, 10 Nov 2014 16:27:21 +0100 Subject: [PATCH 59/71] Bug 1090929 - Enable the variables-view tests;r=mratcliffe --- browser/devtools/debugger/test/browser.ini | 12 ++++++------ .../debugger/test/browser_dbg_variables-view-01.js | 2 +- .../debugger/test/browser_dbg_variables-view-02.js | 2 +- .../debugger/test/browser_dbg_variables-view-03.js | 2 +- .../debugger/test/browser_dbg_variables-view-04.js | 2 +- .../debugger/test/browser_dbg_variables-view-05.js | 2 +- .../debugger/test/browser_dbg_variables-view-06.js | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/browser/devtools/debugger/test/browser.ini b/browser/devtools/debugger/test/browser.ini index 9846c7c97cd..7b3e721b3ff 100644 --- a/browser/devtools/debugger/test/browser.ini +++ b/browser/devtools/debugger/test/browser.ini @@ -446,17 +446,17 @@ skip-if = e10s [browser_dbg_tracing-08.js] skip-if = e10s [browser_dbg_variables-view-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-05.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-06.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-accessibility.js] skip-if = e10s [browser_dbg_variables-view-data.js] diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-01.js b/browser/devtools/debugger/test/browser_dbg_variables-view-01.js index 48d7d255378..a3591eb935d 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-01.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-01.js @@ -9,7 +9,7 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let variables = aPanel.panelWin.DebuggerView.Variables; let testScope = variables.addScope("test"); diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-02.js b/browser/devtools/debugger/test/browser_dbg_variables-view-02.js index 57b14df08e0..438b07a0f86 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-02.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-02.js @@ -9,7 +9,7 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let variables = aPanel.panelWin.DebuggerView.Variables; let testScope = variables.addScope("test"); let testVar = testScope.addItem("something"); diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-03.js b/browser/devtools/debugger/test/browser_dbg_variables-view-03.js index 9e0fe8c102a..4a591ad9690 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-03.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-03.js @@ -9,7 +9,7 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let variables = aPanel.panelWin.DebuggerView.Variables; let testScope = variables.addScope("test"); diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-04.js b/browser/devtools/debugger/test/browser_dbg_variables-view-04.js index 74684250111..1ad4ff10f1e 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-04.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-04.js @@ -8,7 +8,7 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let variables = aPanel.panelWin.DebuggerView.Variables; let testScope = variables.addScope("test"); let testVar = testScope.addItem("something"); diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-05.js b/browser/devtools/debugger/test/browser_dbg_variables-view-05.js index 4f64e49375a..71c857fb68b 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-05.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-05.js @@ -8,7 +8,7 @@ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { let variables = aPanel.panelWin.DebuggerView.Variables; let globalScope = variables.addScope("Test-Global"); diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-06.js b/browser/devtools/debugger/test/browser_dbg_variables-view-06.js index f4034ab3d1c..fa6901d081b 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-06.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-06.js @@ -8,11 +8,11 @@ const TAB_URL = EXAMPLE_URL + "doc_promise.html"; const test = Task.async(function* () { - const [tab, debuggee, panel] = yield initDebugger(TAB_URL); + const [tab,, panel] = yield initDebugger(TAB_URL); yield ensureSourceIs(panel, "doc_promise.html", true); const scopes = waitForCaretAndScopes(panel, 21); - executeSoon(debuggee.doPause); + callInTab(tab, "doPause"); yield scopes; const variables = panel.panelWin.DebuggerView.Variables; From 0309028bf340388c6f438ee95f9bf050999c3044 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 22:45:59 -0800 Subject: [PATCH 60/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a582621c2232 Author: Min-Zhong "John" Lu Desc: Merge pull request #25980 from mnjul/bug_1094122_layout_not_remembered Bug 1094122 - Do not save activeLayout to settings if setKeyboardToShow is called with launchOnly=true. r=rudyl ======== https://hg.mozilla.org/integration/gaia-central/rev/22bba8090a51 Author: John Lu [:mnjul] Desc: Bug 1094122 - Do not save activeLayout to settings if setKeyboardToShow is called with launchOnly=true --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7cc7a37c129..3b2c3d6eb9f 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "0b567433bbdba511c50dea07497259f00ad4a483", + "revision": "a582621c22327b67c263208686a50524d72bf129", "repo_path": "integration/gaia-central" } From dc121908c88deac3bdd3c2470007c2d06cf505a3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 22:51:52 -0800 Subject: [PATCH 61/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 447a50a7ef6..01f9a96a11f 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 000ea11ad20..6b02e94b3f6 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e64225f7d63..366c8f92fb5 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7ee92c63916..4da67ec8fda 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 000ea11ad20..6b02e94b3f6 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 01141e6d924..7a070e4a06c 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index eac6b8d9cab..44b48399259 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index b74067b6cff..0bbe02b2ef4 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e1c890cf0fa..252d88ecddd 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index a08659dfcad..0a73026e401 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index bf025458598..ab559cca86e 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From b80efa5ac1819e9ea9e8db975d36a2552773598d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 23:20:53 -0800 Subject: [PATCH 62/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/57ca61c5a07e Author: chirarobert Desc: Merge pull request #25583 from viorelaioia/bug-1087383 Bug 1087383 - Add a test that sets the wallpaper from Gallery, by long p... ======== https://hg.mozilla.org/integration/gaia-central/rev/84eebc0ac8ed Author: Viorela Ioia Desc: Bug 1087383 - Add a test that sets the wallpaper from Gallery, by long press on the screen --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 3b2c3d6eb9f..d067eda4c55 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "a582621c22327b67c263208686a50524d72bf129", + "revision": "57ca61c5a07ecafadf699a9f531207921662ea70", "repo_path": "integration/gaia-central" } From fd8cb28861f54ea40e80bcc196558a7e2f9f73e7 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 23:27:17 -0800 Subject: [PATCH 63/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 01f9a96a11f..68e41ac25c5 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 6b02e94b3f6..b81c7995c3c 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 366c8f92fb5..cc0f2742d19 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 4da67ec8fda..2238f527fdf 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 6b02e94b3f6..b81c7995c3c 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 7a070e4a06c..810dd6e7052 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 44b48399259..7d5aa03bcbe 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 0bbe02b2ef4..819adcff784 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 252d88ecddd..e1f4d6aea20 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 0a73026e401..f938f4bb150 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index ab559cca86e..80b23373b7b 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From b5b8ee9b36dd82a6c51edd48c2b21716ae7248dd Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Mon, 10 Nov 2014 23:30:07 -0800 Subject: [PATCH 64/71] Bug 1095801 - Make adb work properly on user builds (Nexus 4/5). r=fabrice --- b2g/chrome/content/devtools/adb.js | 14 ++++++++++++-- dom/system/gonk/AutoMounter.cpp | 12 ++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/b2g/chrome/content/devtools/adb.js b/b2g/chrome/content/devtools/adb.js index 6e6f4cda20d..6745ea32c3e 100644 --- a/b2g/chrome/content/devtools/adb.js +++ b/b2g/chrome/content/devtools/adb.js @@ -100,11 +100,11 @@ let AdbController = { return; } let storage = this.storages[storageIndex]; - DEBUG && debug("Checking availability of storage: '" + storage.storageName); + DEBUG && debug("Checking availability of storage: '" + storage.storageName + "'"); let req = storage.available(); req.onsuccess = function(e) { - DEBUG && debug("Storage: '" + storage.storageName + "' is '" + e.target.result); + DEBUG && debug("Storage: '" + storage.storageName + "' is '" + e.target.result + "'"); if (e.target.result == 'shared') { // We've found a storage area that's being shared with the PC. // We can stop looking now. @@ -216,6 +216,11 @@ let AdbController = { // Configure adb. let currentConfig = libcutils.property_get("persist.sys.usb.config"); let configFuncs = currentConfig.split(","); + if (currentConfig == "" || currentConfig == "none") { + // We want to treat none like the empty string. + // "".split(",") yields [""] and not [] + configFuncs = []; + } let adbIndex = configFuncs.indexOf("adb"); if (enableAdb) { @@ -230,6 +235,11 @@ let AdbController = { } } let newConfig = configFuncs.join(","); + if (newConfig == "") { + // Convert the empty string back into none, since that's what init.rc + // needs. + newConfig = "none"; + } if (newConfig != currentConfig) { DEBUG && debug("updateState: currentConfig = " + currentConfig); DEBUG && debug("updateState: newConfig = " + newConfig); diff --git a/dom/system/gonk/AutoMounter.cpp b/dom/system/gonk/AutoMounter.cpp index dc9190ba3da..8de27daabe5 100644 --- a/dom/system/gonk/AutoMounter.cpp +++ b/dom/system/gonk/AutoMounter.cpp @@ -102,6 +102,7 @@ namespace system { #define USB_FUNC_ADB "adb" #define USB_FUNC_MTP "mtp" +#define USB_FUNC_NONE "none" #define USB_FUNC_RNDIS "rndis" #define USB_FUNC_UMS "mass_storage" @@ -528,6 +529,13 @@ SetUsbFunction(const char* aUsbFunc) char oldSysUsbConfig[PROPERTY_VALUE_MAX]; property_get(SYS_USB_CONFIG, oldSysUsbConfig, ""); + if (strcmp(oldSysUsbConfig, USB_FUNC_NONE) == 0) { + // It's quite possible that sys.usb.config may have the value "none". We + // convert that to an empty string here, and at the end we convert the + // empty string back to "none". + oldSysUsbConfig[0] = '\0'; + } + if (IsUsbFunctionEnabled(oldSysUsbConfig, aUsbFunc)) { // The function is already configured. Nothing else to do. DBG("SetUsbFunction('%s') - already set - nothing to do", aUsbFunc); @@ -583,6 +591,10 @@ SetUsbFunction(const char* aUsbFunc) return; } + if (newSysUsbConfig[0] == '\0') { + // Convert the empty string back to the string "none" + strlcpy(newSysUsbConfig, USB_FUNC_NONE, sizeof(newSysUsbConfig)); + } LOG("SetUsbFunction(%s) %s from '%s' to '%s'", aUsbFunc, SYS_USB_CONFIG, oldSysUsbConfig, newSysUsbConfig); property_set(SYS_USB_CONFIG, newSysUsbConfig); From a3428d01c4dac518e00251c73f5fbf0303f1465c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 23:35:58 -0800 Subject: [PATCH 65/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/e5ebfb4ea072 Author: Greg Weng Desc: Merge pull request #25983 from snowmantw/bug1089529 Bug 1089529 - Lockscreen error after screen off and on when device shows... ======== https://hg.mozilla.org/integration/gaia-central/rev/ad34c949c64d Author: Greg Weng Desc: Bug 1089529 - Lockscreen error after screen off and on when device shows NFC shrinking UI --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d067eda4c55..903d78196aa 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "57ca61c5a07ecafadf699a9f531207921662ea70", + "revision": "e5ebfb4ea0728adab52c12a46b587da949ce88dd", "repo_path": "integration/gaia-central" } From 1269a23871b8a4a8dd4280350c10e5fb0cf2af2c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 10 Nov 2014 23:41:52 -0800 Subject: [PATCH 66/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 68e41ac25c5..bc2bfc008cb 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b81c7995c3c..5e34eb111e8 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index cc0f2742d19..7e239bd2f5a 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 2238f527fdf..a650bd03805 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b81c7995c3c..5e34eb111e8 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 810dd6e7052..a679e79508e 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 7d5aa03bcbe..19cb6eba007 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 819adcff784..2a71692f8bf 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e1f4d6aea20..40febd7bdd0 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index f938f4bb150..4c7b1b26e4a 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 80b23373b7b..0bcdf5c2bdc 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 32b70f07960f0fd65e279f7da28d383a210f3d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eddy=20Bru=C3=ABl?= Date: Tue, 11 Nov 2014 08:44:27 +0100 Subject: [PATCH 67/71] Bug 1090929 - Enable the tracer tests;r=mratcliffe --- browser/devtools/debugger/test/browser.ini | 16 ++++++++-------- .../debugger/test/browser_dbg_tracing-01.js | 10 +++------- .../debugger/test/browser_dbg_tracing-02.js | 10 +++------- .../debugger/test/browser_dbg_tracing-03.js | 10 +++------- .../debugger/test/browser_dbg_tracing-04.js | 10 +++------- .../debugger/test/browser_dbg_tracing-05.js | 10 +++------- .../debugger/test/browser_dbg_tracing-06.js | 6 ++---- .../debugger/test/browser_dbg_tracing-07.js | 9 +++------ 8 files changed, 28 insertions(+), 53 deletions(-) diff --git a/browser/devtools/debugger/test/browser.ini b/browser/devtools/debugger/test/browser.ini index 7b3e721b3ff..33cca74280b 100644 --- a/browser/devtools/debugger/test/browser.ini +++ b/browser/devtools/debugger/test/browser.ini @@ -430,21 +430,21 @@ skip-if = e10s [browser_dbg_terminate-on-tab-close.js] skip-if = e10s [browser_dbg_tracing-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-05.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-06.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-07.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_tracing-08.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-01.js] skip-if = e10s && debug [browser_dbg_variables-view-02.js] diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-01.js b/browser/devtools/debugger/test/browser_dbg_tracing-01.js index 3b0262cf95c..116173621dc 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-01.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-01.js @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { SpecialPowers.pushPrefEnv({'set': [["devtools.debugger.tracer", true]]}, () => { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -37,9 +36,7 @@ function test() { } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function testTraceLogs() { @@ -103,7 +100,6 @@ function testTraceLogs() { registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-02.js b/browser/devtools/debugger/test/browser_dbg_tracing-02.js index e931974a078..eb55db1610c 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-02.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-02.js @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { SpecialPowers.pushPrefEnv({'set': [["devtools.debugger.tracer", true]]}, () => { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -40,9 +39,7 @@ function test() { } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function highlightCall() { @@ -72,7 +69,6 @@ function testNoneHighlighted() { registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-03.js b/browser/devtools/debugger/test/browser_dbg_tracing-03.js index 7835d0d4310..99cb641a037 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-03.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-03.js @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { SpecialPowers.pushPrefEnv({'set': [["devtools.debugger.tracer", true]]}, () => { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -48,9 +47,7 @@ function test() { } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function clickTraceLog() { @@ -64,7 +61,6 @@ function testCorrectLine() { registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-04.js b/browser/devtools/debugger/test/browser_dbg_tracing-04.js index b6cb7526571..c5976c6cb2c 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-04.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-04.js @@ -7,13 +7,12 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; function test() { SpecialPowers.pushPrefEnv({'set': [["devtools.debugger.tracer", true]]}, () => { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -41,9 +40,7 @@ function test() { } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function clickTraceCall() { @@ -78,7 +75,6 @@ function testReturn() { registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; }); diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-05.js b/browser/devtools/debugger/test/browser_dbg_tracing-05.js index b0e3a3664e5..a51cc0ae111 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-05.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-05.js @@ -7,14 +7,13 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gTracer, gL10N; function test() { SpecialPowers.pushPrefEnv({'set': [["devtools.debugger.tracer", true]]}, () => { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; gTracer = gDebugger.DebuggerView.Tracer; @@ -70,14 +69,11 @@ function testNoEmptyText() { } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; gTracer = null; diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-06.js b/browser/devtools/debugger/test/browser_dbg_tracing-06.js index db46b581c4b..f1f836ef38a 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-06.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-06.js @@ -8,14 +8,13 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; const TRACER_PREF = "devtools.debugger.tracer"; -let gTab, gDebuggee, gPanel, gDebugger; +let gTab, gPanel, gDebugger; let gOriginalPref = Services.prefs.getBoolPref(TRACER_PREF); Services.prefs.setBoolPref(TRACER_PREF, false); function test() { - initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + initDebugger(TAB_URL).then(([aTab,, aPanel]) => { gTab = aTab; - gDebuggee = aDebuggee; gPanel = aPanel; gDebugger = gPanel.panelWin; @@ -32,7 +31,6 @@ function test() { registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; gDebugger = null; Services.prefs.setBoolPref(TRACER_PREF, gOriginalPref); diff --git a/browser/devtools/debugger/test/browser_dbg_tracing-07.js b/browser/devtools/debugger/test/browser_dbg_tracing-07.js index e8d94369494..4aaba2c41b5 100644 --- a/browser/devtools/debugger/test/browser_dbg_tracing-07.js +++ b/browser/devtools/debugger/test/browser_dbg_tracing-07.js @@ -8,13 +8,13 @@ const TAB_URL = EXAMPLE_URL + "doc_tracing-01.html"; -let gTab, gDebuggee, gPanel; +let gTab, gPanel; function test() { Task.async(function*() { yield pushPref(); - [gTab, gDebuggee, gPanel] = yield initDebugger(TAB_URL); + [gTab,, gPanel] = yield initDebugger(TAB_URL); yield startTracing(gPanel); yield clickButton(); @@ -60,9 +60,7 @@ function test() { } function clickButton() { - EventUtils.sendMouseEvent({ type: "click" }, - gDebuggee.document.querySelector("button"), - gDebuggee); + sendMouseClickToTab(gTab, content.document.querySelector("button")); } function pushPref() { @@ -80,7 +78,6 @@ function popPref() { registerCleanupFunction(function() { gTab = null; - gDebuggee = null; gPanel = null; }); From 254a1bddefe3b41c98e257f0ab4023ba6199591d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 11 Nov 2014 00:05:55 -0800 Subject: [PATCH 68/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/44c7a6b1b677 Author: Rex KM Lee Desc: Merge pull request #26000 from rexboy7/1095325-homeactivity bug 1096231 - [Stingray][smart-home]Prevent src hash from blocking activity. r=johnhu ======== https://hg.mozilla.org/integration/gaia-central/rev/9d8382923121 Author: Rex Lee Desc: bug 1096231 - [Stingray][smart-home]Prevent src hash from blocking activity/system message --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 903d78196aa..7220903ab02 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "e5ebfb4ea0728adab52c12a46b587da949ce88dd", + "revision": "44c7a6b1b677d3080142e0c13ecd368c3106eca2", "repo_path": "integration/gaia-central" } From 73a4cf0ca87ad61e0771129c0e6a7d69fdac6936 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 11 Nov 2014 00:12:22 -0800 Subject: [PATCH 69/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index bc2bfc008cb..24e4907f3c3 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 5e34eb111e8..baf6620fb08 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 7e239bd2f5a..ecfa410f465 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index a650bd03805..46fa5ae63dd 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 5e34eb111e8..baf6620fb08 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index a679e79508e..42980291430 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 19cb6eba007..1b671f2bc46 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 2a71692f8bf..85f7a4de6d0 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 40febd7bdd0..8aa2c0e23bd 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 4c7b1b26e4a..adfb37daa49 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 0bcdf5c2bdc..3b7d713bcf6 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 890cfdaded944a856c747f9f88d9df32756c8010 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 11 Nov 2014 00:35:55 -0800 Subject: [PATCH 70/71] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a7c053f5e582 Author: EragonJ (E.J.) Desc: Merge pull request #26011 from EragonJ/bug-1096737 Bug 1096737 - [Settings] All unit tests of settings app are not running ======== https://hg.mozilla.org/integration/gaia-central/rev/c49ba17a9061 Author: EragonJ Desc: Bug 1096737 - [Settings] All unit tests of settings app are not running --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7220903ab02..98ee3b709c2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "44c7a6b1b677d3080142e0c13ecd368c3106eca2", + "revision": "a7c053f5e582c15255c49645b07a19d72e4e5cb2", "repo_path": "integration/gaia-central" } From 481ed5c67c24e35b35748fddbd37ea5032344029 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 11 Nov 2014 00:42:19 -0800 Subject: [PATCH 71/71] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 24e4907f3c3..c083f679f9c 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index baf6620fb08..c8b8ed5e895 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index ecfa410f465..2945d951520 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 46fa5ae63dd..2a90dd94670 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index baf6620fb08..c8b8ed5e895 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 42980291430..3612bdf9b26 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 1b671f2bc46..56b23553292 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 85f7a4de6d0..accb2aecaf1 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 8aa2c0e23bd..ba953f0c49f 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index adfb37daa49..bbaedcc67c4 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 3b7d713bcf6..4e564eb7127 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - +