author | Ryan VanderMeulen <ryanvm@gmail.com> |
Tue, 15 Apr 2014 23:26:35 -0400 | |
changeset 197225 | dd50745d7f35796adf7b037c2e60c3f6809a7347 |
parent 197142 | 26209c17215041ecee2d7542839553a9754bbee6 (current diff) |
parent 197224 | fcb4575e90d9bf72c7fd12a17e2423760ac61570 (diff) |
child 197245 | b73ad6f8bf2618b8e9b077e1839c3c30f4d1aae6 |
child 197269 | 025a433dd5eb133140b0ff7c46731d4c28c110b1 |
child 197289 | eb732605c93a2189df07b025df172a9356db2037 |
push id | 3624 |
push user | asasaki@mozilla.com |
push date | Mon, 09 Jun 2014 21:49:01 +0000 |
treeherder | mozilla-beta@b1a5da15899a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 31.0a1 |
first release with | nightly linux32
dd50745d7f35
/
31.0a1
/
20140416030202
/
files
nightly linux64
dd50745d7f35
/
31.0a1
/
20140416030202
/
files
nightly mac
dd50745d7f35
/
31.0a1
/
20140416030202
/
files
nightly win32
dd50745d7f35
/
31.0a1
/
20140416030202
/
files
nightly win64
dd50745d7f35
/
31.0a1
/
20140416030202
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
31.0a1
/
20140416030202
/
pushlog to previous
nightly linux64
31.0a1
/
20140416030202
/
pushlog to previous
nightly mac
31.0a1
/
20140416030202
/
pushlog to previous
nightly win32
31.0a1
/
20140416030202
/
pushlog to previous
nightly win64
31.0a1
/
20140416030202
/
pushlog to previous
|
--- a/accessible/src/jsat/Utils.jsm +++ b/accessible/src/jsat/Utils.jsm @@ -592,17 +592,17 @@ PivotContext.prototype = { */ _getAncestry: function _getAncestry(aAccessible) { let ancestry = []; let parent = aAccessible; try { while (parent && (parent = parent.parent)) { ancestry.push(parent); } - } catch (e) { + } catch (x) { // A defunct accessible will raise an exception geting parent. Logger.debug('Failed to get parent:', x); } return ancestry.reverse(); }, /** * A list of the old accessible's ancestry.
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -269,17 +269,16 @@ pref("editor.singleLine.pasteNewlines", pref("ui.dragThresholdX", 25); pref("ui.dragThresholdY", 25); // Layers Acceleration. We can only have nice things on gonk, because // they're not maintained anywhere else. pref("layers.offmainthreadcomposition.enabled", true); #ifndef MOZ_WIDGET_GONK pref("dom.ipc.tabs.disabled", true); -pref("layers.acceleration.disabled", true); pref("layers.offmainthreadcomposition.async-animations", false); pref("layers.async-video.enabled", false); #else pref("dom.ipc.tabs.disabled", false); pref("layers.acceleration.disabled", false); pref("layers.offmainthreadcomposition.async-animations", true); pref("layers.async-video.enabled", true); pref("layers.async-pan-zoom.enabled", true);
--- a/b2g/config/mozconfigs/macosx64_gecko/debug +++ b/b2g/config/mozconfigs/macosx64_gecko/debug @@ -1,8 +1,9 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" . $topsrcdir/build/macosx/mozconfig.common ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-signmar # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly +++ b/b2g/config/mozconfigs/macosx64_gecko/nightly @@ -1,8 +1,9 @@ +. "$topsrcdir/b2g/config/mozconfigs/common" . $topsrcdir/build/macosx/mozconfig.common ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-signmar # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics
--- a/browser/components/shell/src/nsWindowsShellService.cpp +++ b/browser/components/shell/src/nsWindowsShellService.cpp @@ -748,27 +748,29 @@ nsWindowsShellService::SetShouldCheckDef return prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck); } static nsresult WriteBitmap(nsIFile* aFile, imgIContainer* aImage) { nsresult rv; - nsRefPtr<gfxASurface> thebesSurface = + RefPtr<SourceSurface> surface = aImage->GetFrame(imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - nsRefPtr<gfxImageSurface> thebesImageSurface = - thebesSurface->GetAsReadableARGB32ImageSurface(); - NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE); + // For either of the following formats we want to set the biBitCount member + // of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap + // format defines that the A8/X8 WORDs in the bitmap byte stream be ignored + // for the BI_RGB value we use for the biCompression member. + MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 || + surface->GetFormat() == SurfaceFormat::B8G8R8X8); - RefPtr<DataSourceSurface> dataSurface = - thebesImageSurface->CopyToB8G8R8A8DataSourceSurface(); + RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface(); NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); int32_t width = dataSurface->GetSize().width; int32_t height = dataSurface->GetSize().height; int32_t bytesPerPixel = 4 * sizeof(uint8_t); uint32_t bytesPerRow = bytesPerPixel * width; // initialize these bitmap structs which we will later
--- a/content/base/src/moz.build +++ b/content/base/src/moz.build @@ -224,13 +224,14 @@ LOCAL_INCLUDES += [ '/js/xpconnect/src', '/js/xpconnect/wrappers', '/layout/base', '/layout/generic', '/layout/style', '/layout/svg', '/layout/xul', '/netwerk/base/src', + '/xpcom/ds', ] if CONFIG['GNU_CC'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': # Work around bug 986928 CXXFLAGS += ['-Wno-error=format']
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -119,16 +119,17 @@ #include "nsIImageLoadingContent.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIIOService.h" #include "nsIJSRuntimeService.h" #include "nsILineBreaker.h" #include "nsILoadContext.h" #include "nsILoadGroup.h" +#include "nsIMemoryReporter.h" #include "nsIMIMEService.h" #include "nsINode.h" #include "nsINodeInfo.h" #include "nsIObjectLoadingContent.h" #include "nsIObserver.h" #include "nsIObserverService.h" #include "nsIOfflineCacheUpdate.h" #include "nsIParser.h"
--- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -95,19 +95,21 @@ #include "nsGlobalWindow.h" #include "GLContext.h" #include "GLContextProvider.h" #include "SVGContentUtils.h" #include "nsIScreenManager.h" #undef free // apparently defined by some windows header, clashing with a free() // method in SkTypes.h +#ifdef USE_SKIA #include "SkiaGLGlue.h" #include "SurfaceStream.h" #include "SurfaceTypes.h" +#endif using mozilla::gl::GLContext; using mozilla::gl::SkiaGLGlue; using mozilla::gl::GLContextProvider; #ifdef XP_WIN #include "gfxWindowsPlatform.h" #endif @@ -895,25 +897,27 @@ CanvasRenderingContext2D::EnsureTarget() if (layerManager) { if (gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() && !mForceSoftware && CheckSizeForSkiaGL(size)) { DemoteOldestContextIfNecessary(); SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); +#if USE_SKIA if (glue && glue->GetGrContext() && glue->GetGLContext()) { mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format); if (mTarget) { mStream = gfx::SurfaceStream::CreateForType(SurfaceStreamType::TripleBuffer, glue->GetGLContext()); AddDemotableContext(this); } else { printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n"); } } +#endif if (!mTarget) { mTarget = layerManager->CreateDrawTarget(size, format); } } else mTarget = layerManager->CreateDrawTarget(size, format); } else { mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format); } @@ -4239,22 +4243,24 @@ CanvasRenderingContext2D::GetCanvasLayer if (!mResetLayer && aOldLayer) { CanvasRenderingContext2DUserData* userData = static_cast<CanvasRenderingContext2DUserData*>( aOldLayer->GetUserData(&g2DContextLayerUserData)); CanvasLayer::Data data; if (mStream) { +#ifdef USE_SKIA SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); if (glue) { data.mGLContext = glue->GetGLContext(); data.mStream = mStream.get(); } +#endif } else { data.mDrawTarget = mTarget; } if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) { nsRefPtr<CanvasLayer> ret = aOldLayer; return ret.forget(); } @@ -4287,17 +4293,19 @@ CanvasRenderingContext2D::GetCanvasLayer CanvasLayer::Data data; if (mStream) { SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); if (glue) { canvasLayer->SetPreTransactionCallback( CanvasRenderingContext2DUserData::PreTransactionCallback, userData); +#if USE_SKIA data.mGLContext = glue->GetGLContext(); +#endif data.mStream = mStream.get(); data.mTexID = (uint32_t)((uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE)); } } else { data.mDrawTarget = mTarget; } data.mSize = nsIntSize(mWidth, mHeight);
--- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -4669,34 +4669,25 @@ HTMLInputElement::GetValueAsDate(const n * -The day must be exactly 2 digit long, and 01 <= day <= maxday * Where maxday is the number of days in the month 'month' and year 'year' */ if (aValue.Length() < 10) { return false; } - uint32_t endOfYearOffset = 0; - for (; NS_IsAsciiDigit(aValue[endOfYearOffset]); ++endOfYearOffset); - - // The year must be at least 4 digits long. - if (aValue[endOfYearOffset] != '-' || endOfYearOffset < 4) { + uint32_t endOfYearOffset = aValue.Length() - 6; + + if (aValue[endOfYearOffset] != '-' || + aValue[endOfYearOffset + 3] != '-') { return false; } - // Now, we know where is the next '-' and what should be the size of the - // string. - if (aValue[endOfYearOffset + 3] != '-' || - aValue.Length() != 10 + (endOfYearOffset - 4)) { - return false; - } - - nsresult ec; - *aYear = PromiseFlatString(StringHead(aValue, endOfYearOffset)).ToInteger(&ec); - if (NS_FAILED(ec) || *aYear == 0) { + if (!DigitSubStringToNumber(aValue, 0, endOfYearOffset, aYear) || + *aYear < 1) { return false; } if (!DigitSubStringToNumber(aValue, endOfYearOffset + 1, 2, aMonth) || *aMonth < 1 || *aMonth > 12) { return false; }
--- a/content/media/Latency.h +++ b/content/media/Latency.h @@ -8,17 +8,17 @@ #define MOZILLA_LATENCY_H #include "mozilla/TimeStamp.h" #include "prlog.h" #include "nsCOMPtr.h" #include "nsIThread.h" #include "mozilla/Monitor.h" #include "nsISupportsImpl.h" -#include "nsObserverService.h" +#include "nsIObserver.h" class AsyncLatencyLogger; class LogEvent; PRLogModuleInfo* GetLatencyLog(); // This class is a singleton. It is refcounted. class AsyncLatencyLogger : public nsIObserver
--- a/content/media/MediaTaskQueue.h +++ b/content/media/MediaTaskQueue.h @@ -18,21 +18,23 @@ namespace mozilla { class SharedThreadPool; // Abstracts executing runnables in order in a thread pool. The runnables // dispatched to the MediaTaskQueue will be executed in the order in which // they're received, and are guaranteed to not be executed concurrently. // They may be executed on different threads, and a memory barrier is used // to make this threadsafe for objects that aren't already threadsafe. -class MediaTaskQueue : public AtomicRefCounted<MediaTaskQueue> { +class MediaTaskQueue MOZ_FINAL { + ~MediaTaskQueue(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaTaskQueue) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTaskQueue) + MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool); - ~MediaTaskQueue(); nsresult Dispatch(nsIRunnable* aRunnable); // Removes all pending tasks from the task queue, and blocks until // the currently running task (if any) finishes. void Flush(); // Blocks until all tasks finish executing, then shuts down the task queue
--- a/content/media/fmp4/PlatformDecoderModule.h +++ b/content/media/fmp4/PlatformDecoderModule.h @@ -138,20 +138,22 @@ public: // // All functions must be threadsafe, and be able to be called on an // arbitrary thread. // // Decoding is done asynchronously. Any async work can be done on the // MediaTaskQueue passed into the PlatformDecoderModules's Create*Decoder() // function. This may not be necessary for platforms with async APIs // for decoding. -class MediaDataDecoder : public AtomicRefCounted<MediaDataDecoder> { +class MediaDataDecoder { +protected: + virtual ~MediaDataDecoder() {}; + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaDataDecoder) - virtual ~MediaDataDecoder() {}; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDecoder) // Initialize the decoder. The decoder should be ready to decode after // this returns. The decoder should do any initialization here, rather // than in its constructor or PlatformDecoderModule::Create*Decoder(), // so that if the MP4Reader needs to shutdown during initialization, // it can call Shutdown() to cancel this operation. Any initialization // that requires blocking the calling thread in this function *must* // be done here so that it can be canceled by calling Shutdown()!
--- a/content/media/fmp4/wmf/MFTDecoder.h +++ b/content/media/fmp4/wmf/MFTDecoder.h @@ -9,21 +9,23 @@ #include "WMF.h" #include "mozilla/RefPtr.h" #include "mozilla/ReentrantMonitor.h" #include "nsIThread.h" namespace mozilla { -class MFTDecoder : public AtomicRefCounted<MFTDecoder> { +class MFTDecoder MOZ_FINAL { + ~MFTDecoder(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(MTFDecoder) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFTDecoder) + MFTDecoder(); - ~MFTDecoder(); // Creates the MFT. First thing to do as part of setup. // // Params: // - aMFTClsID the clsid used by CoCreateInstance to instantiate the // decoder MFT. HRESULT Create(const GUID& aMFTClsID);
new file mode 100644 --- /dev/null +++ b/content/media/gtest/TestVideoTrackEncoder.cpp @@ -0,0 +1,296 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gtest/gtest.h" +#include <algorithm> + +#include "mozilla/ArrayUtils.h" +#include "VP8TrackEncoder.h" +#include "ImageContainer.h" +#include "MediaStreamGraph.h" +#include "WebMWriter.h" // TODO: it's weird to include muxer header to get the class definition of VP8 METADATA + +using ::testing::TestWithParam; +using ::testing::Values; + +using namespace mozilla::layers; +using namespace mozilla; + +// A helper object to generate of different YUV planes. +class YUVBufferGenerator { +public: + YUVBufferGenerator() {} + + void Init(const mozilla::gfx::IntSize &aSize) + { + mImageSize = aSize; + + int yPlaneLen = aSize.width * aSize.height; + int cbcrPlaneLen = (yPlaneLen + 1) / 2; + int frameLen = yPlaneLen + cbcrPlaneLen; + + // Generate source buffer. + mSourceBuffer.SetLength(frameLen); + + // Fill Y plane. + memset(mSourceBuffer.Elements(), 0x10, yPlaneLen); + + // Fill Cb/Cr planes. + memset(mSourceBuffer.Elements() + yPlaneLen, 0x80, cbcrPlaneLen); + } + + mozilla::gfx::IntSize GetSize() const + { + return mImageSize; + } + + void Generate(nsTArray<nsRefPtr<Image> > &aImages) + { + aImages.AppendElement(CreateI420Image()); + aImages.AppendElement(CreateNV12Image()); + aImages.AppendElement(CreateNV21Image()); + } + +private: + Image *CreateI420Image() + { + PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin()); + PlanarYCbCrData data; + + const uint32_t yPlaneSize = mImageSize.width * mImageSize.height; + const uint32_t halfWidth = (mImageSize.width + 1) / 2; + const uint32_t halfHeight = (mImageSize.height + 1) / 2; + const uint32_t uvPlaneSize = halfWidth * halfHeight; + + // Y plane. + uint8_t *y = mSourceBuffer.Elements(); + data.mYChannel = y; + data.mYSize.width = mImageSize.width; + data.mYSize.height = mImageSize.height; + data.mYStride = mImageSize.width; + data.mYSkip = 0; + + // Cr plane. + uint8_t *cr = y + yPlaneSize + uvPlaneSize; + data.mCrChannel = cr; + data.mCrSkip = 0; + + // Cb plane + uint8_t *cb = y + yPlaneSize; + data.mCbChannel = cb; + data.mCbSkip = 0; + + // CrCb plane vectors. + data.mCbCrStride = halfWidth; + data.mCbCrSize.width = halfWidth; + data.mCbCrSize.height = halfHeight; + + image->SetData(data); + return image; + } + + Image *CreateNV12Image() + { + PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin()); + PlanarYCbCrData data; + + const uint32_t yPlaneSize = mImageSize.width * mImageSize.height; + const uint32_t halfWidth = (mImageSize.width + 1) / 2; + const uint32_t halfHeight = (mImageSize.height + 1) / 2; + + // Y plane. + uint8_t *y = mSourceBuffer.Elements(); + data.mYChannel = y; + data.mYSize.width = mImageSize.width; + data.mYSize.height = mImageSize.height; + data.mYStride = mImageSize.width; + data.mYSkip = 0; + + // Cr plane. + uint8_t *cr = y + yPlaneSize; + data.mCrChannel = cr; + data.mCrSkip = 1; + + // Cb plane + uint8_t *cb = y + yPlaneSize + 1; + data.mCbChannel = cb; + data.mCbSkip = 1; + + // 4:2:0. + data.mCbCrStride = mImageSize.width; + data.mCbCrSize.width = halfWidth; + data.mCbCrSize.height = halfHeight; + + image->SetData(data); + return image; + } + + Image *CreateNV21Image() + { + PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin()); + PlanarYCbCrData data; + + const uint32_t yPlaneSize = mImageSize.width * mImageSize.height; + const uint32_t halfWidth = (mImageSize.width + 1) / 2; + const uint32_t halfHeight = (mImageSize.height + 1) / 2; + + // Y plane. + uint8_t *y = mSourceBuffer.Elements(); + data.mYChannel = y; + data.mYSize.width = mImageSize.width; + data.mYSize.height = mImageSize.height; + data.mYStride = mImageSize.width; + data.mYSkip = 0; + + // Cr plane. + uint8_t *cr = y + yPlaneSize + 1; + data.mCrChannel = cr; + data.mCrSkip = 1; + + // Cb plane + uint8_t *cb = y + yPlaneSize; + data.mCbChannel = cb; + data.mCbSkip = 1; + + // 4:2:0. + data.mCbCrStride = mImageSize.width; + data.mCbCrSize.width = halfWidth; + data.mCbCrSize.height = halfHeight; + + image->SetData(data); + return image; + } + +private: + mozilla::gfx::IntSize mImageSize; + nsTArray<uint8_t> mSourceBuffer; +}; + +struct InitParam { + bool mShouldSucceed; // This parameter should cause success or fail result + int mWidth; // frame width + int mHeight; // frame height + mozilla::TrackRate mTrackRate; // track rate. 90K is the most commond track rate. +}; + +class TestVP8TrackEncoder: public VP8TrackEncoder +{ +public: + ::testing::AssertionResult TestInit(const InitParam &aParam) + { + nsresult result = Init(aParam.mWidth, aParam.mHeight, aParam.mWidth, aParam.mHeight, aParam.mTrackRate); + + if (((NS_FAILED(result) && aParam.mShouldSucceed)) || (NS_SUCCEEDED(result) && !aParam.mShouldSucceed)) + { + return ::testing::AssertionFailure() + << " width = " << aParam.mWidth + << " height = " << aParam.mHeight + << " TrackRate = " << aParam.mTrackRate << "."; + } + else + { + return ::testing::AssertionSuccess(); + } + } +}; + +// Init test +TEST(VP8VideoTrackEncoder, Initialization) +{ + InitParam params[] = { + // Failure cases. + { false, 640, 480, 0 }, // Trackrate should be larger than 1. + { false, 640, 480, -1 }, // Trackrate should be larger than 1. + { false, 0, 0, 90000 }, // Height/ width should be larger than 1. + { false, 0, 1, 90000 }, // Height/ width should be larger than 1. + { false, 1, 0, 90000}, // Height/ width should be larger than 1. + + // Success cases + { true, 640, 480, 90000}, // Standard VGA + { true, 800, 480, 90000}, // Standard WVGA + { true, 960, 540, 90000}, // Standard qHD + { true, 1280, 720, 90000} // Standard HD + }; + + for (size_t i = 0; i < ArrayLength(params); i++) + { + TestVP8TrackEncoder encoder; + EXPECT_TRUE(encoder.TestInit(params[i])); + } +} + +// Get MetaData test +TEST(VP8VideoTrackEncoder, FetchMetaData) +{ + InitParam params[] = { + // Success cases + { true, 640, 480, 90000}, // Standard VGA + { true, 800, 480, 90000}, // Standard WVGA + { true, 960, 540, 90000}, // Standard qHD + { true, 1280, 720, 90000} // Standard HD + }; + + for (size_t i = 0; i < ArrayLength(params); i++) + { + TestVP8TrackEncoder encoder; + EXPECT_TRUE(encoder.TestInit(params[i])); + + nsRefPtr<TrackMetadataBase> meta = encoder.GetMetadata(); + nsRefPtr<VP8Metadata> vp8Meta(static_cast<VP8Metadata*>(meta.get())); + + // METADATA should be depend on how to initiate encoder. + EXPECT_TRUE(vp8Meta->mWidth == params[i].mWidth); + EXPECT_TRUE(vp8Meta->mHeight == params[i].mHeight); + } +} + +// Encode test +TEST(VP8VideoTrackEncoder, FrameEncode) +{ + // Initiate VP8 encoder + TestVP8TrackEncoder encoder; + InitParam param = {true, 640, 480, 90000}; + encoder.TestInit(param); + + // Create YUV images as source. + nsTArray<nsRefPtr<Image>> images; + YUVBufferGenerator generator; + generator.Init(mozilla::gfx::IntSize(640, 480)); + generator.Generate(images); + + // Put generated YUV frame into video segment. + // Duration of each frame is 1 second. + VideoSegment segment; + for (nsTArray<nsRefPtr<Image>>::size_type i = 0; i < images.Length(); i++) + { + nsRefPtr<Image> image = images[i]; + segment.AppendFrame(image.forget(), mozilla::TrackTicks(90000), generator.GetSize()); + } + + // track change notification. + encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0, 0, segment); + + // Pull Encoded Data back from encoder. + EncodedFrameContainer container; + EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); +} + +// EOS test +TEST(VP8VideoTrackEncoder, EncodeComplete) +{ + // Initiate VP8 encoder + TestVP8TrackEncoder encoder; + InitParam param = {true, 640, 480, 90000}; + encoder.TestInit(param); + + // track end notification. + VideoSegment segment; + encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0, MediaStreamListener::TRACK_EVENT_ENDED, segment); + + // Pull Encoded Data back from encoder. Since we have sent + // EOS to encoder, encoder.GetEncodedTrack should return + // NS_OK immidiately. + EncodedFrameContainer container; + EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); +}
--- a/content/media/gtest/moz.build +++ b/content/media/gtest/moz.build @@ -6,16 +6,20 @@ LIBRARY_NAME = 'media_gtest' UNIFIED_SOURCES += [ 'TestAudioCompactor.cpp', 'TestTrackEncoder.cpp', ] +if CONFIG['MOZ_WEBM_ENCODER']: + UNIFIED_SOURCES += ['TestVideoTrackEncoder.cpp', +] + EXPORT_LIBRARY = True include('/ipc/chromium/chromium-config.mozbuild') LOCAL_INCLUDES += [ '/content/media/encoder', ]
--- a/content/svg/content/src/SVGFEImageElement.cpp +++ b/content/svg/content/src/SVGFEImageElement.cpp @@ -3,16 +3,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/SVGFEImageElement.h" #include "mozilla/EventStates.h" #include "mozilla/dom/SVGFEImageElementBinding.h" #include "mozilla/dom/SVGFilterElement.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "nsContentUtils.h" #include "nsLayoutUtils.h" #include "nsSVGUtils.h" #include "nsNetUtil.h" #include "imgIContainer.h" #include "gfx2DGlue.h" NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEImage) @@ -206,32 +208,26 @@ SVGFEImageElement::GetPrimitiveDescripti GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, getter_AddRefs(currentRequest)); nsCOMPtr<imgIContainer> imageContainer; if (currentRequest) { currentRequest->GetImage(getter_AddRefs(imageContainer)); } - nsRefPtr<gfxASurface> currentFrame; + RefPtr<SourceSurface> image; if (imageContainer) { - currentFrame = - imageContainer->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); + image = imageContainer->GetFrame(imgIContainer::FRAME_CURRENT, + imgIContainer::FLAG_SYNC_DECODE); } - if (!currentFrame) { + if (!image) { return FilterPrimitiveDescription(PrimitiveType::Empty); } - gfxPlatform* platform = gfxPlatform::GetPlatform(); - DrawTarget* dt = platform->ScreenReferenceDrawTarget(); - RefPtr<SourceSurface> image = - platform->GetSourceSurfaceForSurface(dt, currentFrame); - IntSize nativeSize; imageContainer->GetWidth(&nativeSize.width); imageContainer->GetHeight(&nativeSize.height); Matrix viewBoxTM = SVGContentUtils::GetViewBoxTransform(aFilterSubregion.width, aFilterSubregion.height, 0, 0, nativeSize.width, nativeSize.height, mPreserveAspectRatio);
--- a/dom/apps/src/AppsUtils.jsm +++ b/dom/apps/src/AppsUtils.jsm @@ -4,27 +4,27 @@ "use strict"; const Cu = Components.utils; const Cc = Components.classes; const Ci = Components.interfaces; const Cr = Components.results; -Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/WebappOSUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyServiceGetter(this, "NetworkUtil", - "@mozilla.org/network/util;1", - "nsINetUtil"); +XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", + "resource://gre/modules/FileUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils", + "resource://gre/modules/WebappOSUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); // Shared code for AppsServiceChild.jsm, Webapps.jsm and Webapps.js this.EXPORTED_SYMBOLS = ["AppsUtils", "ManifestHelper", "isAbsoluteURI"]; @@ -337,17 +337,18 @@ this.AppsUtils = { } return true; }, checkManifestContentType: function checkManifestContentType(aInstallOrigin, aWebappOrigin, aContentType) { let hadCharset = { }; let charset = { }; - let contentType = NetworkUtil.parseContentType(aContentType, charset, hadCharset); + let netutil = Cc["@mozilla.org/network/util;1"].getService(Ci.nsINetUtil); + let contentType = netutil.parseContentType(aContentType, charset, hadCharset); if (aInstallOrigin != aWebappOrigin && contentType != "application/x-web-app-manifest+json") { return false; } return true; }, /**
--- a/dom/bluetooth/BluetoothProfileController.h +++ b/dom/bluetooth/BluetoothProfileController.h @@ -3,17 +3,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_bluetooth_bluetoothprofilecontroller_h__ #define mozilla_dom_bluetooth_bluetoothprofilecontroller_h__ #include "BluetoothUuid.h" -#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" #include "nsAutoPtr.h" #include "nsITimer.h" BEGIN_BLUETOOTH_NAMESPACE /* * Class of Device(CoD): 32-bit unsigned integer * @@ -52,20 +52,22 @@ BEGIN_BLUETOOTH_NAMESPACE // Pointing device: sub-field of minor device class (Bit 7) #define IS_POINTING_DEVICE(cod) ((GET_MINOR_DEVICE_CLASS(cod) & 0x20) >> 5) class BluetoothProfileManagerBase; class BluetoothReplyRunnable; typedef void (*BluetoothProfileControllerCallback)(); -class BluetoothProfileController : public RefCounted<BluetoothProfileController> +class BluetoothProfileController MOZ_FINAL { + ~BluetoothProfileController(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(BluetoothProfileController) + NS_INLINE_DECL_REFCOUNTING(BluetoothProfileController) /** * @param aConnect: If it's a connect request, the value should be set * to true. For disconnect request, set it to false. * @param aDeviceAddress: The address of remote device. * @param aRunnable: Once the controller has done, the runnable will be * replied. When all connection/disconnection attemps * have failed, an error is fired. In other words, * reply a success if any attemp successes. @@ -78,17 +80,16 @@ public: * aCod or disconnect all connected profiles. */ BluetoothProfileController(bool aConnect, const nsAString& aDeviceAddress, BluetoothReplyRunnable* aRunnable, BluetoothProfileControllerCallback aCallback, uint16_t aServiceUuid, uint32_t aCod = 0); - ~BluetoothProfileController(); /** * The controller starts connecting/disconnecting profiles one by one * according to the order in array mProfiles. */ void StartSession(); /**
--- a/dom/browser-element/BrowserElementPanning.js +++ b/dom/browser-element/BrowserElementPanning.js @@ -24,16 +24,37 @@ const ContentPanning = { // Are we listening to touch or mouse events? watchedEventsType: '', // Are mouse events being delivered to this content along with touch // events, in violation of spec? hybridEvents: false, init: function cp_init() { + // If APZ is enabled, we do active element handling in C++ + // (see widget/xpwidgets/ActiveElementManager.h), and panning + // itself in APZ, so we don't need to handle any touch events here. + if (docShell.asyncPanZoomEnabled === false) { + this._setupListenersForPanning(); + } + + addEventListener("unload", + this._unloadHandler.bind(this), + /* useCapture = */ false, + /* wantsUntrusted = */ false); + + addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); + addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); + addEventListener("visibilitychange", this._handleVisibilityChange.bind(this)); + kObservedEvents.forEach((topic) => { + Services.obs.addObserver(this, topic, false); + }); + }, + + _setupListenersForPanning: function cp_setupListenersForPanning() { var events; try { content.document.createEvent('TouchEvent'); events = ['touchstart', 'touchend', 'touchmove']; this.watchedEventsType = 'touch'; #ifdef MOZ_WIDGET_GONK // The gonk widget backend does not deliver mouse events per // spec. Third-party content isn't exposed to this behavior, @@ -55,28 +76,16 @@ const ContentPanning = { events.forEach(function(type) { // Using the system group for mouse/touch events to avoid // missing events if .stopPropagation() has been called. els.addSystemEventListener(global, type, this.handleEvent.bind(this), /* useCapture = */ false); }.bind(this)); - - addEventListener("unload", - this._unloadHandler.bind(this), - /* useCapture = */ false, - /* wantsUntrusted = */ false); - - addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); - addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); - addEventListener("visibilitychange", this._handleVisibilityChange.bind(this)); - kObservedEvents.forEach((topic) => { - Services.obs.addObserver(this, topic, false); - }); }, handleEvent: function cp_handleEvent(evt) { // Ignore events targeting a <iframe mozbrowser> since those will be // handle by the BrowserElementPanning.js instance of it. if (evt.target instanceof Ci.nsIMozBrowserFrame) { return; } @@ -190,18 +199,17 @@ const ContentPanning = { } this.position.set(screenX, screenY); KineticPanning.reset(); KineticPanning.record(new Point(0, 0), evt.timeStamp); // We prevent start events to avoid sending a focus event at the end of this // touch series. See bug 889717. - if (docShell.asyncPanZoomEnabled === false && - (this.panning || this.preventNextClick)) { + if ((this.panning || this.preventNextClick)) { evt.preventDefault(); } }, onTouchEnd: function cp_onTouchEnd(evt) { let touch = null; if (!this.dragging || (this.watchedEventsType == 'touch' && @@ -230,17 +238,17 @@ const ContentPanning = { } if (this.target && click && (this.panning || this.preventNextClick)) { if (this.hybridEvents) { let target = this.target; let view = target.ownerDocument ? target.ownerDocument.defaultView : target; view.addEventListener('click', this, true, true); - } else if (docShell.asyncPanZoomEnabled === false) { + } else { // We prevent end events to avoid sending a focus event. See bug 889717. evt.preventDefault(); } } else if (this.target && click && !this.panning) { this.notify(this._activationTimer); } this._finishPanning(); @@ -279,28 +287,25 @@ const ContentPanning = { this._resetActive(); } // There's no possibility of us panning anything. if (!this.scrollCallback) { return; } - // If the application is not managed by the AsyncPanZoomController, then - // scroll manually. - if (docShell.asyncPanZoomEnabled === false) { - this.scrollCallback(delta.scale(-1)); - } + // Scroll manually. + this.scrollCallback(delta.scale(-1)); if (!this.panning && isPan) { this.panning = true; this._activationTimer.cancel(); } - if (this.panning && docShell.asyncPanZoomEnabled === false) { + if (this.panning) { // Only do this when we're actually executing a pan gesture. // Otherwise synthetic mouse events will be canceled. evt.stopPropagation(); evt.preventDefault(); } }, // nsITimerCallback @@ -587,19 +592,18 @@ const ContentPanning = { return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9)); }, _finishPanning: function() { this.dragging = false; delete this.primaryPointerId; this._activationTimer.cancel(); - // If there is a scroll action but the application is not managed by - // the AsyncPanZoom controller, let's do a manual kinetic panning action. - if (this.panning && docShell.asyncPanZoomEnabled === false) { + // If there is a scroll action, let's do a manual kinetic panning action. + if (this.panning) { KineticPanning.start(this); } }, _unloadHandler: function() { kObservedEvents.forEach((topic) => { Services.obs.removeObserver(this, topic); });
--- a/dom/camera/CameraControlImpl.h +++ b/dom/camera/CameraControlImpl.h @@ -14,18 +14,16 @@ #include "AutoRwLock.h" #include "nsIDOMDeviceStorage.h" #include "ICameraControl.h" #include "CameraCommon.h" #include "DeviceStorage.h" #include "DeviceStorageFileDescriptor.h" #include "CameraControlListener.h" -class DeviceStorageFileDescriptor; - namespace mozilla { namespace layers { class Image; } class RecorderProfileManager;
--- a/dom/camera/DOMCameraManager.cpp +++ b/dom/camera/DOMCameraManager.cpp @@ -4,17 +4,17 @@ #include "DOMCameraManager.h" #include "nsDebug.h" #include "jsapi.h" #include "Navigator.h" #include "nsPIDOMWindow.h" #include "mozilla/Services.h" #include "nsContentPermissionHelper.h" -#include "nsObserverService.h" +#include "nsIObserverService.h" #include "nsIPermissionManager.h" #include "DOMCameraControl.h" #include "nsDOMClassInfo.h" #include "CameraCommon.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/CameraManagerBinding.h" #include "mozilla/dom/PermissionMessageUtils.h" #include "mozilla/dom/TabChild.h"
--- a/dom/camera/ICameraControl.h +++ b/dom/camera/ICameraControl.h @@ -5,17 +5,17 @@ #ifndef DOM_CAMERA_ICAMERACONTROL_H #define DOM_CAMERA_ICAMERACONTROL_H #include "nsCOMPtr.h" #include "nsString.h" #include "nsAutoPtr.h" #include "nsISupportsImpl.h" -class DeviceStorageFileDescriptor; +struct DeviceStorageFileDescriptor; class nsIFile; namespace mozilla { class CameraControlListener; class RecorderProfileManager;
--- a/dom/devicestorage/DeviceStorage.h +++ b/dom/devicestorage/DeviceStorage.h @@ -316,23 +316,17 @@ private: bool mIsWatchingFile; bool mAllowedToWatchFile; nsresult Notify(const char* aReason, class DeviceStorageFile* aFile); friend class WatchFileEvent; friend class DeviceStorageRequest; - class VolumeNameCache : public mozilla::RefCounted<VolumeNameCache> - { - public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeNameCache) - nsTArray<nsString> mVolumeNames; - }; - static mozilla::StaticRefPtr<VolumeNameCache> sVolumeNameCache; + static mozilla::StaticAutoPtr<nsTArray<nsString>> sVolumeNameCache; #ifdef MOZ_WIDGET_GONK nsString mLastStatus; void DispatchMountChangeEvent(nsAString& aVolumeStatus); #endif // nsIDOMDeviceStorage.type enum {
--- a/dom/devicestorage/DeviceStorageFileDescriptor.h +++ b/dom/devicestorage/DeviceStorageFileDescriptor.h @@ -4,18 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DeviceStorageFileDescriptor_h #define DeviceStorageFileDescriptor_h #include "mozilla/ipc/FileDescriptor.h" -class DeviceStorageFileDescriptor MOZ_FINAL - : public mozilla::RefCounted<DeviceStorageFileDescriptor> +struct DeviceStorageFileDescriptor MOZ_FINAL { -public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(DeviceStorageFileDescriptor) + NS_INLINE_DECL_REFCOUNTING(DeviceStorageFileDescriptor) nsRefPtr<DeviceStorageFile> mDSFile; mozilla::ipc::FileDescriptor mFileDescriptor; }; #endif
--- a/dom/devicestorage/DeviceStorageRequestChild.h +++ b/dom/devicestorage/DeviceStorageRequestChild.h @@ -4,17 +4,17 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_devicestorage_DeviceStorageRequestChild_h #define mozilla_dom_devicestorage_DeviceStorageRequestChild_h #include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h" class DeviceStorageFile; -class DeviceStorageFileDescriptor; +struct DeviceStorageFileDescriptor; namespace mozilla { namespace dom { class DOMRequest; namespace devicestorage {
--- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -110,25 +110,26 @@ DeviceStorageUsedSpaceCache::CreateOrGet MOZ_ASSERT(NS_IsMainThread()); sDeviceStorageUsedSpaceCache = new DeviceStorageUsedSpaceCache(); ClearOnShutdown(&sDeviceStorageUsedSpaceCache); return sDeviceStorageUsedSpaceCache; } -TemporaryRef<DeviceStorageUsedSpaceCache::CacheEntry> +already_AddRefed<DeviceStorageUsedSpaceCache::CacheEntry> DeviceStorageUsedSpaceCache::GetCacheEntry(const nsAString& aStorageName) { - nsTArray<RefPtr<CacheEntry> >::size_type numEntries = mCacheEntries.Length(); - nsTArray<RefPtr<CacheEntry> >::index_type i; + nsTArray<nsRefPtr<CacheEntry>>::size_type numEntries = mCacheEntries.Length(); + nsTArray<nsRefPtr<CacheEntry>>::index_type i; for (i = 0; i < numEntries; i++) { - RefPtr<CacheEntry> cacheEntry = mCacheEntries[i]; + nsRefPtr<CacheEntry>& cacheEntry = mCacheEntries[i]; if (cacheEntry->mStorageName.Equals(aStorageName)) { - return cacheEntry; + nsRefPtr<CacheEntry> addRefedCacheEntry = cacheEntry; + return addRefedCacheEntry.forget(); } } return nullptr; } static int64_t GetFreeBytes(const nsAString& aStorageName) { @@ -144,17 +145,17 @@ GetFreeBytes(const nsAString& aStorageNa nsresult DeviceStorageUsedSpaceCache::AccumUsedSizes(const nsAString& aStorageName, uint64_t* aPicturesSoFar, uint64_t* aVideosSoFar, uint64_t* aMusicSoFar, uint64_t* aTotalSoFar) { - RefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName); + nsRefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName); if (!cacheEntry || cacheEntry->mDirty) { return NS_ERROR_NOT_AVAILABLE; } int64_t freeBytes = GetFreeBytes(cacheEntry->mStorageName); if (freeBytes != cacheEntry->mFreeBytes) { // Free space changed, so our cached results are no longer valid. return NS_ERROR_NOT_AVAILABLE; } @@ -169,35 +170,35 @@ DeviceStorageUsedSpaceCache::AccumUsedSi void DeviceStorageUsedSpaceCache::SetUsedSizes(const nsAString& aStorageName, uint64_t aPictureSize, uint64_t aVideosSize, uint64_t aMusicSize, uint64_t aTotalUsedSize) { - RefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName); + nsRefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName); if (!cacheEntry) { cacheEntry = new CacheEntry; cacheEntry->mStorageName = aStorageName; mCacheEntries.AppendElement(cacheEntry); } cacheEntry->mFreeBytes = GetFreeBytes(cacheEntry->mStorageName); cacheEntry->mPicturesUsedSize = aPictureSize; cacheEntry->mVideosUsedSize = aVideosSize; cacheEntry->mMusicUsedSize = aMusicSize; cacheEntry->mTotalUsedSize = aTotalUsedSize; cacheEntry->mDirty = false; } -class GlobalDirs : public RefCounted<GlobalDirs> +class GlobalDirs { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(GlobalDirs) + NS_INLINE_DECL_REFCOUNTING(GlobalDirs) #if !defined(MOZ_WIDGET_GONK) nsCOMPtr<nsIFile> pictures; nsCOMPtr<nsIFile> videos; nsCOMPtr<nsIFile> music; nsCOMPtr<nsIFile> sdcard; #endif nsCOMPtr<nsIFile> apps; nsCOMPtr<nsIFile> crashes; @@ -3174,26 +3175,25 @@ nsDOMDeviceStorage::Shutdown() UnregisterForSDCardChanges(this); } nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); obs->RemoveObserver(this, "file-watcher-update"); obs->RemoveObserver(this, "disk-space-watcher"); } -StaticRefPtr<nsDOMDeviceStorage::VolumeNameCache> - nsDOMDeviceStorage::sVolumeNameCache; +StaticAutoPtr<nsTArray<nsString>> nsDOMDeviceStorage::sVolumeNameCache; // static void nsDOMDeviceStorage::GetOrderedVolumeNames( nsDOMDeviceStorage::VolumeNameArray &aVolumeNames) { - if (sVolumeNameCache && sVolumeNameCache->mVolumeNames.Length() > 0) { - aVolumeNames.AppendElements(sVolumeNameCache->mVolumeNames); + if (sVolumeNameCache && sVolumeNameCache->Length() > 0) { + aVolumeNames.AppendElements(*sVolumeNameCache); return; } #ifdef MOZ_WIDGET_GONK nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID); if (vs) { vs->GetVolumeNames(aVolumeNames); // If the volume sdcard exists, then we want it to be first. @@ -3204,18 +3204,18 @@ nsDOMDeviceStorage::GetOrderedVolumeName aVolumeNames.RemoveElementAt(sdcardIndex); aVolumeNames.InsertElementAt(0, NS_LITERAL_STRING("sdcard")); } } #endif if (aVolumeNames.IsEmpty()) { aVolumeNames.AppendElement(EmptyString()); } - sVolumeNameCache = new VolumeNameCache; - sVolumeNameCache->mVolumeNames.AppendElements(aVolumeNames); + sVolumeNameCache = new nsTArray<nsString>; + sVolumeNameCache->AppendElements(aVolumeNames); } // static void nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin, const nsAString &aType, nsDOMDeviceStorage** aStore) {
--- a/dom/devicestorage/nsDeviceStorage.h +++ b/dom/devicestorage/nsDeviceStorage.h @@ -24,17 +24,16 @@ class nsPIDOMWindow; #include "nsWeakPtr.h" #include "nsIDOMEventListener.h" #include "nsIObserver.h" #include "nsIStringBundle.h" #include "mozilla/Mutex.h" #include "prtime.h" #include "DeviceStorage.h" #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h" -#include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" namespace mozilla { class ErrorResult; } // namespace mozilla #define POST_ERROR_EVENT_FILE_EXISTS "NoModificationAllowedError" #define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST "NotFoundError" @@ -75,17 +74,17 @@ public: const nsAString& aStorageName) : mCache(aCache) , mStorageName(aStorageName) {} ~InvalidateRunnable() {} NS_IMETHOD Run() MOZ_OVERRIDE { - mozilla::RefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry; + nsRefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry; cacheEntry = mCache->GetCacheEntry(mStorageName); if (cacheEntry) { cacheEntry->mDirty = true; } return NS_OK; } private: DeviceStorageUsedSpaceCache* mCache; @@ -115,31 +114,31 @@ public: void SetUsedSizes(const nsAString& aStorageName, uint64_t aPictureSize, uint64_t aVideosSize, uint64_t aMusicSize, uint64_t aTotalSize); private: friend class InvalidateRunnable; - class CacheEntry : public mozilla::RefCounted<CacheEntry> + struct CacheEntry { - public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(DeviceStorageUsedSpaceCache::CacheEntry) + NS_INLINE_DECL_REFCOUNTING(DeviceStorageUsedSpaceCache::CacheEntry) + bool mDirty; nsString mStorageName; int64_t mFreeBytes; uint64_t mPicturesUsedSize; uint64_t mVideosUsedSize; uint64_t mMusicUsedSize; uint64_t mTotalUsedSize; }; - mozilla::TemporaryRef<CacheEntry> GetCacheEntry(const nsAString& aStorageName); + already_AddRefed<CacheEntry> GetCacheEntry(const nsAString& aStorageName); - nsTArray<mozilla::RefPtr<CacheEntry> > mCacheEntries; + nsTArray<nsRefPtr<CacheEntry>> mCacheEntries; nsCOMPtr<nsIThread> mIOThread; static mozilla::StaticAutoPtr<DeviceStorageUsedSpaceCache> sDeviceStorageUsedSpaceCache; }; class DeviceStorageTypeChecker MOZ_FINAL {
--- a/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl +++ b/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl @@ -7,17 +7,17 @@ interface nsIDOMBlob; interface nsIDOMDOMRequest; interface nsIDOMDOMCursor; interface nsIDOMDeviceStorageChangeEvent; interface nsIDOMEventListener; interface nsIFile; %{C++ -class DeviceStorageFileDescriptor; +struct DeviceStorageFileDescriptor; %} [ptr] native DeviceStorageFdPtr(DeviceStorageFileDescriptor); [scriptable, uuid(8b724547-3c78-4244-969a-f00a1f4ae0c3), builtinclass] interface nsIDOMDeviceStorage : nsIDOMEventTarget { [implicit_jscontext] attribute jsval onchange; nsIDOMDOMRequest add(in nsIDOMBlob aBlob);
--- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -45,16 +45,17 @@ using class mozilla::WidgetSelectionEven using class mozilla::WidgetTextEvent from "ipc/nsGUIEventIPC.h"; using class mozilla::WidgetTouchEvent from "ipc/nsGUIEventIPC.h"; using struct mozilla::dom::RemoteDOMEvent from "mozilla/dom/TabMessageUtils.h"; using mozilla::dom::ScreenOrientation from "mozilla/dom/ScreenOrientation.h"; using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h"; using mozilla::CSSPoint from "Units.h"; using mozilla::CSSToScreenScale from "Units.h"; using mozilla::CommandInt from "mozilla/EventForwards.h"; +using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h"; namespace mozilla { namespace dom { struct NativeKeyBinding { CommandInt[] singleLineCommands; CommandInt[] multiLineCommands; @@ -405,21 +406,20 @@ child: * relative to the current scroll offset. In the case the "contextmenu" * event generated by the preceding HandleLongTap call was not handled, * this message is expected to generate a "mousedown" and "mouseup" * series of events */ HandleLongTapUp(CSSPoint point, ScrollableLayerGuid aGuid); /** - * Notifies the child that the parent has begun or finished transforming - * the visible child content area. Useful for showing/hiding scrollbars. + * Notifies the child about various APZ state changes. + * See GeckoContentController::NotifyAPZStateChange() for details. */ - NotifyTransformBegin(ViewID aViewId); - NotifyTransformEnd(ViewID aViewId); + NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg); /** * Sending an activate message moves focus to the child. */ Activate(); Deactivate();
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -69,16 +69,17 @@ #include "nsViewportInfo.h" #include "JavaScriptChild.h" #include "APZCCallbackHelper.h" #include "nsILoadContext.h" #include "ipc/nsGUIEventIPC.h" #include "mozilla/gfx/Matrix.h" #include "UnitTransforms.h" #include "ClientLayerManager.h" +#include "ActiveElementManager.h" #include "nsColorPickerProxy.h" #ifdef DEBUG #include "PCOMContentPermissionRequestChild.h" #endif /* DEBUG */ #define BROWSER_ELEMENT_CHILD_SCRIPT \ @@ -682,16 +683,17 @@ TabChild::TabChild(ContentChild* aManage , mDidFakeShow(false) , mNotified(false) , mTriedBrowserInit(false) , mOrientation(eScreenOrientation_PortraitPrimary) , mUpdateHitRegion(false) , mContextMenuHandled(false) , mWaitingTouchListeners(false) , mIgnoreKeyPressEvent(false) + , mActiveElementManager(new ActiveElementManager()) { if (!sActiveDurationMsSet) { Preferences::AddIntVarCache(&sActiveDurationMs, "ui.touch_activation.duration_ms", sActiveDurationMs); sActiveDurationMsSet = true; } } @@ -1725,33 +1727,59 @@ TabChild::RecvHandleLongTapUp(const CSSP return true; } RecvHandleSingleTap(aPoint, aGuid); return true; } bool -TabChild::RecvNotifyTransformBegin(const ViewID& aViewId) +TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId, + const APZStateChange& aChange, + const int& aArg) { - nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId); - nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf); - if (scrollbarOwner) { - scrollbarOwner->ScrollbarActivityStarted(); + switch (aChange) + { + case APZStateChange::TransformBegin: + { + nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId); + nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf); + if (scrollbarOwner) { + scrollbarOwner->ScrollbarActivityStarted(); + } + break; } - return true; -} - -bool -TabChild::RecvNotifyTransformEnd(const ViewID& aViewId) -{ - nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId); - nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf); - if (scrollbarOwner) { - scrollbarOwner->ScrollbarActivityStopped(); + case APZStateChange::TransformEnd: + { + nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId); + nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf); + if (scrollbarOwner) { + scrollbarOwner->ScrollbarActivityStopped(); + } + break; + } + case APZStateChange::StartTouch: + { + mActiveElementManager->HandleTouchStart(aArg); + break; + } + case APZStateChange::StartPanning: + { + mActiveElementManager->HandlePanStart(); + break; + } + case APZStateChange::EndTouch: + { + mActiveElementManager->HandleTouchEnd(aArg); + break; + } + default: + // APZStateChange has a 'sentinel' value, and the compiler complains + // if an enumerator is not handled and there is no 'default' case. + break; } return true; } bool TabChild::RecvActivate() { nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation()); @@ -1946,16 +1974,20 @@ TabChild::RecvRealTouchEvent(const Widge nsEventStatus status = DispatchWidgetEvent(localEvent); if (!IsAsyncPanZoomEnabled()) { UpdateTapState(localEvent, status); return true; } + if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) { + mActiveElementManager->SetTargetElement(localEvent.touches[0]->Target()); + } + nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation()); nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow(); if (!innerWindow || !innerWindow->HasTouchEventListeners()) { SendContentReceivedTouch(aGuid, false); return true; }
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -37,16 +37,20 @@ class nsICachedFileDescriptorListener; class nsIDOMWindowUtils; namespace mozilla { namespace layout { class RenderFrameChild; } +namespace widget { +class ActiveElementManager; +} + namespace dom { class TabChild; class ClonedMessageData; class TabChildBase; class TabChildGlobal : public DOMEventTargetHelper, public nsIContentFrameMessageManager, @@ -223,16 +227,17 @@ class TabChild : public PBrowserChild, public nsIObserver, public TabContext, public nsITooltipListener, public TabChildBase { typedef mozilla::dom::ClonedMessageData ClonedMessageData; typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::layout::ScrollingBehavior ScrollingBehavior; + typedef mozilla::widget::ActiveElementManager ActiveElementManager; public: /** * This is expected to be called off the critical path to content * startup. This is an opportunity to load things that are slow * on the critical path. */ static void PreloadSlowThings(); @@ -291,18 +296,19 @@ public: virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual bool RecvHandleSingleTap(const CSSPoint& aPoint, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual bool RecvHandleLongTap(const CSSPoint& aPoint, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual bool RecvHandleLongTapUp(const CSSPoint& aPoint, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; - virtual bool RecvNotifyTransformBegin(const ViewID& aViewId) MOZ_OVERRIDE; - virtual bool RecvNotifyTransformEnd(const ViewID& aViewId) MOZ_OVERRIDE; + virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId, + const APZStateChange& aChange, + const int& aArg) MOZ_OVERRIDE; virtual bool RecvActivate() MOZ_OVERRIDE; virtual bool RecvDeactivate() MOZ_OVERRIDE; virtual bool RecvMouseEvent(const nsString& aType, const float& aX, const float& aY, const int32_t& aButton, const int32_t& aClickCount, const int32_t& aModifiers, @@ -539,16 +545,17 @@ private: bool mTriedBrowserInit; ScreenOrientation mOrientation; bool mUpdateHitRegion; bool mContextMenuHandled; bool mWaitingTouchListeners; void FireSingleTapEvent(LayoutDevicePoint aPoint); bool mIgnoreKeyPressEvent; + nsRefPtr<ActiveElementManager> mActiveElementManager; DISALLOW_EVIL_CONSTRUCTORS(TabChild); }; } } #endif // mozilla_dom_TabChild_h
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -549,27 +549,22 @@ void TabParent::HandleLongTapUp(const CS int32_t aModifiers, const ScrollableLayerGuid &aGuid) { if (!mIsDestroyed) { unused << SendHandleLongTapUp(aPoint, aGuid); } } -void TabParent::NotifyTransformBegin(ViewID aViewId) +void TabParent::NotifyAPZStateChange(ViewID aViewId, + APZStateChange aChange, + int aArg) { if (!mIsDestroyed) { - unused << SendNotifyTransformBegin(aViewId); - } -} - -void TabParent::NotifyTransformEnd(ViewID aViewId) -{ - if (!mIsDestroyed) { - unused << SendNotifyTransformEnd(aViewId); + unused << SendNotifyAPZStateChange(aViewId, aChange, aArg); } } void TabParent::Activate() { if (!mIsDestroyed) { unused << SendActivate();
--- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -207,18 +207,19 @@ public: int32_t aModifiers, const ScrollableLayerGuid& aGuid); void HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid); void HandleLongTapUp(const CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid); - void NotifyTransformBegin(ViewID aViewId); - void NotifyTransformEnd(ViewID aViewId); + void NotifyAPZStateChange(ViewID aViewId, + APZStateChange aChange, + int aArg); void Activate(); void Deactivate(); bool MapEventCoordinatesForChildProcess(mozilla::WidgetEvent* aEvent); void MapEventCoordinatesForChildProcess(const LayoutDeviceIntPoint& aOffset, mozilla::WidgetEvent* aEvent); void SendMouseEvent(const nsAString& aType, float aX, float aY,
--- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -6,17 +6,17 @@ #include "mozilla/Services.h" #include "mozilla/unused.h" #include "nsIMediaManager.h" #include "nsHashKeys.h" #include "nsGlobalWindow.h" #include "nsClassHashtable.h" #include "nsRefPtrHashtable.h" -#include "nsObserverService.h" +#include "nsIObserver.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" #include "nsPIDOMWindow.h" #include "nsIDOMNavigatorUserMedia.h" #include "nsXULAppAPI.h" #include "mozilla/Attributes.h" #include "mozilla/Preferences.h"
--- a/dom/system/gonk/AutoMounter.cpp +++ b/dom/system/gonk/AutoMounter.cpp @@ -158,22 +158,22 @@ protected: private: const static int kMaxErrorCount = 3; // Max number of errors before we give up int mErrorCount; }; /***************************************************************************/ -class AutoMounter : public RefCounted<AutoMounter> +class AutoMounter { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(AutoMounter) + NS_INLINE_DECL_REFCOUNTING(AutoMounter) - typedef nsTArray<RefPtr<Volume> > VolumeArray; + typedef nsTArray<RefPtr<Volume>> VolumeArray; AutoMounter() : mResponseCallback(new AutoMounterResponseCallback), mMode(AUTOMOUNTER_DISABLE) { VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver); Volume::RegisterObserver(&mVolumeEventObserver); @@ -687,31 +687,31 @@ UsbCableEventIOThread() * * Public API * * Since the AutoMounter runs in IO Thread context, we need to switch * to IOThread context before we can do anything. * **************************************************************************/ -class UsbCableObserver : public SwitchObserver, - public RefCounted<UsbCableObserver> +class UsbCableObserver MOZ_FINAL : public SwitchObserver { + ~UsbCableObserver() + { + UnregisterSwitchObserver(SWITCH_USB, this); + } + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(UsbCableObserver) + NS_INLINE_DECL_REFCOUNTING(UsbCableObserver) + UsbCableObserver() { RegisterSwitchObserver(SWITCH_USB, this); } - ~UsbCableObserver() - { - UnregisterSwitchObserver(SWITCH_USB, this); - } - virtual void Notify(const SwitchEvent& aEvent) { DBG("UsbCable switch device: %d state: %s\n", aEvent.device(), SwitchStateStr(aEvent)); XRE_GetIOMessageLoop()->PostTask( FROM_HERE, NewRunnableFunction(UsbCableEventIOThread)); }
--- a/dom/system/gonk/Volume.h +++ b/dom/system/gonk/Volume.h @@ -4,35 +4,36 @@ #ifndef mozilla_system_volume_h__ #define mozilla_system_volume_h__ #include "VolumeCommand.h" #include "nsIVolume.h" #include "nsString.h" #include "mozilla/Observer.h" -#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" #include "nsWhitespaceTokenizer.h" namespace mozilla { namespace system { /*************************************************************************** * * There is an instance of the Volume class for each volume reported * from vold. * * Each volume originates from the /system/etv/vold.fstab file. * ***************************************************************************/ -class Volume : public RefCounted<Volume> +class Volume MOZ_FINAL { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(Volume) + NS_INLINE_DECL_REFCOUNTING(Volume) + Volume(const nsCSubstring& aVolumeName); typedef long STATE; // States are now defined in nsIVolume.idl static const char* StateStr(STATE aState) { return NS_VolumeStateStr(aState); } const char* StateStr() const { return StateStr(mState); } STATE State() const { return mState; }
--- a/dom/system/gonk/VolumeCommand.h +++ b/dom/system/gonk/VolumeCommand.h @@ -1,16 +1,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_system_volumecommand_h__ #define mozilla_system_volumecommand_h__ #include "nsString.h" +#include "nsISupportsImpl.h" #include "mozilla/RefPtr.h" #include <algorithm> #include <vold/ResponseCode.h> namespace mozilla { namespace system { class Volume; @@ -27,25 +28,26 @@ class VolumeCommand; * The responses from vold are all of the form: * * <ResponseCode> <String> * * Valid Response codes can be found in the vold/ResponseCode.h header. * ***************************************************************************/ -class VolumeResponseCallback : public RefCounted<VolumeResponseCallback> +class VolumeResponseCallback { +protected: + virtual ~VolumeResponseCallback() {} + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeResponseCallback) + NS_INLINE_DECL_REFCOUNTING(VolumeResponseCallback) VolumeResponseCallback() : mResponseCode(0), mPending(false) {} - virtual ~VolumeResponseCallback() {} - bool Done() const { // Response codes from the 200, 400, and 500 series all indicated that // the command has completed. return (mResponseCode >= ResponseCode::CommandOkay) && (mResponseCode < ResponseCode::UnsolicitedInformational); } @@ -101,36 +103,38 @@ private: * Commands sent to vold need an explicit null character so we add one * to the command to ensure that it's included in the length. * * All of these commands are asynchronous in nature, and the * ResponseReceived callback will be called when a response is available. * ***************************************************************************/ -class VolumeCommand : public RefCounted<VolumeCommand> +class VolumeCommand { +protected: + virtual ~VolumeCommand() {} + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeCommand) + NS_INLINE_DECL_REFCOUNTING(VolumeCommand) + VolumeCommand(VolumeResponseCallback* aCallback) : mBytesConsumed(0), mCallback(aCallback) { SetCmd(NS_LITERAL_CSTRING("")); } VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback) : mBytesConsumed(0), mCallback(aCallback) { SetCmd(aCommand); } - virtual ~VolumeCommand() {} - void SetCmd(const nsACString& aCommand) { mCmd.Truncate(); #if ANDROID_VERSION >= 17 // JB requires a sequence number at the beginning of messages. // It doesn't matter what we use, so we use 0. mCmd = "0 "; #endif
--- a/dom/system/gonk/VolumeManager.h +++ b/dom/system/gonk/VolumeManager.h @@ -6,17 +6,17 @@ #define mozilla_system_volumemanager_h__ #include <vector> #include <queue> #include "base/message_loop.h" #include "mozilla/FileUtils.h" #include "mozilla/Observer.h" -#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" #include "nsString.h" #include "nsTArray.h" #include "Volume.h" #include "VolumeCommand.h" namespace mozilla { namespace system { @@ -68,26 +68,26 @@ namespace system { * There is also a command line tool called vdc, which can be used to send * the above commands to vold. * * Currently, only the volume list, share/unshare, and mount/unmount * commands are being used. * ***************************************************************************/ -class VolumeManager : public MessageLoopForIO::LineWatcher, - public RefCounted<VolumeManager> +class VolumeManager MOZ_FINAL : public MessageLoopForIO::LineWatcher { + virtual ~VolumeManager(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeManager) + NS_INLINE_DECL_REFCOUNTING(VolumeManager) - typedef nsTArray<RefPtr<Volume> > VolumeArray; + typedef nsTArray<RefPtr<Volume>> VolumeArray; VolumeManager(); - virtual ~VolumeManager(); //----------------------------------------------------------------------- // // State related methods. // // The VolumeManager starts off in the STARTING state. Once a connection // is established with vold, it asks for a list of volumes, and once the // volume list has been received, then the VolumeManager enters the
--- a/dom/system/gonk/VolumeServiceIOThread.h +++ b/dom/system/gonk/VolumeServiceIOThread.h @@ -14,23 +14,24 @@ namespace system { class nsVolumeService; /*************************************************************************** * The nsVolumeServiceIOThread is a companion class to the nsVolumeService * class, but whose methods are called from IOThread. */ class VolumeServiceIOThread : public VolumeManager::StateObserver, - public Volume::EventObserver, - public RefCounted<VolumeServiceIOThread> + public Volume::EventObserver { + ~VolumeServiceIOThread(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeServiceIOThread) + NS_INLINE_DECL_REFCOUNTING(VolumeServiceIOThread) + VolumeServiceIOThread(nsVolumeService* aVolumeService); - ~VolumeServiceIOThread(); private: void UpdateAllVolumes(); virtual void Notify(const VolumeManager::StateChangedEvent& aEvent); virtual void Notify(Volume* const & aVolume); RefPtr<nsVolumeService> mVolumeService;
--- a/dom/xbl/test/file_bug821850.xhtml +++ b/dom/xbl/test/file_bug821850.xhtml @@ -48,21 +48,22 @@ https://bugzilla.mozilla.org/show_bug.cg "Unexposed method should be visible to XBL"); is(typeof bound.wrappedJSObject.unexposedMethod, 'undefined', "Unexposed method should not be defined in content"); is(typeof bound.unexposedProperty, 'number', "Unexposed property should be visible to XBL"); is(typeof bound.wrappedJSObject.unexposedProperty, 'undefined', "Unexposed property should not be defined in content"); - // Check that here document.QueryInterface works - ok("QueryInterface" in document, - "Should have a document.QueryInterface here"); - is(document.QueryInterface(Components.interfaces.nsIDOMDocument), - document, "Should be able to QI the document"); + // Check that here HTMLImageElement.QueryInterface works + var img = document.querySelector("img"); + ok("QueryInterface" in img, + "Should have a img.QueryInterface here"); + is(img.QueryInterface(Components.interfaces.nsIImageLoadingContent), + img, "Should be able to QI the image"); // Make sure standard constructors work right in the presence of // sandboxPrototype and Xray-resolved constructors. is(window.Function, XPCNativeWrapper(window.wrappedJSObject.Function), "window.Function comes from the window, not the global"); ok(Function != window.Function, "Function constructors are distinct"); is(Object.getPrototypeOf(Function.prototype), Object.getPrototypeOf({foo: 42}), "Function constructor is local"); @@ -284,13 +285,14 @@ https://bugzilla.mozilla.org/show_bug.cg </script> </head> <body onload="setup()"> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821850">Mozilla Bug 821850</a> <p id="display"></p> <div id="content"> <div id="bound">Bound element</div> <div id="bound2">Bound element</div> + <img/> </div> <pre id="test"> </pre> </body> </html>
--- a/editor/libeditor/html/tests/browserscope/lib/richtext2/richtext2/tests/insert.py +++ b/editor/libeditor/html/tests/browserscope/lib/richtext2/richtext2/tests/insert.py @@ -160,55 +160,55 @@ INSERT_TESTS = { ] }, { 'desc': 'insert <img>', 'command': 'insertimage', 'tests': [ { 'id': 'IIMG:url_TEXT-1_SC', 'rte1-id': 'a-insertimage-0', - 'desc': 'Insert image with URL "http://goo.gl/bar.png"', - 'value': 'http://goo.gl/bar.png', + 'desc': 'Insert image with URL "bar.png"', + 'value': 'bar.png', 'checkAttrs': True, 'pad': 'foo^bar', - 'expected': [ 'foo<img src="http://goo.gl/bar.png">|bar', - 'foo<img src="http://goo.gl/bar.png">^bar' ] }, + 'expected': [ 'foo<img src="bar.png">|bar', + 'foo<img src="bar.png">^bar' ] }, { 'id': 'IIMG:url_IMG-1_SO', 'desc': 'Change existing image to new URL, selection on <img>', - 'value': 'http://baz.com/quz.png', + 'value': 'quz.png', 'checkAttrs': True, - 'pad': '<span>foo{<img src="http://goo.gl/bar.png">}bar</span>', - 'expected': [ '<span>foo<img src="http://baz.com/quz.png"/>|bar</span>', - '<span>foo<img src="http://baz.com/quz.png"/>^bar</span>' ] }, + 'pad': '<span>foo{<img src="bar.png">}bar</span>', + 'expected': [ '<span>foo<img src="quz.png"/>|bar</span>', + '<span>foo<img src="quz.png"/>^bar</span>' ] }, { 'id': 'IIMG:url_SPAN-IMG-1_SO', 'desc': 'Change existing image to new URL, selection in text surrounding <img>', - 'value': 'http://baz.com/quz.png', + 'value': 'quz.png', 'checkAttrs': True, - 'pad': 'foo[<img src="http://goo.gl/bar.png">]bar', - 'expected': [ 'foo<img src="http://baz.com/quz.png"/>|bar', - 'foo<img src="http://baz.com/quz.png"/>^bar' ] }, + 'pad': 'foo[<img src="bar.png">]bar', + 'expected': [ 'foo<img src="quz.png"/>|bar', + 'foo<img src="quz.png"/>^bar' ] }, { 'id': 'IIMG:._SPAN-IMG-1_SO', 'desc': 'Remove existing image or URL, selection on <img>', 'value': '', 'checkAttrs': True, - 'pad': '<span>foo{<img src="http://goo.gl/bar.png">}bar</span>', + 'pad': '<span>foo{<img src="bar.png">}bar</span>', 'expected': [ '<span>foo^bar</span>', '<span>foo<img>|bar</span>', '<span>foo<img>^bar</span>', '<span>foo<img src="">|bar</span>', '<span>foo<img src="">^bar</span>' ] }, { 'id': 'IIMG:._IMG-1_SO', 'desc': 'Remove existing image or URL, selection in text surrounding <img>', 'value': '', 'checkAttrs': True, - 'pad': 'foo[<img src="http://goo.gl/bar.png">]bar', + 'pad': 'foo[<img src="bar.png">]bar', 'expected': [ 'foo^bar', 'foo<img>|bar', 'foo<img>^bar', 'foo<img src="">|bar', 'foo<img src="">^bar' ] } ] },
--- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -411,17 +411,17 @@ public: } /* * Returns a DataSourceSurface with the same data as this one, but * guaranteed to have surface->GetType() == SurfaceType::DATA. */ virtual TemporaryRef<DataSourceSurface> GetDataSurface(); - DebugOnly<bool> mIsMapped; + bool mIsMapped; }; /* This is an abstract object that accepts path segments. */ class PathSink : public RefCounted<PathSink> { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathSink) virtual ~PathSink() {}
--- a/gfx/2d/DataSurfaceHelpers.h +++ b/gfx/2d/DataSurfaceHelpers.h @@ -20,27 +20,29 @@ ConvertBGRXToBGRA(uint8_t* aData, const * contain |aSrcSize.width * aSrcSize.height * aBytesPerPixel| bytes. */ void CopySurfaceDataToPackedArray(uint8_t* aSrc, uint8_t* aDst, IntSize aSrcSize, int32_t aSrcStride, int32_t aBytesPerPixel); /** * Convert aSurface to a packed buffer in BGRA format. The pixel data is - * returned in a buffer allocated with new uint8_t[]. + * returned in a buffer allocated with new uint8_t[]. The caller then has + * ownership of the buffer and is responsible for delete[]'ing it. */ uint8_t* SurfaceToPackedBGRA(DataSourceSurface *aSurface); /** * Convert aSurface to a packed buffer in BGR format. The pixel data is - * returned in a buffer allocated with new uint8_t[]. + * returned in a buffer allocated with new uint8_t[]. The caller then has + * ownership of the buffer and is responsible for delete[]'ing it. * * This function is currently only intended for use with surfaces of format - * SurfaceFormat::B8G8R8X8 since the X components of the pixel data are simply - * dropped (no attempt is made to un-pre-multiply alpha from the color - * components). + * SurfaceFormat::B8G8R8X8 since the X components of the pixel data (if any) + * are simply dropped (no attempt is made to un-pre-multiply alpha from the + * color components). */ uint8_t* SurfaceToPackedBGR(DataSourceSurface *aSurface); } }
--- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -21,16 +21,17 @@ #include "gfxRect.h" #include "nsRect.h" #include "nsRegion.h" #include "gfxTypes.h" #include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/CompositorTypes.h" #include "FrameMetrics.h" #include "FilterSupport.h" +#include "mozilla/layers/GeckoContentController.h" #ifdef _MSC_VER #pragma warning( disable : 4800 ) #endif namespace mozilla { typedef gfxImageFormat PixelFormat; @@ -1064,11 +1065,21 @@ struct ParamTraits<mozilla::gfx::FilterD static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { return (ReadParam(aMsg, aIter, &aResult->mFilterSpaceBounds) && ReadParam(aMsg, aIter, &aResult->mPrimitives)); } }; +typedef mozilla::layers::GeckoContentController::APZStateChange APZStateChange; + +template <> +struct ParamTraits<APZStateChange> + : public ContiguousTypedEnumSerializer< + APZStateChange, + APZStateChange::TransformBegin, + APZStateChange::APZStateChangeSentinel> +{}; + } /* namespace IPC */ #endif /* __GFXMESSAGEUTILS_H__ */
--- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -132,28 +132,22 @@ enum SurfaceInitMode { INIT_MODE_NONE, INIT_MODE_CLEAR }; /** * A base class for a platform-dependent helper for use by TextureHost. */ -class CompositorBackendSpecificData : public RefCounted<CompositorBackendSpecificData> +class CompositorBackendSpecificData { -public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorBackendSpecificData) - CompositorBackendSpecificData() - { - MOZ_COUNT_CTOR(CompositorBackendSpecificData); - } - virtual ~CompositorBackendSpecificData() - { - MOZ_COUNT_DTOR(CompositorBackendSpecificData); - } + NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData) + +protected: + virtual ~CompositorBackendSpecificData() {} }; /** * Common interface for compositor backends. * * Compositor provides a cross-platform interface to a set of operations for * compositing quads. Compositor knows nothing about the layer tree. It must be * told everything about each composited quad - contents, location, transform, @@ -190,31 +184,30 @@ public: * * By default, the compositor will render to the screen, to render to a target, * call SetTargetContext or SetRenderTarget, the latter with a target created * by CreateRenderTarget or CreateRenderTargetFromSource. * * The target and viewport methods can be called before any DrawQuad call and * affect any subsequent DrawQuad calls. */ -class Compositor : public RefCounted<Compositor> +class Compositor { +protected: + virtual ~Compositor() {} + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(Compositor) + NS_INLINE_DECL_REFCOUNTING(Compositor) + Compositor(PCompositorParent* aParent = nullptr) : mCompositorID(0) , mDiagnosticTypes(DIAGNOSTIC_NONE) , mParent(aParent) , mScreenRotation(ROTATION_0) { - MOZ_COUNT_CTOR(Compositor); - } - virtual ~Compositor() - { - MOZ_COUNT_DTOR(Compositor); } virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0; virtual bool Initialize() = 0; virtual void Destroy() = 0; /** * Return true if the effect type is supported.
--- a/gfx/layers/Effects.h +++ b/gfx/layers/Effects.h @@ -32,25 +32,28 @@ namespace layers { * - any way in which rendering can be changed, e.g., applying a mask layer. * * During the rendering process, an effect chain is created by the layer being * rendered and the primary effect is added by the compositable host. Secondary * effects may be added by the layer or compositable. The effect chain is passed * to the compositor by the compositable host as a parameter to DrawQuad. */ -struct Effect : public RefCounted<Effect> +struct Effect { - MOZ_DECLARE_REFCOUNTED_TYPENAME(Effect) + NS_INLINE_DECL_REFCOUNTING(Effect) + Effect(EffectTypes aType) : mType(aType) {} EffectTypes mType; + virtual void PrintInfo(nsACString& aTo, const char* aPrefix) = 0; + +protected: virtual ~Effect() {} - virtual void PrintInfo(nsACString& aTo, const char* aPrefix) =0; }; // Render from a texture struct TexturedEffect : public Effect { TexturedEffect(EffectTypes aType, TextureSource *aTexture, bool aPremultiplied,
--- a/gfx/layers/client/CompositableClient.h +++ b/gfx/layers/client/CompositableClient.h @@ -63,24 +63,26 @@ class TextureClientData; * by this layer forwarder (the matching uses a global map on the compositor side, * see CompositableMap in ImageBridgeParent.cpp) * * Subclasses: Thebes layers use ContentClients, ImageLayers use ImageClients, * Canvas layers use CanvasClients (but ImageHosts). We have a different subclass * where we have a different way of interfacing with the textures - in terms of * drawing into the compositable and/or passing its contents to the compostior. */ -class CompositableClient : public AtomicRefCounted<CompositableClient> +class CompositableClient { +protected: + virtual ~CompositableClient(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableClient) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositableClient) + CompositableClient(CompositableForwarder* aForwarder, TextureFlags aFlags = 0); - virtual ~CompositableClient(); - virtual TextureInfo GetTextureInfo() const = 0; LayersBackend GetCompositorBackendType() const; TemporaryRef<BufferTextureClient> CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT, gfx::BackendType aMoz2dBackend = gfx::BackendType::NONE);
--- a/gfx/layers/client/SimpleTextureClientPool.h +++ b/gfx/layers/client/SimpleTextureClientPool.h @@ -14,31 +14,31 @@ #include <stack> #include <list> namespace mozilla { namespace layers { class ISurfaceAllocator; -class SimpleTextureClientPool : public RefCounted<SimpleTextureClientPool> +class SimpleTextureClientPool { -public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(SimpleTextureClientPool) - - SimpleTextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, - ISurfaceAllocator *aAllocator); - ~SimpleTextureClientPool() { for (auto it = mOutstandingTextureClients.begin(); it != mOutstandingTextureClients.end(); ++it) { (*it)->ClearRecycleCallback(); } } +public: + NS_INLINE_DECL_REFCOUNTING(SimpleTextureClientPool) + + SimpleTextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, + ISurfaceAllocator *aAllocator); + /** * If a TextureClient is AutoRecycled, when the last reference is * released this object will be automatically return to the pool as * soon as the compositor informs us it is done with it. */ TemporaryRef<TextureClient> GetTextureClient(bool aAutoRecycle = false); TemporaryRef<TextureClient> GetTextureClientWithAutoRecycle() { return GetTextureClient(true); }
--- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -70,33 +70,27 @@ namespace layers { * TextureChild is used to synchronize a texture client and its corresponding * TextureHost if needed (a TextureClient that is not shared with the compositor * does not have a TextureChild) * * During the deallocation phase, a TextureChild may hold its recently destroyed * TextureClient's data until the compositor side confirmed that it is safe to * deallocte or recycle the it. */ -class TextureChild : public PTextureChild - , public AtomicRefCounted<TextureChild> +class TextureChild MOZ_FINAL : public PTextureChild { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureChild) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild) + TextureChild() : mForwarder(nullptr) , mTextureData(nullptr) , mTextureClient(nullptr) , mIPCOpen(false) { - MOZ_COUNT_CTOR(TextureChild); - } - - ~TextureChild() - { - MOZ_COUNT_DTOR(TextureChild); } bool Recv__delete__() MOZ_OVERRIDE; bool RecvCompositorRecycle(const MaybeFenceHandle& aFence) { RECYCLE_LOG("Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get()); if (aFence.type() != aFence.Tnull_t) {
--- a/gfx/layers/client/TextureClientPool.h +++ b/gfx/layers/client/TextureClientPool.h @@ -13,23 +13,25 @@ #include "nsITimer.h" #include <stack> namespace mozilla { namespace layers { class ISurfaceAllocator; -class TextureClientPool : public RefCounted<TextureClientPool> +class TextureClientPool MOZ_FINAL { + ~TextureClientPool(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureClientPool) + NS_INLINE_DECL_REFCOUNTING(TextureClientPool) + TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, ISurfaceAllocator *aAllocator); - ~TextureClientPool(); /** * Gets an allocated TextureClient of size and format that are determined * by the initialisation parameters given to the pool. This will either be * a cached client that was returned to the pool, or a newly allocated * client if one isn't available. * * All clients retrieved by this method should be returned using the return
--- a/gfx/layers/client/TiledContentClient.h +++ b/gfx/layers/client/TiledContentClient.h @@ -42,20 +42,22 @@ namespace mozilla { namespace layers { class BasicTileDescriptor; class ClientTiledThebesLayer; class ClientLayerManager; // A class to help implement copy-on-write semantics for shared tiles. -class gfxSharedReadLock : public AtomicRefCounted<gfxSharedReadLock> { +class gfxSharedReadLock { +protected: + virtual ~gfxSharedReadLock() {} + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(gfxSharedReadLock) - virtual ~gfxSharedReadLock() {} + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxSharedReadLock) virtual int32_t ReadLock() = 0; virtual int32_t ReadUnlock() = 0; virtual int32_t GetReadCount() = 0; virtual bool IsValid() const = 0; enum gfxSharedReadLockType { TYPE_MEMORY,
--- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -774,17 +774,16 @@ APZCTreeManager::HandOffFling(AsyncPanZo ScreenPoint endPoint = startPoint + aVelocity; TransformDisplacement(this, aPrev, next, startPoint, endPoint); ScreenPoint transformedVelocity = endPoint - startPoint; // Tell |next| to start a fling with the transformed velocity. next->TakeOverFling(transformedVelocity); } - bool APZCTreeManager::FlushRepaintsForOverscrollHandoffChain() { MonitorAutoLock lock(mTreeLock); // to access mOverscrollHandoffChain if (mOverscrollHandoffChain.length() == 0) { return false; } for (uint32_t i = 0; i < mOverscrollHandoffChain.length(); i++) { @@ -792,16 +791,40 @@ APZCTreeManager::FlushRepaintsForOverscr if (item) { item->FlushRepaintForOverscrollHandoff(); } } return true; } bool +APZCTreeManager::CanBePanned(AsyncPanZoomController* aApzc) +{ + MonitorAutoLock lock(mTreeLock); // to access mOverscrollHandoffChain + + // Find |aApzc| in the handoff chain. + uint32_t i; + for (i = 0; i < mOverscrollHandoffChain.length(); ++i) { + if (mOverscrollHandoffChain[i] == aApzc) { + break; + } + } + + // See whether any APZC in the handoff chain starting from |aApzc| + // has room to be panned. + for (uint32_t j = i; j < mOverscrollHandoffChain.length(); ++j) { + if (mOverscrollHandoffChain[j]->IsPannable()) { + return true; + } + } + + return false; +} + +bool APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint) { MonitorAutoLock lock(mTreeLock); nsRefPtr<AsyncPanZoomController> target; // The root may have siblings, so check those too gfxPoint point(aPoint.x, aPoint.y); for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) { target = GetAPZCAtPoint(apzc, point);
--- a/gfx/layers/composite/APZCTreeManager.h +++ b/gfx/layers/composite/APZCTreeManager.h @@ -209,16 +209,17 @@ public: */ void GetAllowedTouchBehavior(WidgetInputEvent* aEvent, nsTArray<TouchBehaviorFlags>& aOutValues); /** * Sets allowed touch behavior values for current touch-session for specific apzc (determined by guid). * Should be invoked by the widget. Each value of the aValues arrays corresponds to the different * touch point that is currently active. + * Must be called after receiving the TOUCH_START event that starts the touch-session. */ void SetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, const nsTArray<TouchBehaviorFlags>& aValues); /** * This is a callback for AsyncPanZoomController to call when it wants to * scroll in response to a touch-move event, or when it needs to hand off * overscroll to the next APZC. Note that because of scroll grabbing, the @@ -266,16 +267,23 @@ public: * @param aApzc the APZC that is handing off the fling * @param aVelocity the current velocity of the fling, in |aApzc|'s screen * pixels per millisecond */ void HandOffFling(AsyncPanZoomController* aApzc, ScreenPoint aVelocity); bool FlushRepaintsForOverscrollHandoffChain(); + /** + * Determine whether |aApzc|, or any APZC along its overscroll handoff chain, + * has room to be panned. + * Expects the overscroll handoff chain to already be built. + */ + bool CanBePanned(AsyncPanZoomController* aApzc); + protected: // Protected destructor, to discourage deletion outside of Release(): virtual ~APZCTreeManager(); /** * Debug-build assertion that can be called to ensure code is running on the * compositor thread. */
--- a/gfx/layers/composite/AsyncCompositionManager.h +++ b/gfx/layers/composite/AsyncCompositionManager.h @@ -56,32 +56,31 @@ struct ViewTransform { /** * Manage async composition effects. This class is only used with OMTC and only * lives on the compositor thread. It is a layer on top of the layer manager * (LayerManagerComposite) which deals with elements of composition which are * usually dealt with by dom or layout when main thread rendering, but which can * short circuit that stuff to directly affect layers as they are composited, * for example, off-main thread animation, async video, async pan/zoom. */ -class AsyncCompositionManager MOZ_FINAL : public RefCounted<AsyncCompositionManager> +class AsyncCompositionManager MOZ_FINAL { friend class AutoResolveRefLayers; public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(AsyncCompositionManager) + NS_INLINE_DECL_REFCOUNTING(AsyncCompositionManager) + AsyncCompositionManager(LayerManagerComposite* aManager) : mLayerManager(aManager) , mIsFirstPaint(false) , mLayersUpdated(false) , mReadyForCompose(true) { - MOZ_COUNT_CTOR(AsyncCompositionManager); } ~AsyncCompositionManager() { - MOZ_COUNT_DTOR(AsyncCompositionManager); } /** * This forces the is-first-paint flag to true. This is intended to * be called by the widget code when it loses its viewport information * (or for whatever reason wants to refresh the viewport information). * The information refresh happens because the compositor will call * SetFirstPaintViewport on the next frame of composition.
--- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -51,28 +51,28 @@ class Compositor; class ISurfaceAllocator; class ThebesBufferData; class TiledLayerComposer; struct EffectChain; /** * A base class for doing CompositableHost and platform dependent task on TextureHost. */ -class CompositableBackendSpecificData : public RefCounted<CompositableBackendSpecificData> +class CompositableBackendSpecificData { +protected: + virtual ~CompositableBackendSpecificData() { } + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableBackendSpecificData) + NS_INLINE_DECL_REFCOUNTING(CompositableBackendSpecificData) + CompositableBackendSpecificData() { - MOZ_COUNT_CTOR(CompositableBackendSpecificData); } - virtual ~CompositableBackendSpecificData() - { - MOZ_COUNT_DTOR(CompositableBackendSpecificData); - } + virtual void SetCompositor(Compositor* aCompositor) {} virtual void ClearData() { mCurrentReleaseFenceTexture = nullptr; ClearPendingReleaseFenceTextureList(); } /** @@ -119,24 +119,25 @@ protected: * the layers transaction to update the Compositbale's textures from the * content side. The actual update (and any syncronous upload) is done by the * TextureHost, but it is coordinated by the CompositableHost. * * Composite is called by the owning layer when it is composited. CompositableHost * will use its TextureHost(s) and call Compositor::DrawQuad to do the actual * rendering. */ -class CompositableHost : public RefCounted<CompositableHost> +class CompositableHost { +protected: + virtual ~CompositableHost(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableHost) + NS_INLINE_DECL_REFCOUNTING(CompositableHost) CompositableHost(const TextureInfo& aTextureInfo); - virtual ~CompositableHost(); - static TemporaryRef<CompositableHost> Create(const TextureInfo& aTextureInfo); virtual CompositableType GetType() = 0; virtual CompositableBackendSpecificData* GetCompositableBackendSpecificData() { return mBackendData; }
--- a/gfx/layers/composite/TextRenderer.h +++ b/gfx/layers/composite/TextRenderer.h @@ -2,27 +2,29 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GFX_TextRenderer_H #define GFX_TextRenderer_H #include "mozilla/gfx/2D.h" +#include "nsISupportsImpl.h" #include <string> namespace mozilla { namespace layers { class Compositor; -class TextRenderer : public RefCounted<TextRenderer> +class TextRenderer { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(TextRenderer) + NS_INLINE_DECL_REFCOUNTING(TextRenderer) + TextRenderer(Compositor *aCompositor) : mCompositor(aCompositor) { } ~TextRenderer(); void RenderText(const std::string& aText, const gfx::IntPoint& aOrigin,
--- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -75,22 +75,25 @@ public: * TextureSource is the interface for texture objects that can be composited * by a given compositor backend. Since the drawing APIs are different * between backends, the TextureSource interface is split into different * interfaces (TextureSourceOGL, etc.), and TextureSource mostly provide * access to these interfaces. * * This class is used on the compositor side. */ -class TextureSource : public RefCounted<TextureSource> +class TextureSource { +protected: + virtual ~TextureSource(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureSource) + NS_INLINE_DECL_REFCOUNTING(TextureSource) + TextureSource(); - virtual ~TextureSource(); /** * Return the size of the texture in texels. * If this is a tile iterator, GetSize must return the size of the current tile. */ virtual gfx::IntSize GetSize() const = 0; /**
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -127,16 +127,17 @@ WidgetModifiersToDOMModifiers(mozilla::M } using namespace mozilla::css; namespace mozilla { namespace layers { typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior; +typedef GeckoContentController::APZStateChange APZStateChange; /* * The following prefs are used to control the behaviour of the APZC. * The default values are provided in gfxPrefs.h. * * "apz.allow-checkerboarding" * Pref that allows or disallows checkerboarding * @@ -415,19 +416,16 @@ AsyncPanZoomController::AsyncPanZoomCont mZoomConstraints(false, false, MIN_ZOOM, MAX_ZOOM), mLastSampleTime(GetFrameTime()), mState(NOTHING), mLastAsyncScrollTime(GetFrameTime()), mLastAsyncScrollOffset(0, 0), mCurrentAsyncScrollOffset(0, 0), mAsyncScrollTimeoutTask(nullptr), mHandlingTouchQueue(false), - mAllowedTouchBehaviorSet(false), - mPreventDefault(false), - mPreventDefaultSet(false), mTreeManager(aTreeManager), mScrollParentId(FrameMetrics::NULL_SCROLL_ID), mAPZCId(sAsyncPanZoomControllerCount++), mSharedFrameMetricsBuffer(nullptr), mSharedLock(nullptr) { MOZ_COUNT_CTOR(AsyncPanZoomController); @@ -493,31 +491,33 @@ AsyncPanZoomController::GetTouchStartTol } /* static */AsyncPanZoomController::AxisLockMode AsyncPanZoomController::GetAxisLockMode() { return static_cast<AxisLockMode>(gfxPrefs::APZAxisLockMode()); } nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent) { + if (aEvent.mInputType == MULTITOUCH_INPUT && + aEvent.AsMultiTouchInput().mType == MultiTouchInput::MULTITOUCH_START) { + // Starting a new touch block, clear old touch block state. + mTouchBlockState = TouchBlockState(); + } + // If we may have touch listeners and touch action property is enabled, we // enable the machinery that allows touch listeners to preventDefault any touch inputs // and also waits for the allowed touch behavior values to be received from the outside. // This should not happen unless there are actually touch listeners and touch-action property // enable as it introduces potentially unbounded lag because it causes a round-trip through // content. Usually, if content is responding in a timely fashion, this only introduces a // nearly constant few hundred ms of lag. if (mFrameMetrics.mMayHaveTouchListeners && aEvent.mInputType == MULTITOUCH_INPUT && (mState == NOTHING || mState == TOUCHING || IsPanningState(mState))) { const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput(); if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) { - mAllowedTouchBehaviors.Clear(); - mAllowedTouchBehaviorSet = false; - mPreventDefault = false; - mPreventDefaultSet = false; SetState(WAITING_CONTENT_RESPONSE); } } if (mState == WAITING_CONTENT_RESPONSE || mHandlingTouchQueue) { if (aEvent.mInputType == MULTITOUCH_INPUT) { const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput(); mTouchQueue.AppendElement(multiTouchInput); @@ -610,21 +610,28 @@ nsEventStatus AsyncPanZoomController::On RequestContentRepaint(); ScheduleComposite(); UpdateSharedCompositorFrameMetrics(); } // Fall through. case FLING: CancelAnimation(); // Fall through. - case NOTHING: + case NOTHING: { mX.StartTouch(point.x); mY.StartTouch(point.y); + APZCTreeManager* treeManagerLocal = mTreeManager; + if (treeManagerLocal) { + bool touchCanBePan = treeManagerLocal->CanBePanned(this); + mGeckoContentController->NotifyAPZStateChange( + GetGuid(), APZStateChange::StartTouch, touchCanBePan); + } SetState(TOUCHING); break; + } case TOUCHING: case PANNING: case PANNING_LOCKED_X: case PANNING_LOCKED_Y: case CROSS_SLIDING_X: case CROSS_SLIDING_Y: case PINCHING: case WAITING_CONTENT_RESPONSE: @@ -693,16 +700,18 @@ nsEventStatus AsyncPanZoomController::On } return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) { APZC_LOG("%p got a touch-end in state %d\n", this, mState); + OnTouchEndOrCancel(); + // In case no touch behavior triggered previously we can avoid sending // scroll events or requesting content repaint. This condition is added // to make tests consistent - in case touch-action is NONE (and therefore // no pans/zooms can be performed) we expected neither scroll or repaint // events. if (mState != NOTHING) { ReentrantMonitorAutoEnter lock(mMonitor); SendAsyncScrollEvent(); @@ -759,16 +768,17 @@ nsEventStatus AsyncPanZoomController::On break; } return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) { APZC_LOG("%p got a touch-cancel in state %d\n", this, mState); + OnTouchEndOrCancel(); SetState(NOTHING); return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) { APZC_LOG("%p got a scale-begin in state %d\n", this, mState); if (!TouchActionAllowZoom()) { @@ -924,56 +934,56 @@ nsEventStatus AsyncPanZoomController::On if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { controller->HandleLongTapUp(geckoScreenPoint, modifiers, GetGuid()); return nsEventStatus_eConsumeNoDefault; } } return nsEventStatus_eIgnore; } -nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) { - APZC_LOG("%p got a single-tap-up in state %d\n", this, mState); +nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) { nsRefPtr<GeckoContentController> controller = GetGeckoContentController(); - // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before - // sending event to content - if (controller && !mZoomConstraints.mAllowDoubleTapZoom) { - int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); + if (controller) { CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aPoint, &geckoScreenPoint)) { + int32_t modifiers = WidgetModifiersToDOMModifiers(aModifiers); // Because this may be being running as part of APZCTreeManager::ReceiveInputEvent, // calling controller->HandleSingleTap directly might mean that content receives // the single tap message before the corresponding touch-up. To avoid that we // schedule the singletap message to run on the next spin of the event loop. // See bug 965381 for the issue this was causing. controller->PostDelayedTask( NewRunnableMethod(controller.get(), &GeckoContentController::HandleSingleTap, geckoScreenPoint, modifiers, GetGuid()), 0); + mTouchBlockState.mSingleTapOccurred = true; return nsEventStatus_eConsumeNoDefault; } } return nsEventStatus_eIgnore; } +void AsyncPanZoomController::OnTouchEndOrCancel() { + mGeckoContentController->NotifyAPZStateChange( + GetGuid(), APZStateChange::EndTouch, mTouchBlockState.mSingleTapOccurred); +} + +nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) { + APZC_LOG("%p got a single-tap-up in state %d\n", this, mState); + // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before + // sending event to content + if (!mZoomConstraints.mAllowDoubleTapZoom) { + return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers); + } + return nsEventStatus_eIgnore; +} + nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) { APZC_LOG("%p got a single-tap-confirmed in state %d\n", this, mState); - nsRefPtr<GeckoContentController> controller = GetGeckoContentController(); - if (controller) { - int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); - CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { - // See comment in OnSingleTapUp as to why we do this in PostDelayedTask. - controller->PostDelayedTask( - NewRunnableMethod(controller.get(), &GeckoContentController::HandleSingleTap, - geckoScreenPoint, modifiers, GetGuid()), - 0); - return nsEventStatus_eConsumeNoDefault; - } - } - return nsEventStatus_eIgnore; + return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers); } nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) { APZC_LOG("%p got a double-tap in state %d\n", this, mState); nsRefPtr<GeckoContentController> controller = GetGeckoContentController(); if (controller) { if (mZoomConstraints.mAllowDoubleTapZoom) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); @@ -1087,25 +1097,27 @@ nsEventStatus AsyncPanZoomController::St double angle = atan2(dy, dx); // range [-pi, pi] angle = fabs(angle); // range [0, pi] if (mTouchActionPropertyEnabled) { HandlePanningWithTouchAction(angle, GetTouchBehavior(0)); } else { if (GetAxisLockMode() == FREE) { SetState(PANNING); - return nsEventStatus_eConsumeNoDefault; + } else { + HandlePanning(angle); } - - HandlePanning(angle); } + if (IsPanningState(mState)) { + mGeckoContentController->NotifyAPZStateChange(GetGuid(), APZStateChange::StartPanning); + return nsEventStatus_eConsumeNoDefault; + } // Don't consume an event that didn't trigger a panning. - return IsPanningState(mState) ? nsEventStatus_eConsumeNoDefault - : nsEventStatus_eIgnore; + return nsEventStatus_eIgnore; } void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent) { ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent); TimeDuration timeDelta = TimeDuration().FromMilliseconds(aEvent.mTime - mLastEventTime); // Probably a duplicate event, just throw it away. if (timeDelta.ToMilliseconds() <= EPSILON) { @@ -1440,16 +1452,21 @@ void AsyncPanZoomController::ScheduleCom } void AsyncPanZoomController::FlushRepaintForOverscrollHandoff() { ReentrantMonitorAutoEnter lock(mMonitor); RequestContentRepaint(); UpdateSharedCompositorFrameMetrics(); } +bool AsyncPanZoomController::IsPannable() const { + ReentrantMonitorAutoEnter lock(mMonitor); + return mX.HasRoomToPan() || mY.HasRoomToPan(); +} + void AsyncPanZoomController::RequestContentRepaint() { RequestContentRepaint(mFrameMetrics); } void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics) { aFrameMetrics.SetDisplayPortMargins( CalculatePendingDisplayPort(aFrameMetrics, GetVelocityVector(), @@ -1885,50 +1902,50 @@ void AsyncPanZoomController::ZoomToRect( // Schedule a repaint now, so the new displayport will be painted before the // animation finishes. RequestContentRepaint(endZoomToMetrics); } } void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) { - mPreventDefaultSet = true; - mPreventDefault = aPreventDefault; + mTouchBlockState.mPreventDefaultSet = true; + mTouchBlockState.mPreventDefault = aPreventDefault; CheckContentResponse(); } void AsyncPanZoomController::CheckContentResponse() { bool canProceedToTouchState = true; if (mFrameMetrics.mMayHaveTouchListeners) { - canProceedToTouchState &= mPreventDefaultSet; + canProceedToTouchState &= mTouchBlockState.mPreventDefaultSet; } if (mTouchActionPropertyEnabled) { - canProceedToTouchState &= mAllowedTouchBehaviorSet; + canProceedToTouchState &= mTouchBlockState.mAllowedTouchBehaviorSet; } if (!canProceedToTouchState) { return; } if (mContentResponseTimeoutTask) { mContentResponseTimeoutTask->Cancel(); mContentResponseTimeoutTask = nullptr; } if (mState == WAITING_CONTENT_RESPONSE) { - if (!mPreventDefault) { + if (!mTouchBlockState.mPreventDefault) { SetState(NOTHING); } mHandlingTouchQueue = true; while (!mTouchQueue.IsEmpty()) { - if (!mPreventDefault) { + if (!mTouchBlockState.mPreventDefault) { HandleInputEvent(mTouchQueue[0]); } if (mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_END || mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_CANCEL) { mTouchQueue.RemoveElementAt(0); break; } @@ -1942,66 +1959,66 @@ void AsyncPanZoomController::CheckConten bool AsyncPanZoomController::TouchActionAllowZoom() { if (!mTouchActionPropertyEnabled) { return true; } // Pointer events specification implies all touch points to allow zoom // to perform it. - for (size_t i = 0; i < mAllowedTouchBehaviors.Length(); i++) { - if (!(mAllowedTouchBehaviors[i] & AllowedTouchBehavior::ZOOM)) { + for (size_t i = 0; i < mTouchBlockState.mAllowedTouchBehaviors.Length(); i++) { + if (!(mTouchBlockState.mAllowedTouchBehaviors[i] & AllowedTouchBehavior::ZOOM)) { return false; } } return true; } AsyncPanZoomController::TouchBehaviorFlags AsyncPanZoomController::GetTouchBehavior(uint32_t touchIndex) { - if (touchIndex < mAllowedTouchBehaviors.Length()) { - return mAllowedTouchBehaviors[touchIndex]; + if (touchIndex < mTouchBlockState.mAllowedTouchBehaviors.Length()) { + return mTouchBlockState.mAllowedTouchBehaviors[touchIndex]; } return DefaultTouchBehavior; } AsyncPanZoomController::TouchBehaviorFlags AsyncPanZoomController::GetAllowedTouchBehavior(ScreenIntPoint& aPoint) { // Here we need to perform a hit testing over the touch-action regions attached to the // layer associated with current apzc. // Currently they are in progress, for more info see bug 928833. return AllowedTouchBehavior::UNKNOWN; } void AsyncPanZoomController::SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors) { - mAllowedTouchBehaviors.Clear(); - mAllowedTouchBehaviors.AppendElements(aBehaviors); - mAllowedTouchBehaviorSet = true; + mTouchBlockState.mAllowedTouchBehaviors.Clear(); + mTouchBlockState.mAllowedTouchBehaviors.AppendElements(aBehaviors); + mTouchBlockState.mAllowedTouchBehaviorSet = true; CheckContentResponse(); } void AsyncPanZoomController::SetState(PanZoomState aNewState) { PanZoomState oldState; // Intentional scoping for mutex { ReentrantMonitorAutoEnter lock(mMonitor); oldState = mState; mState = aNewState; } if (mGeckoContentController) { if (!IsTransformingState(oldState) && IsTransformingState(aNewState)) { - mGeckoContentController->NotifyTransformBegin( - ScrollableLayerGuid(mLayersId, mFrameMetrics.mPresShellId, mFrameMetrics.GetScrollId())); + mGeckoContentController->NotifyAPZStateChange( + GetGuid(), APZStateChange::TransformBegin); } else if (IsTransformingState(oldState) && !IsTransformingState(aNewState)) { - mGeckoContentController->NotifyTransformEnd( - ScrollableLayerGuid(mLayersId, mFrameMetrics.mPresShellId, mFrameMetrics.GetScrollId())); + mGeckoContentController->NotifyAPZStateChange( + GetGuid(), APZStateChange::TransformEnd); } } } bool AsyncPanZoomController::IsTransformingState(PanZoomState aState) { return !(aState == NOTHING || aState == TOUCHING || aState == WAITING_CONTENT_RESPONSE); }
--- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -310,16 +310,18 @@ public: * is done we should integrate its logic here. */ TouchBehaviorFlags GetAllowedTouchBehavior(ScreenIntPoint& aPoint); /** * Sets allowed touch behavior for current touch session. * This method is invoked by the APZCTreeManager which in its turn invoked by * the widget after performing touch-action values retrieving. + * Must be called after receiving the TOUCH_START even that started the + * touch session. */ void SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors); /** * Returns whether this APZC is for an element marked with the 'scrollgrab' * attribute. */ bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; } @@ -327,16 +329,21 @@ public: /** * Set an extra offset for testing async scrolling. */ void SetTestAsyncScrollOffset(const CSSPoint& aPoint) { mTestAsyncScrollOffset = aPoint; } + /** + * Returns whether this APZC has room to be panned (in any direction). + */ + bool IsPannable() const; + protected: // Protected destructor, to discourage deletion outside of Release(): ~AsyncPanZoomController(); /** * Helper method for touches beginning. Sets everything up for panning and any * multitouch gestures. */ @@ -552,16 +559,46 @@ private: PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */ ANIMATING_ZOOM, /* animated zoom to a new rect */ WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has put a finger down, but we don't yet know if a touch listener has prevented the default actions yet and the allowed touch behavior was not set yet. we still need to abort animations. */ }; + // State related to a single touch block. Does not persist across touch blocks. + struct TouchBlockState { + + TouchBlockState() + : mAllowedTouchBehaviorSet(false), + mPreventDefault(false), + mPreventDefaultSet(false), + mSingleTapOccurred(false) + {} + + // Values of allowed touch behavior for touch points of this touch block. + // Since there are maybe a few current active touch points per time (multitouch case) + // and each touch point should have its own value of allowed touch behavior- we're + // keeping an array of allowed touch behavior values, not the single value. + nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors; + + // Specifies whether mAllowedTouchBehaviors is set for this touch events block. + bool mAllowedTouchBehaviorSet; + + // Flag used to specify that content prevented the default behavior of this + // touch events block. + bool mPreventDefault; + + // Specifies whether mPreventDefault property is set for this touch events block. + bool mPreventDefaultSet; + + // Specifies whether a single tap event was generated during this touch block. + bool mSingleTapOccurred; + }; + /* * Returns whether current touch behavior values allow zooming. */ bool TouchActionAllowZoom(); /* * Returns allowed touch behavior from the mAllowedTouchBehavior array. * In case apzc didn't receive touch behavior values within the timeout @@ -612,16 +649,22 @@ private: // coordinates but the composition bounds is in parent layer coordinates. ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint); // Update mFrameMetrics.mTransformScale. This should be called whenever // our CSS transform or the non-transient part of our async transform // changes, as it corresponds to the scale portion of those transforms. void UpdateTransformScale(); + // Helper function for OnSingleTapUp() and OnSingleTapConfirmed(). + nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers); + + // Common processing at the end of a touch block. + void OnTouchEndOrCancel(); + uint64_t mLayersId; nsRefPtr<CompositorParent> mCompositorParent; PCompositorParent* mCrossProcessCompositorParent; TaskThrottler mPaintThrottler; /* Access to the following two fields is protected by the mRefPtrMonitor, since they are accessed on the UI thread but can be cleared on the compositor thread. */ @@ -638,17 +681,19 @@ protected: // monitor. Do not read from or modify either of them without locking. FrameMetrics mFrameMetrics; // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|. // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the // monitor should be held. When setting |mState|, either the SetState() // function can be used, or the monitor can be held and then |mState| updated. // IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h. - ReentrantMonitor mMonitor; + // This is mutable to allow entering it from 'const' methods; doing otherwise + // would significantly limit what methods could be 'const'. + mutable ReentrantMonitor mMonitor; // Specifies whether we should use touch-action css property. Initialized from // the preferences. This property (in comparison with the global one) simplifies // testing apzc with (and without) touch-action property enabled concurrently // (e.g. with the gtest framework). bool mTouchActionPropertyEnabled; private: @@ -713,31 +758,18 @@ private: CancelableTask* mAsyncScrollTimeoutTask; // Flag used to determine whether or not we should try to enter the // WAITING_LISTENERS state. This is used in the case that we are processing a // queued up event block. If set, this means that we are handling this queue // and we don't want to queue the events back up again. bool mHandlingTouchQueue; - // Values of allowed touch behavior for current touch points. - // Since there are maybe a few current active touch points per time (multitouch case) - // and each touch point should have its own value of allowed touch behavior- we're - // keeping an array of allowed touch behavior values, not the single value. - nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors; - - // Specifies whether mAllowedTouchBehaviors is set for current touch events block. - bool mAllowedTouchBehaviorSet; - - // Flag used to specify that content prevented the default behavior of the current - // touch events block. - bool mPreventDefault; - - // Specifies whether mPreventDefault property is set for current touch events block. - bool mPreventDefaultSet; + // Stores information about the current touch block. + TouchBlockState mTouchBlockState; // Extra offset to add in SampleContentTransformForFrame for testing CSSPoint mTestAsyncScrollOffset; RefPtr<AsyncPanZoomAnimation> mAnimation; friend class Axis; friend class FlingAnimation;
--- a/gfx/layers/ipc/Axis.cpp +++ b/gfx/layers/ipc/Axis.cpp @@ -202,89 +202,95 @@ float Axis::ScaleWillOverscrollAmount(fl float Axis::GetVelocity() { return mAxisLocked ? 0 : mVelocity; } void Axis::SetVelocity(float aVelocity) { mVelocity = aVelocity; } -float Axis::GetCompositionEnd() { +float Axis::GetCompositionEnd() const { return GetOrigin() + GetCompositionLength(); } -float Axis::GetPageEnd() { +float Axis::GetPageEnd() const { return GetPageStart() + GetPageLength(); } -float Axis::GetOrigin() { +float Axis::GetOrigin() const { CSSPoint origin = mAsyncPanZoomController->GetFrameMetrics().GetScrollOffset(); return GetPointOffset(origin); } -float Axis::GetCompositionLength() { +float Axis::GetCompositionLength() const { const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics(); return GetRectLength(metrics.CalculateCompositedRectInCssPixels()); } -float Axis::GetPageStart() { +float Axis::GetPageStart() const { CSSRect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect; return GetRectOffset(pageRect); } -float Axis::GetPageLength() { +float Axis::GetPageLength() const { CSSRect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect; return GetRectLength(pageRect); } bool Axis::ScaleWillOverscrollBothSides(float aScale) { const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics(); CSSToParentLayerScale scale(metrics.GetZoomToParent().scale * aScale); CSSRect cssCompositionBounds = metrics.mCompositionBounds / scale; return GetRectLength(metrics.mScrollableRect) < GetRectLength(cssCompositionBounds); } +bool Axis::HasRoomToPan() const { + return GetOrigin() > GetPageStart() + || GetCompositionEnd() < GetPageEnd(); +} + + AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController) : Axis(aAsyncPanZoomController) { } -float AxisX::GetPointOffset(const CSSPoint& aPoint) +float AxisX::GetPointOffset(const CSSPoint& aPoint) const { return aPoint.x; } -float AxisX::GetRectLength(const CSSRect& aRect) +float AxisX::GetRectLength(const CSSRect& aRect) const { return aRect.width; } -float AxisX::GetRectOffset(const CSSRect& aRect) +float AxisX::GetRectOffset(const CSSRect& aRect) const { return aRect.x; } AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController) : Axis(aAsyncPanZoomController) { } -float AxisY::GetPointOffset(const CSSPoint& aPoint) +float AxisY::GetPointOffset(const CSSPoint& aPoint) const { return aPoint.y; } -float AxisY::GetRectLength(const CSSRect& aRect) +float AxisY::GetRectLength(const CSSRect& aRect) const { return aRect.height; } -float AxisY::GetRectOffset(const CSSRect& aRect) +float AxisY::GetRectOffset(const CSSRect& aRect) const { return aRect.y; } } }
--- a/gfx/layers/ipc/Axis.h +++ b/gfx/layers/ipc/Axis.h @@ -165,50 +165,55 @@ public: * Checks if an axis will overscroll in both directions by computing the * content rect and checking that its height/width (depending on the axis) * does not overextend past the viewport. * * This gets called by ScaleWillOverscroll(). */ bool ScaleWillOverscrollBothSides(float aScale); - float GetOrigin(); - float GetCompositionLength(); - float GetPageStart(); - float GetPageLength(); - float GetCompositionEnd(); - float GetPageEnd(); + /** + * Returns whether there is room to pan on this axis in either direction. + */ + bool HasRoomToPan() const; + + float GetOrigin() const; + float GetCompositionLength() const; + float GetPageStart() const; + float GetPageLength() const; + float GetCompositionEnd() const; + float GetPageEnd() const; int32_t GetPos() const { return mPos; } - virtual float GetPointOffset(const CSSPoint& aPoint) = 0; - virtual float GetRectLength(const CSSRect& aRect) = 0; - virtual float GetRectOffset(const CSSRect& aRect) = 0; + virtual float GetPointOffset(const CSSPoint& aPoint) const = 0; + virtual float GetRectLength(const CSSRect& aRect) const = 0; + virtual float GetRectOffset(const CSSRect& aRect) const = 0; protected: int32_t mPos; int32_t mStartPos; float mVelocity; bool mAxisLocked; // Whether movement on this axis is locked. AsyncPanZoomController* mAsyncPanZoomController; nsTArray<float> mVelocityQueue; }; class AxisX : public Axis { public: AxisX(AsyncPanZoomController* mAsyncPanZoomController); - virtual float GetPointOffset(const CSSPoint& aPoint); - virtual float GetRectLength(const CSSRect& aRect); - virtual float GetRectOffset(const CSSRect& aRect); + virtual float GetPointOffset(const CSSPoint& aPoint) const; + virtual float GetRectLength(const CSSRect& aRect) const; + virtual float GetRectOffset(const CSSRect& aRect) const; }; class AxisY : public Axis { public: AxisY(AsyncPanZoomController* mAsyncPanZoomController); - virtual float GetPointOffset(const CSSPoint& aPoint); - virtual float GetRectLength(const CSSRect& aRect); - virtual float GetRectOffset(const CSSRect& aRect); + virtual float GetPointOffset(const CSSPoint& aPoint) const; + virtual float GetRectLength(const CSSRect& aRect) const; + virtual float GetRectOffset(const CSSRect& aRect) const; }; } } #endif
--- a/gfx/layers/ipc/GeckoContentController.h +++ b/gfx/layers/ipc/GeckoContentController.h @@ -108,27 +108,58 @@ public: * APZ can then get the correct touch-sensitive region for each frame * directly from the layer. */ virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) { return false; } + MOZ_BEGIN_NESTED_ENUM_CLASS(APZStateChange, int8_t) + /** + * APZ started modifying the view (including panning, zooming, and fling). + */ + TransformBegin, + /** + * APZ finished modifying the view. + */ + TransformEnd, + /** + * APZ started a touch. + * |aArg| is 1 if touch can be a pan, 0 otherwise. + */ + StartTouch, + /** + * APZ started a pan. + */ + StartPanning, + /** + * APZ finished processing a touch. + * |aArg| is 1 if touch was a click, 0 otherwise. + */ + EndTouch, + APZStateChangeSentinel + MOZ_END_NESTED_ENUM_CLASS(APZStateChange) + /** - * General tranformation notices for consumers. These fire any time - * the apzc is modifying the view, including panning, zooming, and - * fling. + * General notices of APZ state changes for consumers. + * |aGuid| identifies the APZC originating the state change. + * |aChange| identifies the type of state change + * |aArg| is used by some state changes to pass extra information (see + * the documentation for each state change above) */ - virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid) {} - virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid) {} + virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, + APZStateChange aChange, + int aArg = 0) {} GeckoContentController() {} protected: // Protected destructor, to discourage deletion outside of Release(): virtual ~GeckoContentController() {} }; +MOZ_FINISH_NESTED_ENUM_CLASS(GeckoContentController::APZStateChange) + } } #endif // mozilla_layers_GeckoContentController_h
--- a/gfx/layers/ipc/LayerTransactionChild.h +++ b/gfx/layers/ipc/LayerTransactionChild.h @@ -18,38 +18,35 @@ namespace mozilla { namespace layout { class RenderFrameChild; } namespace layers { class LayerTransactionChild : public PLayerTransactionChild - , public AtomicRefCounted<LayerTransactionChild> { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(LayerTransactionChild) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LayerTransactionChild) /** * Clean this up, finishing with Send__delete__(). * * It is expected (checked with an assert) that all shadow layers * created by this have already been destroyed and * Send__delete__()d by the time this method is called. */ void Destroy(); bool IPCOpen() const { return mIPCOpen; } protected: LayerTransactionChild() : mIPCOpen(false) {} ~LayerTransactionChild() { } - friend class AtomicRefCounted<LayerTransactionChild>; - friend class detail::RefCounted<LayerTransactionChild, detail::AtomicRefCount>; virtual PGrallocBufferChild* AllocPGrallocBufferChild(const IntSize&, const uint32_t&, const uint32_t&, MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE; virtual bool DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
--- a/gfx/layers/opengl/CompositorOGL.h +++ b/gfx/layers/opengl/CompositorOGL.h @@ -59,22 +59,23 @@ struct EffectChain; * Interface for pools of temporary gl textures for the compositor. * The textures are fully owned by the pool, so the latter is responsible * calling fDeleteTextures accordingly. * Users of GetTexture receive a texture that is only valid for the duration * of the current frame. * This is primarily intended for direct texturing APIs that need to attach * shared objects (such as an EGLImage) to a gl texture. */ -class CompositorTexturePoolOGL : public RefCounted<CompositorTexturePoolOGL> +class CompositorTexturePoolOGL { +protected: + virtual ~CompositorTexturePoolOGL() {} + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorTexturePoolOGL) - - virtual ~CompositorTexturePoolOGL() {} + NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL) virtual void Clear() = 0; virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0; virtual void EndFrame() = 0; };
--- a/gfx/src/FilterSupport.cpp +++ b/gfx/src/FilterSupport.cpp @@ -225,20 +225,20 @@ namespace FilterWrappers { // A class that wraps a FilterNode and handles conversion between different // color models. Create FilterCachedColorModels with your original filter and // the color model that this filter outputs in natively, and then call // ->ForColorModel(colorModel) in order to get a FilterNode which outputs to // the specified colorModel. // Internally, this is achieved by wrapping the original FilterNode with // conversion FilterNodes. These filter nodes are cached in such a way that no // repeated or back-and-forth conversions happen. -class FilterCachedColorModels : public RefCounted<FilterCachedColorModels> +class FilterCachedColorModels { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(FilterCachedColorModels) + NS_INLINE_DECL_REFCOUNTING(FilterCachedColorModels) // aFilter can be null. In that case, ForColorModel will return a non-null // completely transparent filter for all color models. FilterCachedColorModels(DrawTarget* aDT, FilterNode* aFilter, ColorModel aOriginalColorModel); // Get a FilterNode for the specified color model, guaranteed to be non-null. TemporaryRef<FilterNode> ForColorModel(ColorModel aColorModel);
--- a/gfx/src/nsRenderingContext.h +++ b/gfx/src/nsRenderingContext.h @@ -29,25 +29,24 @@ struct nsRect; typedef enum { nsLineStyle_kNone = 0, nsLineStyle_kSolid = 1, nsLineStyle_kDashed = 2, nsLineStyle_kDotted = 3 } nsLineStyle; -class nsRenderingContext +class nsRenderingContext MOZ_FINAL { typedef mozilla::gfx::UserData UserData; typedef mozilla::gfx::UserDataKey UserDataKey; typedef mozilla::gfx::DrawTarget DrawTarget; public: nsRenderingContext() : mP2A(0.) {} - // ~nsRenderingContext() {} NS_INLINE_DECL_REFCOUNTING(nsRenderingContext) void Init(nsDeviceContext* aContext, gfxASurface* aThebesSurface); void Init(nsDeviceContext* aContext, gfxContext* aThebesContext); void Init(nsDeviceContext* aContext, DrawTarget* aDrawTarget); // These accessors will never return null. @@ -125,17 +124,22 @@ public: } void *GetUserData(UserDataKey *key) { return mUserData.Get(key); } void *RemoveUserData(UserDataKey *key) { return mUserData.Remove(key); } -protected: +private: + // Private destructor, to discourage deletion outside of Release(): + ~nsRenderingContext() + { + } + int32_t GetMaxChunkLength(); nsRefPtr<gfxContext> mThebes; nsRefPtr<nsDeviceContext> mDeviceContext; nsRefPtr<nsFontMetrics> mFontMetrics; double mP2A; // cached app units per device pixel value
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -163,17 +163,24 @@ FrameMetrics TestFrameMetrics() { return fm; } /* * Dispatches mock touch events to the apzc and checks whether apzc properly * consumed them and triggered scrolling behavior. */ static -void ApzcPan(AsyncPanZoomController* apzc, TestAPZCTreeManager* aTreeManager, int& aTime, int aTouchStartY, int aTouchEndY, bool expectIgnoredPan = false, bool hasTouchListeners = false) { +void ApzcPan(AsyncPanZoomController* apzc, + TestAPZCTreeManager* aTreeManager, + int& aTime, + int aTouchStartY, + int aTouchEndY, + bool expectIgnoredPan = false, + bool hasTouchListeners = false, + nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr) { const int TIME_BETWEEN_TOUCH_EVENT = 100; const int OVERCOME_TOUCH_TOLERANCE = 100; MultiTouchInput mti; nsEventStatus status; // Since we're passing inputs directly to the APZC instead of going through // the tree manager, we need to build the overscroll handoff chain explicitly @@ -193,16 +200,21 @@ void ApzcPan(AsyncPanZoomController* apz mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, 0); aTime += TIME_BETWEEN_TOUCH_EVENT; // Make sure the move is large enough to not be handled as a tap mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchStartY+OVERCOME_TOUCH_TOLERANCE), ScreenSize(0, 0), 0, 0)); status = apzc->ReceiveInputEvent(mti); EXPECT_EQ(status, touchStartStatus); // APZC should be in TOUCHING state + // Allowed touch behaviours must be set after sending touch-start. + if (aAllowedTouchBehaviors) { + apzc->SetAllowedTouchBehavior(*aAllowedTouchBehaviors); + } + nsEventStatus touchMoveStatus; if (expectIgnoredPan) { // APZC should ignore panning, be in TOUCHING state and therefore return eIgnore. // The same applies to all consequent touch move events. touchMoveStatus = nsEventStatus_eIgnore; } else { // APZC should go into the panning state and therefore consume the event. touchMoveStatus = nsEventStatus_eConsumeNoDefault; @@ -249,35 +261,33 @@ void DoPanTest(bool aShouldTriggerScroll } int time = 0; int touchStart = 50; int touchEnd = 10; ScreenPoint pointOut; ViewTransform viewTransformOut; - nsTArray<uint32_t> values; - values.AppendElement(aBehavior); + nsTArray<uint32_t> allowedTouchBehaviors; + allowedTouchBehaviors.AppendElement(aBehavior); // Pan down - apzc->SetAllowedTouchBehavior(values); - ApzcPan(apzc, tm, time, touchStart, touchEnd, !aShouldTriggerScroll); + ApzcPan(apzc, tm, time, touchStart, touchEnd, !aShouldTriggerScroll, false, &allowedTouchBehaviors); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); if (aShouldTriggerScroll) { EXPECT_EQ(pointOut, ScreenPoint(0, -(touchEnd-touchStart))); EXPECT_NE(viewTransformOut, ViewTransform()); } else { EXPECT_EQ(pointOut, ScreenPoint()); EXPECT_EQ(viewTransformOut, ViewTransform()); } // Pan back - apzc->SetAllowedTouchBehavior(values); - ApzcPan(apzc, tm, time, touchEnd, touchStart, !aShouldTriggerScroll); + ApzcPan(apzc, tm, time, touchEnd, touchStart, !aShouldTriggerScroll, false, &allowedTouchBehaviors); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(pointOut, ScreenPoint()); EXPECT_EQ(viewTransformOut, ViewTransform()); apzc->Destroy(); } @@ -608,21 +618,20 @@ TEST_F(AsyncPanZoomControllerTester, Pan int time = 0; int touchStart = 50; int touchEnd = 10; ScreenPoint pointOut; ViewTransform viewTransformOut; // Pan down - nsTArray<uint32_t> values; - values.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN); + nsTArray<uint32_t> allowedTouchBehaviors; + allowedTouchBehaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN); apzc->SetTouchActionEnabled(true); - apzc->SetAllowedTouchBehavior(values); - ApzcPan(apzc, tm, time, touchStart, touchEnd, true, true); + ApzcPan(apzc, tm, time, touchStart, touchEnd, true, true, &allowedTouchBehaviors); // Send the signal that content has handled and preventDefaulted the touch // events. This flushes the event queue. apzc->ContentReceivedTouch(true); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(pointOut, ScreenPoint()); EXPECT_EQ(viewTransformOut, ViewTransform()); @@ -741,26 +750,28 @@ DoLongPressTest(bool aShouldUseTouchActi nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager(); nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController( 0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR); apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0))); - nsTArray<uint32_t> values; - values.AppendElement(aBehavior); apzc->SetTouchActionEnabled(aShouldUseTouchAction); - apzc->SetAllowedTouchBehavior(values); int time = 0; nsEventStatus status = ApzcDown(apzc, 10, 10, time); EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status); + // SetAllowedTouchBehavior() must be called after sending touch-start. + nsTArray<uint32_t> allowedTouchBehaviors; + allowedTouchBehaviors.AppendElement(aBehavior); + apzc->SetAllowedTouchBehavior(allowedTouchBehaviors); + MockFunction<void(std::string checkPointName)> check; { InSequence s; EXPECT_CALL(check, Call("preHandleLongTap")); EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1); EXPECT_CALL(check, Call("postHandleLongTap"));
--- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -68,22 +68,24 @@ #include "nsCRT.h" #include "GLContext.h" #include "GLContextProvider.h" #ifdef MOZ_WIDGET_ANDROID #include "TexturePoolOGL.h" #endif +#include "mozilla/Hal.h" #ifdef USE_SKIA -#include "mozilla/Hal.h" #include "skia/SkGraphics.h" #include "SkiaGLGlue.h" - +#else +class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted { +}; #endif #include "mozilla/Preferences.h" #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/Mutex.h" #include "nsIGfxInfo.h" @@ -923,17 +925,19 @@ gfxPlatform::InitializeSkiaCacheLimits() cacheSizeLimit = totalMemory / 16; } } #ifdef DEBUG printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit); #endif +#ifdef USE_SKIA_GPU mSkiaGlue->GetGrContext()->setTextureCacheLimits(cacheItemLimit, cacheSizeLimit); +#endif } } mozilla::gl::SkiaGLGlue* gfxPlatform::GetSkiaGLGlue() { #ifdef USE_SKIA_GPU if (!mSkiaGlue) {
--- a/hal/HalWakeLock.cpp +++ b/hal/HalWakeLock.cpp @@ -7,17 +7,17 @@ #include "mozilla/HalWakeLock.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" #include "mozilla/dom/ContentParent.h" #include "nsClassHashtable.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "nsIPropertyBag2.h" -#include "nsObserverService.h" +#include "nsIObserverService.h" using namespace mozilla; using namespace mozilla::hal; namespace { struct LockCount { LockCount()
--- a/hal/cocoa/CocoaBattery.cpp +++ b/hal/cocoa/CocoaBattery.cpp @@ -7,17 +7,18 @@ #import <CoreFoundation/CoreFoundation.h> #import <IOKit/ps/IOPowerSources.h> #import <IOKit/ps/IOPSKeys.h> #include <mozilla/Hal.h> #include <mozilla/dom/battery/Constants.h> #include <mozilla/Services.h> -#include <nsObserverService.h> +#include <nsIObserverService.h> +#include <nsIObserver.h> #include <dlfcn.h> #define IOKIT_FRAMEWORK_PATH "/System/Library/Frameworks/IOKit.framework/IOKit" #ifndef kIOPSTimeRemainingUnknown #define kIOPSTimeRemainingUnknown ((CFTimeInterval)-1.0) #endif
--- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -289,21 +289,21 @@ public: hal::NotifyBatteryChange(info); return NS_OK; } }; } // anonymous namespace -class BatteryObserver : public IUeventObserver, - public RefCounted<BatteryObserver> +class BatteryObserver : public IUeventObserver { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(BatteryObserver) + NS_INLINE_DECL_REFCOUNTING(BatteryObserver) + BatteryObserver() :mUpdater(new BatteryUpdater()) { } virtual void Notify(const NetlinkEvent &aEvent) { // this will run on IO thread
--- a/hal/gonk/GonkSwitch.cpp +++ b/hal/gonk/GonkSwitch.cpp @@ -46,20 +46,21 @@ namespace hal_impl { * change@/devices/virtual/switch/usb_configuration * ACTION=change * DEVPATH=/devices/virtual/switch/usb_configuration * SUBSYSTEM=switch * SWITCH_NAME=usb_configuration * SWITCH_STATE=0 * SEQNUM=5038 */ -class SwitchHandler : public RefCounted<SwitchHandler> +class SwitchHandler { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(SwitchHandler) + NS_INLINE_DECL_REFCOUNTING(SwitchHandler) + SwitchHandler(const char* aDevPath, SwitchDevice aDevice) : mDevPath(aDevPath), mState(SWITCH_STATE_UNKNOWN), mDevice(aDevice) { GetInitialState(); } @@ -225,31 +226,30 @@ public: { NotifySwitchChange(mEvent); return NS_OK; } private: SwitchEvent mEvent; }; -class SwitchEventObserver : public IUeventObserver, - public RefCounted<SwitchEventObserver> +class SwitchEventObserver MOZ_FINAL : public IUeventObserver { + ~SwitchEventObserver() + { + mHandler.Clear(); + } + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(SwitchEventObserver) + NS_INLINE_DECL_REFCOUNTING(SwitchEventObserver) SwitchEventObserver() : mEnableCount(0) { Init(); } - ~SwitchEventObserver() - { - mHandler.Clear(); - } - int GetEnableCount() { return mEnableCount; } void EnableSwitch(SwitchDevice aDevice) { mEventInfo[aDevice].mEnabled = true;
--- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -8,16 +8,18 @@ %{C++ #include "gfxImageSurface.h" #include "gfxContext.h" #include "gfxMatrix.h" #include "gfxRect.h" #include "GraphicsFilter.h" #include "gfxASurface.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "nsRect.h" #include "nsSize.h" #include "limits.h" namespace mozilla { namespace layers { class LayerManager; class ImageContainer; @@ -50,27 +52,27 @@ native gfxGraphicsFilter(GraphicsFilter) [ref] native nsIntSize(nsIntSize); native nsSize(nsSize); [ptr] native nsIFrame(nsIFrame); [ptr] native ImageContainer(mozilla::layers::ImageContainer); [ptr] native LayerManager(mozilla::layers::LayerManager); native Orientation(mozilla::image::Orientation); [ref] native TimeStamp(mozilla::TimeStamp); [ptr] native SVGImageContext(mozilla::SVGImageContext); -native already_AddRefed_gfxASurface(already_AddRefed<gfxASurface>); +native TempRefSourceSurface(mozilla::TemporaryRef<mozilla::gfx::SourceSurface>); /** * imgIContainer is the interface that represents an image. It allows * access to frames as Thebes surfaces. It also allows drawing of images * onto Thebes contexts. * * Internally, imgIContainer also manages animation of images. */ -[scriptable, builtinclass, uuid(8b7db7dd-bfe9-40d3-9114-3a79c0658afd)] +[scriptable, builtinclass, uuid(503a830c-734d-4362-91f6-73f83ac59646)] interface imgIContainer : nsISupports { /** * The width of the container rectangle. In the case of any error, * zero is returned, and an exception will be thrown. */ readonly attribute int32_t width; @@ -145,16 +147,17 @@ interface imgIContainer : nsISupports */ const long FLAG_NONE = 0x0; const long FLAG_SYNC_DECODE = 0x1; const long FLAG_DECODE_NO_PREMULTIPLY_ALPHA = 0x2; const long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x4; const long FLAG_CLAMP = 0x8; const long FLAG_HIGH_QUALITY_SCALING = 0x10; + const long FLAG_WANT_DATA_SURFACE = 0x20; /** * Constants for specifying various "special" frames. * * FRAME_FIRST: The first frame * FRAME_CURRENT: The current frame * * FRAME_MAX_VALUE should be set to the value of the maximum constant above, @@ -168,19 +171,18 @@ interface imgIContainer : nsISupports * Get a surface for the given frame. This may be a platform-native, * optimized surface, so you cannot inspect its pixel data. If you * need that, use gfxASurface::GetAsReadableARGB32ImageSurface or * gfxASurface::CopyToARGB32ImageSurface. * * @param aWhichFrame Frame specifier of the FRAME_* variety. * @param aFlags Flags of the FLAG_* variety */ - [noscript, notxpcom] already_AddRefed_gfxASurface - getFrame(in uint32_t aWhichFrame, - in uint32_t aFlags); + [noscript, notxpcom] TempRefSourceSurface getFrame(in uint32_t aWhichFrame, + in uint32_t aFlags); /** * Whether the given frame is opaque; that is, needs the background painted * behind it. * * @param aWhichFrame Frame specifier of the FRAME_* variety. */ [notxpcom] boolean frameIsOpaque(in uint32_t aWhichFrame);
--- a/image/src/ClippedImage.cpp +++ b/image/src/ClippedImage.cpp @@ -1,31 +1,35 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gfxDrawable.h" #include "gfxPlatform.h" #include "gfxUtils.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "ClippedImage.h" #include "Orientation.h" #include "SVGImageContext.h" +using namespace mozilla; +using namespace mozilla::gfx; using mozilla::layers::LayerManager; using mozilla::layers::ImageContainer; namespace mozilla { namespace image { class ClippedImageCachedSurface { public: - ClippedImageCachedSurface(mozilla::gfx::DrawTarget* aSurface, + ClippedImageCachedSurface(TemporaryRef<SourceSurface> aSurface, const nsIntSize& aViewportSize, const SVGImageContext* aSVGContext, float aFrame, uint32_t aFlags) : mSurface(aSurface) , mViewportSize(aViewportSize) , mFrame(aFrame) , mFlags(aFlags) @@ -44,23 +48,22 @@ public: bool matchesSVGContext = (!aSVGContext && mSVGContext.empty()) || *aSVGContext == mSVGContext.ref(); return mViewportSize == aViewportSize && matchesSVGContext && mFrame == aFrame && mFlags == aFlags; } - already_AddRefed<gfxASurface> Surface() { - nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mSurface); - return surf.forget(); + TemporaryRef<SourceSurface> Surface() { + return mSurface; } private: - nsRefPtr<mozilla::gfx::DrawTarget> mSurface; + RefPtr<SourceSurface> mSurface; const nsIntSize mViewportSize; Maybe<SVGImageContext> mSVGContext; const float mFrame; const uint32_t mFlags; }; class DrawSingleTileCallback : public gfxDrawingCallback { @@ -204,62 +207,60 @@ ClippedImage::GetIntrinsicRatio(nsSize* if (!ShouldClip()) { return InnerImage()->GetIntrinsicRatio(aRatio); } *aRatio = nsSize(mClip.width, mClip.height); return NS_OK; } -NS_IMETHODIMP_(already_AddRefed<gfxASurface>) +NS_IMETHODIMP_(TemporaryRef<SourceSurface>) ClippedImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { return GetFrameInternal(mClip.Size(), nullptr, aWhichFrame, aFlags); } -already_AddRefed<gfxASurface> +TemporaryRef<SourceSurface> ClippedImage::GetFrameInternal(const nsIntSize& aViewportSize, const SVGImageContext* aSVGContext, uint32_t aWhichFrame, uint32_t aFlags) { if (!ShouldClip()) { return InnerImage()->GetFrame(aWhichFrame, aFlags); } float frameToDraw = InnerImage()->GetFrameIndex(aWhichFrame); if (!mCachedSurface || !mCachedSurface->Matches(aViewportSize, aSVGContext, frameToDraw, aFlags)) { // Create a surface to draw into. - mozilla::RefPtr<mozilla::gfx::DrawTarget> target; - nsRefPtr<gfxContext> ctx; + RefPtr<DrawTarget> target = gfxPlatform::GetPlatform()-> + CreateOffscreenContentDrawTarget(IntSize(mClip.width, mClip.height), + SurfaceFormat::B8G8R8A8); - target = gfxPlatform::GetPlatform()-> - CreateOffscreenContentDrawTarget(gfx::IntSize(mClip.width, mClip.height), - gfx::SurfaceFormat::B8G8R8A8); - ctx = new gfxContext(target); + nsRefPtr<gfxContext> ctx = new gfxContext(target); // Create our callback. nsRefPtr<gfxDrawingCallback> drawTileCallback = new DrawSingleTileCallback(this, mClip, aViewportSize, aSVGContext, aWhichFrame, aFlags); nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(drawTileCallback, mClip.Size()); // Actually draw. The callback will end up invoking DrawSingleTile. gfxRect imageRect(0, 0, mClip.width, mClip.height); gfxUtils::DrawPixelSnapped(ctx, drawable, gfxMatrix(), imageRect, imageRect, imageRect, imageRect, gfxImageFormat::ARGB32, GraphicsFilter::FILTER_FAST); // Cache the resulting surface. - mCachedSurface = new ClippedImageCachedSurface(target, + mCachedSurface = new ClippedImageCachedSurface(target->Snapshot(), aViewportSize, aSVGContext, frameToDraw, aFlags); } MOZ_ASSERT(mCachedSurface, "Should have a cached surface now"); return mCachedSurface->Surface(); @@ -317,17 +318,17 @@ ClippedImage::Draw(gfxContext* aContext, } // Check for tiling. If we need to tile then we need to create a // gfxCallbackDrawable to handle drawing for us. gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); if (MustCreateSurface(aContext, aUserSpaceToImageSpace, sourceRect, aSubimage, aFlags)) { // Create a temporary surface containing a single tile of this image. // GetFrame will call DrawSingleTile internally. - nsRefPtr<gfxASurface> surface = + RefPtr<SourceSurface> surface = GetFrameInternal(aViewportSize, aSVGContext, aWhichFrame, aFlags); NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); // Create a drawable from that surface. nsRefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, gfxIntSize(mClip.width, mClip.height)); // Draw.
--- a/image/src/ClippedImage.h +++ b/image/src/ClippedImage.h @@ -2,46 +2,50 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ #define MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ #include "ImageWrapper.h" +#include "mozilla/gfx/2D.h" #include "mozilla/Maybe.h" +#include "mozilla/RefPtr.h" namespace mozilla { namespace image { class ClippedImageCachedSurface; class DrawSingleTileCallback; /** * An Image wrapper that clips an image against a rectangle. Right now only * absolute coordinates in pixels are supported. * * XXX(seth): There a known (performance, not correctness) issue with * GetImageContainer. See the comments for that method for more information. */ class ClippedImage : public ImageWrapper { + typedef mozilla::gfx::SourceSurface SourceSurface; + public: NS_DECL_ISUPPORTS virtual ~ClippedImage(); virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE; NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE; NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE; - NS_IMETHOD_(already_AddRefed<gfxASurface>) GetFrame(uint32_t aWhichFrame, - uint32_t aFlags) MOZ_OVERRIDE; + NS_IMETHOD_(mozilla::TemporaryRef<SourceSurface>) + GetFrame(uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE; NS_IMETHOD Draw(gfxContext* aContext, GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage, const nsIntSize& aViewportSize, @@ -50,20 +54,21 @@ public: uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD RequestDiscard() MOZ_OVERRIDE; NS_IMETHOD_(Orientation) GetOrientation() MOZ_OVERRIDE; protected: ClippedImage(Image* aImage, nsIntRect aClip); private: - already_AddRefed<gfxASurface> GetFrameInternal(const nsIntSize& aViewportSize, - const SVGImageContext* aSVGContext, - uint32_t aWhichFrame, - uint32_t aFlags); + mozilla::TemporaryRef<SourceSurface> + GetFrameInternal(const nsIntSize& aViewportSize, + const SVGImageContext* aSVGContext, + uint32_t aWhichFrame, + uint32_t aFlags); bool ShouldClip(); bool MustCreateSurface(gfxContext* aContext, const gfxMatrix& aTransform, const gfxRect& aSourceRect, const nsIntRect& aSubimage, const uint32_t aFlags) const; gfxFloat ClampFactor(const gfxFloat aToClamp, const int aReference) const; nsresult DrawSingleTile(gfxContext* aContext,
--- a/image/src/FrozenImage.cpp +++ b/image/src/FrozenImage.cpp @@ -1,15 +1,17 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "FrozenImage.h" +using namespace mozilla::gfx; + namespace mozilla { namespace image { NS_IMPL_ISUPPORTS1(FrozenImage, imgIContainer) nsIntRect FrozenImage::FrameRect(uint32_t /* aWhichFrame - ignored */) { @@ -35,17 +37,17 @@ FrozenImage::GetAnimated(bool* aAnimated bool dummy; nsresult rv = InnerImage()->GetAnimated(&dummy); if (NS_SUCCEEDED(rv)) { *aAnimated = false; } return rv; } -NS_IMETHODIMP_(already_AddRefed<gfxASurface>) +NS_IMETHODIMP_(TemporaryRef<SourceSurface>) FrozenImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { return InnerImage()->GetFrame(FRAME_FIRST, aFlags); } NS_IMETHODIMP_(bool) FrozenImage::FrameIsOpaque(uint32_t aWhichFrame)
--- a/image/src/FrozenImage.h +++ b/image/src/FrozenImage.h @@ -2,16 +2,18 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_IMAGELIB_FROZENIMAGE_H_ #define MOZILLA_IMAGELIB_FROZENIMAGE_H_ #include "ImageWrapper.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" namespace mozilla { namespace image { /** * An Image wrapper that disables animation, freezing the image at its first * frame. It does this using two strategies. If this is the only instance of the * image, animation will never start, because IncrementAnimationConsumers is @@ -19,28 +21,30 @@ namespace image { * because any imgIContainer method that is affected by animation gets its * aWhichFrame argument set to FRAME_FIRST when it passes through FrozenImage. * * XXX(seth): There a known (performance, not correctness) issue with * GetImageContainer. See the comments for that method for more information. */ class FrozenImage : public ImageWrapper { + typedef mozilla::gfx::SourceSurface SourceSurface; + public: NS_DECL_ISUPPORTS virtual ~FrozenImage() { } virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; virtual void IncrementAnimationConsumers() MOZ_OVERRIDE; virtual void DecrementAnimationConsumers() MOZ_OVERRIDE; NS_IMETHOD GetAnimated(bool* aAnimated) MOZ_OVERRIDE; - NS_IMETHOD_(already_AddRefed<gfxASurface>) GetFrame(uint32_t aWhichFrame, - uint32_t aFlags) MOZ_OVERRIDE; + NS_IMETHOD_(TemporaryRef<SourceSurface>) + GetFrame(uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD_(bool) FrameIsOpaque(uint32_t aWhichFrame) MOZ_OVERRIDE; NS_IMETHOD GetImageContainer(layers::LayerManager* aManager, layers::ImageContainer** _retval) MOZ_OVERRIDE; NS_IMETHOD Draw(gfxContext* aContext, GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage,
--- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -1,18 +1,22 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageWrapper.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "Orientation.h" #include "mozilla/MemoryReporting.h" +using mozilla::gfx::DataSourceSurface; +using mozilla::gfx::SourceSurface; using mozilla::layers::LayerManager; using mozilla::layers::ImageContainer; namespace mozilla { namespace image { // Inherited methods from Image. @@ -191,17 +195,17 @@ ImageWrapper::GetType() } NS_IMETHODIMP ImageWrapper::GetAnimated(bool* aAnimated) { return mInnerImage->GetAnimated(aAnimated); } -NS_IMETHODIMP_(already_AddRefed<gfxASurface>) +NS_IMETHODIMP_(TemporaryRef<SourceSurface>) ImageWrapper::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { return mInnerImage->GetFrame(aWhichFrame, aFlags); } NS_IMETHODIMP_(bool) ImageWrapper::FrameIsOpaque(uint32_t aWhichFrame)
--- a/image/src/OrientedImage.cpp +++ b/image/src/OrientedImage.cpp @@ -6,16 +6,18 @@ #include <algorithm> #include "gfxDrawable.h" #include "gfxPlatform.h" #include "gfxUtils.h" #include "OrientedImage.h" +using namespace mozilla::gfx; + using std::swap; using mozilla::layers::LayerManager; using mozilla::layers::ImageContainer; namespace mozilla { namespace image { NS_IMPL_ISUPPORTS1(OrientedImage, imgIContainer) @@ -70,71 +72,68 @@ OrientedImage::GetIntrinsicRatio(nsSize* if (mOrientation.SwapsWidthAndHeight()) { swap(aRatio->width, aRatio->height); } return rv; } -NS_IMETHODIMP_(already_AddRefed<gfxASurface>) +NS_IMETHODIMP_(TemporaryRef<SourceSurface>) OrientedImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { nsresult rv; if (mOrientation.IsIdentity()) { return InnerImage()->GetFrame(aWhichFrame, aFlags); } // Get the underlying dimensions. int32_t width, height; + rv = InnerImage()->GetWidth(&width); + NS_ENSURE_SUCCESS(rv, nullptr); + rv = InnerImage()->GetHeight(&height); + NS_ENSURE_SUCCESS(rv, nullptr); if (mOrientation.SwapsWidthAndHeight()) { - rv = InnerImage()->GetWidth(&height); - rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&width); - } else { - rv = InnerImage()->GetWidth(&width); - rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&height); + swap(width, height); } NS_ENSURE_SUCCESS(rv, nullptr); // Determine an appropriate format for the surface. gfx::SurfaceFormat surfaceFormat; gfxImageFormat imageFormat; if (InnerImage()->FrameIsOpaque(aWhichFrame)) { surfaceFormat = gfx::SurfaceFormat::B8G8R8X8; imageFormat = gfxImageFormat::ARGB32; } else { surfaceFormat = gfx::SurfaceFormat::B8G8R8A8; imageFormat = gfxImageFormat::ARGB32; } // Create a surface to draw into. - mozilla::RefPtr<mozilla::gfx::DrawTarget> target; - target = gfxPlatform::GetPlatform()-> - CreateOffscreenContentDrawTarget(gfx::IntSize(width, height), surfaceFormat); + mozilla::RefPtr<DrawTarget> target = + gfxPlatform::GetPlatform()-> + CreateOffscreenContentDrawTarget(IntSize(width, height), surfaceFormat); // Create our drawable. - nsRefPtr<gfxASurface> innerSurface = + RefPtr<SourceSurface> innerSurface = InnerImage()->GetFrame(aWhichFrame, aFlags); NS_ENSURE_TRUE(innerSurface, nullptr); nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(innerSurface, gfxIntSize(width, height)); // Draw. nsRefPtr<gfxContext> ctx = new gfxContext(target); gfxRect imageRect(0, 0, width, height); gfxUtils::DrawPixelSnapped(ctx, drawable, OrientationMatrix(nsIntSize(width, height)), imageRect, imageRect, imageRect, imageRect, imageFormat, GraphicsFilter::FILTER_FAST); - nsRefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()-> - GetThebesSurfaceForDrawTarget(target); - - return surface.forget(); + return target->Snapshot(); } NS_IMETHODIMP OrientedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval) { // XXX(seth): We currently don't have a way of orienting the result of // GetImageContainer. We work around this by always returning null, but if it // ever turns out that OrientedImage is widely used on codepaths that can
--- a/image/src/OrientedImage.h +++ b/image/src/OrientedImage.h @@ -2,43 +2,47 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_IMAGELIB_ORIENTEDIMAGE_H_ #define MOZILLA_IMAGELIB_ORIENTEDIMAGE_H_ #include "ImageWrapper.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "Orientation.h" namespace mozilla { namespace image { /** * An Image wrapper that rotates and/or flips an image according to a specified * Orientation. * * XXX(seth): There a known (performance, not correctness) issue with * GetImageContainer. See the comments for that method for more information. */ class OrientedImage : public ImageWrapper { + typedef mozilla::gfx::SourceSurface SourceSurface; + public: NS_DECL_ISUPPORTS virtual ~OrientedImage() { } virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE; NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE; NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE; - NS_IMETHOD_(already_AddRefed<gfxASurface>) GetFrame(uint32_t aWhichFrame, - uint32_t aFlags) MOZ_OVERRIDE; + NS_IMETHOD_(mozilla::TemporaryRef<SourceSurface>) + GetFrame(uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE; NS_IMETHOD Draw(gfxContext* aContext, GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage, const nsIntSize& aViewportSize,
--- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -1,20 +1,24 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// Must #include ImageLogging.h before any IPDL-generated files or other files that #include prlog.h +#include "ImageLogging.h" + +#include "RasterImage.h" + #include "base/histogram.h" -#include "ImageLogging.h" +#include "gfxPlatform.h" #include "nsComponentManagerUtils.h" #include "imgDecoderObserver.h" #include "nsError.h" #include "Decoder.h" -#include "RasterImage.h" #include "nsAutoPtr.h" #include "prenv.h" #include "prsystem.h" #include "ImageContainer.h" #include "Layers.h" #include "nsPresContext.h" #include "nsIThreadPool.h" #include "nsXPCOMCIDInternal.h" @@ -25,16 +29,18 @@ #include "nsGIFDecoder2.h" #include "nsJPEGDecoder.h" #include "nsBMPDecoder.h" #include "nsICODecoder.h" #include "nsIconDecoder.h" #include "gfxContext.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Services.h" #include "mozilla/Preferences.h" #include <stdint.h> #include "mozilla/Telemetry.h" #include "mozilla/TimeStamp.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/gfx/Scale.h" @@ -43,16 +49,17 @@ #include "gfx2DGlue.h" #include <algorithm> #ifdef MOZ_NUWA_PROCESS #include "ipc/Nuwa.h" #endif using namespace mozilla; +using namespace mozilla::gfx; using namespace mozilla::image; using namespace mozilla::layers; // a mask for flags that will affect the decoding #define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION) #define DECODE_FLAGS_DEFAULT 0 /* Accounting for compressed data */ @@ -875,19 +882,19 @@ RasterImage::CopyFrame(uint32_t aWhichFr ctx.SetPattern(pattern); ctx.Fill(); imgsurface.forget(_retval); return NS_OK; } //****************************************************************************** -/* [noscript] gfxASurface getFrame(in uint32_t aWhichFrame, - * in uint32_t aFlags); */ -NS_IMETHODIMP_(already_AddRefed<gfxASurface>) +/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame, + * in uint32_t aFlags); */ +NS_IMETHODIMP_(TemporaryRef<SourceSurface>) RasterImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE); if (aWhichFrame > FRAME_MAX_VALUE) return nullptr; @@ -946,48 +953,63 @@ RasterImage::GetFrame(uint32_t aWhichFra // The image doesn't have a surface because it's been optimized away. Create // one. if (!framesurf) { nsRefPtr<gfxImageSurface> imgsurf; CopyFrame(aWhichFrame, aFlags, getter_AddRefs(imgsurf)); framesurf = imgsurf; } - return framesurf.forget(); + RefPtr<SourceSurface> result; + + // As far as Moz2D is concerned, SourceSurface contains premultiplied alpha. + // If we're abusing it to contain non-premultiplied alpha then we want to + // avoid having Moz2D do any conversions on it (like copy to another + // surface). Hence why we try to wrap framesurf's data here for + // FLAG_DECODE_NO_PREMULTIPLY_ALPHA. + if ((aFlags & FLAG_WANT_DATA_SURFACE) != 0 || + (aFlags & FLAG_DECODE_NO_PREMULTIPLY_ALPHA) != 0) { + result = gfxPlatform::GetPlatform()->GetWrappedDataSourceSurface(framesurf); + } + if (!result) { + result = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, + framesurf); + } + return result.forget(); } already_AddRefed<layers::Image> RasterImage::GetCurrentImage() { if (!mDecoded) { // We can't call StartDecoding because that can synchronously notify // which can cause DOM modification RequestDecodeCore(ASYNCHRONOUS); return nullptr; } - nsRefPtr<gfxASurface> imageSurface = GetFrame(FRAME_CURRENT, FLAG_NONE); - if (!imageSurface) { + RefPtr<SourceSurface> surface = GetFrame(FRAME_CURRENT, FLAG_NONE); + if (!surface) { // The OS threw out some or all of our buffer. Start decoding again. // GetFrame will only return null in the case that the image was // discarded. We already checked that the image is decoded, so other // error paths are not possible. ForceDiscard(); RequestDecodeCore(ASYNCHRONOUS); return nullptr; } if (!mImageContainer) { mImageContainer = LayerManager::CreateImageContainer(); } CairoImage::Data cairoData; GetWidth(&cairoData.mSize.width); GetHeight(&cairoData.mSize.height); - cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, imageSurface); + cairoData.mSourceSurface = surface; nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::CAIRO_SURFACE); NS_ASSERTION(image, "Failed to create Image"); static_cast<CairoImage*>(image.get())->SetData(cairoData); return image.forget(); }
--- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -105,20 +105,21 @@ private: CachedSurface* mSurface; Cost mCost; }; /* * A CachedSurface associates a surface with a key that uniquely identifies that * surface. */ -class CachedSurface : public RefCounted<CachedSurface> +class CachedSurface { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(CachedSurface) + NS_INLINE_DECL_REFCOUNTING(CachedSurface) + CachedSurface(DrawTarget* aTarget, const IntSize aTargetSize, const Cost aCost, const ImageKey aImageKey, const SurfaceKey& aSurfaceKey) : mTarget(aTarget) , mTargetSize(aTargetSize) , mCost(aCost) @@ -151,20 +152,21 @@ private: }; /* * An ImageSurfaceCache is a per-image surface cache. For correctness we must be * able to remove all surfaces associated with an image when the image is * destroyed or invalidated. Since this will happen frequently, it makes sense * to make it cheap by storing the surfaces for each image separately. */ -class ImageSurfaceCache : public RefCounted<ImageSurfaceCache> +class ImageSurfaceCache { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageSurfaceCache) + NS_INLINE_DECL_REFCOUNTING(ImageSurfaceCache) + typedef nsRefPtrHashtable<nsGenericHashKey<SurfaceKey>, CachedSurface> SurfaceTable; bool IsEmpty() const { return mSurfaces.Count() == 0; } void Insert(const SurfaceKey& aKey, CachedSurface* aSurface) { MOZ_ASSERT(aSurface, "Should have a surface"); mSurfaces.Put(aKey, aSurface);
--- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -644,19 +644,19 @@ VectorImage::FrameIsOpaque(uint32_t aWhi { if (aWhichFrame > FRAME_MAX_VALUE) NS_WARNING("aWhichFrame outside valid range!"); return false; // In general, SVG content is not opaque. } //****************************************************************************** -/* [noscript] gfxASurface getFrame(in uint32_t aWhichFrame, - * in uint32_t aFlags; */ -NS_IMETHODIMP_(already_AddRefed<gfxASurface>) +/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame, + * in uint32_t aFlags; */ +NS_IMETHODIMP_(TemporaryRef<SourceSurface>) VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE); if (aWhichFrame > FRAME_MAX_VALUE) return nullptr; @@ -669,45 +669,32 @@ VectorImage::GetFrame(uint32_t aWhichFra if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eWidth, imageIntSize.width) || !mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eHeight, imageIntSize.height)) { // We'll get here if our SVG doc has a percent-valued width or height. return nullptr; } - // Create a surface that we'll ultimately return - // --------------------------------------------- // Make our surface the size of what will ultimately be drawn to it. // (either the full image size, or the restricted region) - gfxIntSize surfaceSize(imageIntSize.width, imageIntSize.height); - - nsRefPtr<gfxImageSurface> surface = - new gfxImageSurface(surfaceSize, gfxImageFormat::ARGB32); + RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()-> + CreateOffscreenContentDrawTarget(IntSize(imageIntSize.width, + imageIntSize.height), + SurfaceFormat::B8G8R8A8); + nsRefPtr<gfxContext> context = new gfxContext(dt); - RefPtr<DrawTarget> drawTarget = - Factory::CreateDrawTargetForData(BackendType::CAIRO, - surface->Data(), - IntSize(imageIntSize.width, - imageIntSize.height), - surface->Stride(), - SurfaceFormat::B8G8R8A8); - - nsRefPtr<gfxContext> context = new gfxContext(drawTarget); - - // Draw to our surface! - // -------------------- nsresult rv = Draw(context, GraphicsFilter::FILTER_NEAREST, gfxMatrix(), gfxRect(gfxPoint(0,0), gfxIntSize(imageIntSize.width, imageIntSize.height)), nsIntRect(nsIntPoint(0,0), imageIntSize), imageIntSize, nullptr, aWhichFrame, aFlags); NS_ENSURE_SUCCESS(rv, nullptr); - return surface.forget(); + return dt->Snapshot(); } //****************************************************************************** /* [noscript] ImageContainer getImageContainer(); */ NS_IMETHODIMP VectorImage::GetImageContainer(LayerManager* aManager, mozilla::layers::ImageContainer** _retval) {
--- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -1,16 +1,17 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "imgTools.h" +#include "gfxUtils.h" #include "mozilla/gfx/2D.h" #include "mozilla/RefPtr.h" #include "nsCOMPtr.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsError.h" #include "imgLoader.h" #include "imgICache.h" @@ -92,30 +93,16 @@ NS_IMETHODIMP imgTools::DecodeImage(nsII rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true); NS_ENSURE_SUCCESS(rv, rv); // All done. NS_ADDREF(*aContainer = image.get()); return NS_OK; } -static TemporaryRef<SourceSurface> -GetFirstImageFrame(imgIContainer *aContainer) -{ - nsRefPtr<gfxASurface> frame = - aContainer->GetFrame(imgIContainer::FRAME_FIRST, - imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(frame, nullptr); - - nsRefPtr<gfxImageSurface> imageSurface = frame->CopyToARGB32ImageSurface(); - NS_ENSURE_TRUE(imageSurface, nullptr); - - return imageSurface->CopyToB8G8R8A8DataSourceSurface(); -} - /** * This takes a DataSourceSurface rather than a SourceSurface because some * of the callers have a DataSourceSurface and we don't want to call * GetDataSurface on such surfaces since that may incure a conversion to * SurfaceType::DATA which we don't need. */ static nsresult EncodeImageData(DataSourceSurface* aDataSurface, const nsACString& aMimeType, @@ -156,20 +143,32 @@ static nsresult EncodeImageData(DataSour } NS_IMETHODIMP imgTools::EncodeImage(imgIContainer *aContainer, const nsACString& aMimeType, const nsAString& aOutputOptions, nsIInputStream **aStream) { // Use frame 0 from the image container. - RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer); + RefPtr<SourceSurface> frame = + aContainer->GetFrame(imgIContainer::FRAME_FIRST, + imgIContainer::FLAG_SYNC_DECODE); NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); - RefPtr<DataSourceSurface> dataSurface = frame->GetDataSurface(); + RefPtr<DataSourceSurface> dataSurface; + + if (frame->GetFormat() == SurfaceFormat::B8G8R8A8) { + dataSurface = frame->GetDataSurface(); + } else { + // Convert format to SurfaceFormat::B8G8R8A8 + dataSurface = gfxUtils:: + CopySurfaceToDataSourceSurfaceWithFormat(frame, + SurfaceFormat::B8G8R8A8); + } + NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream); } NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, const nsACString& aMimeType, int32_t aScaledWidth, @@ -181,17 +180,19 @@ NS_IMETHODIMP imgTools::EncodeScaledImag // If no scaled size is specified, we'll just encode the image at its // original size (no scaling). if (aScaledWidth == 0 && aScaledHeight == 0) { return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream); } // Use frame 0 from the image container. - RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer); + RefPtr<SourceSurface> frame = + aContainer->GetFrame(imgIContainer::FRAME_FIRST, + imgIContainer::FLAG_SYNC_DECODE); NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); int32_t frameWidth = frame->GetSize().width; int32_t frameHeight = frame->GetSize().height; // If the given width or height is zero we'll replace it with the image's // original dimensions. if (aScaledWidth == 0) { @@ -242,17 +243,19 @@ NS_IMETHODIMP imgTools::EncodeCroppedIma // If no size is specified then we'll preserve the image's original dimensions // and don't need to crop. if (aWidth == 0 && aHeight == 0) { return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream); } // Use frame 0 from the image container. - RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer); + RefPtr<SourceSurface> frame = + aContainer->GetFrame(imgIContainer::FRAME_FIRST, + imgIContainer::FLAG_SYNC_DECODE); NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); int32_t frameWidth = frame->GetSize().width; int32_t frameHeight = frame->GetSize().height; // If the given width or height is zero we'll replace it with the image's // original dimensions. if (aWidth == 0) {
--- a/ipc/netd/Netd.cpp +++ b/ipc/netd/Netd.cpp @@ -11,16 +11,17 @@ #include "cutils/properties.h" #include "android/log.h" #include "nsWhitespaceTokenizer.h" #include "nsXULAppAPI.h" #include "nsAutoPtr.h" #include "nsString.h" #include "nsThreadUtils.h" +#include "mozilla/RefPtr.h" #define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args) #define ICS_SYS_USB_RNDIS_MAC "/sys/class/android_usb/android0/f_rndis/ethaddr" #define INVALID_SOCKET -1 #define MAX_RECONNECT_TIMES 10 namespace {
--- a/ipc/netd/Netd.h +++ b/ipc/netd/Netd.h @@ -1,16 +1,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_system_netd_h__ #define mozilla_system_netd_h__ -#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" #include "nsAutoPtr.h" #include "base/message_loop.h" #include "mozilla/FileUtils.h" #define MAX_COMMAND_SIZE 4096 namespace mozilla { namespace ipc { @@ -21,38 +21,41 @@ namespace ipc { struct NetdCommand { uint8_t mData[MAX_COMMAND_SIZE]; // Number of octets in mData. size_t mSize; }; -class NetdConsumer : public mozilla::RefCounted<NetdConsumer> +class NetdConsumer { +protected: + virtual ~NetdConsumer() { } + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(NetdConsumer) - virtual ~NetdConsumer() { } + NS_INLINE_DECL_REFCOUNTING(NetdConsumer) + virtual void MessageReceived(NetdCommand* aMessage) = 0; }; class NetdWriteTask : public Task { virtual void Run(); }; -class NetdClient : public MessageLoopForIO::LineWatcher, - public RefCounted<NetdClient> +class NetdClient : public MessageLoopForIO::LineWatcher { + virtual ~NetdClient(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(NetdClient) + NS_INLINE_DECL_REFCOUNTING(NetdClient) typedef std::queue<NetdCommand*> NetdCommandQueue; NetdClient(); - virtual ~NetdClient(); static void Start(); static void SendNetdCommandIOThread(NetdCommand* aMessage); private: void WriteNetdCommand(); virtual void OnError(); virtual void OnLineRead(int aFd, nsDependentCSubstring& aMessage); virtual void OnFileCanWriteWithoutBlocking(int aFd);
--- a/ipc/unixsocket/UnixSocket.h +++ b/ipc/unixsocket/UnixSocket.h @@ -130,24 +130,26 @@ public: enum SocketConnectionStatus { SOCKET_DISCONNECTED = 0, SOCKET_LISTENING = 1, SOCKET_CONNECTING = 2, SOCKET_CONNECTED = 3 }; -class UnixSocketConsumer : public AtomicRefCounted<UnixSocketConsumer> +class UnixSocketConsumer { +protected: + virtual ~UnixSocketConsumer(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(UnixSocketConsumer) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UnixSocketConsumer) + UnixSocketConsumer(); - virtual ~UnixSocketConsumer(); - SocketConnectionStatus GetConnectionStatus() const { MOZ_ASSERT(NS_IsMainThread()); return mConnectionStatus; } int GetSuggestedConnectDelayMs() const {
--- a/js/ipc/JavaScriptChild.cpp +++ b/js/ipc/JavaScriptChild.cpp @@ -434,16 +434,18 @@ JavaScriptChild::AnswerIsExtensible(cons JSAutoRequest request(cx); *result = false; RootedObject obj(cx, findObject(objId)); if (!obj) return false; + JSAutoCompartment comp(cx, obj); + bool extensible; if (!JS_IsExtensible(cx, obj, &extensible)) return fail(cx, rs); *result = !!extensible; return ok(rs); }
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug892794.js @@ -0,0 +1,13 @@ +// |jit-test| ion-eager + +function test0(v) { + return (2147483648-Math.max(1.1,-(((2<<(-v|v))-3)|0)))|0; +} +assertEq(test0(1.6), 2147483645); +assertEq(test0(437348122.9), 2147483646); + +function test1(v) { + return (2147483648+Math.min(v,0))|0; +} +assertEq(test1(2.1), -2147483648) +assertEq(test1(-0.1), 2147483647)
--- a/js/src/jit-test/tests/proxy/testDirectProxyConstruct2.js +++ b/js/src/jit-test/tests/proxy/testDirectProxyConstruct2.js @@ -1,15 +1,18 @@ +load(libdir + "asserts.js"); /* * Call the trap with the handler as the this value, the target as the first * argument, and the original arguments as the third argument. + * + * Hooks that don't return an object must throw. */ var target = function () {}; var handler = { construct: function (target1, args) { assertEq(this, handler); assertEq(target1, target); assertEq(args.length, 2); assertEq(args[0], 2); assertEq(args[1], 3); } } -assertEq(new (new Proxy(target, handler))(2, 3), undefined); +assertThrowsInstanceOf(function () {new (new Proxy(target, handler))(2, 3)}, TypeError);
--- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -4369,16 +4369,17 @@ ICGetElemNativeCompiler::generateStubCod emitCallNative(masm, objReg); } else { JS_ASSERT(acctype_ == ICGetElemNativeStub::ScriptedGetter); // Load function in scratchReg and ensure that it has a jit script. masm.loadPtr(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfGetter()), scratchReg); + masm.branchIfFunctionHasNoScript(scratchReg, popR1 ? &failurePopR1 : &failure); masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg); masm.loadBaselineOrIonRaw(scratchReg, scratchReg, SequentialExecution, popR1 ? &failurePopR1 : &failure); // At this point, we are guaranteed to successfully complete. if (popR1) masm.addPtr(Imm32(sizeof(size_t)), BaselineStackReg); @@ -4801,34 +4802,47 @@ ICGetElem_Arguments::Compiler::generateS return true; } // // SetElem_Fallback // static bool +SetElemDenseAddHasSameShapes(ICSetElem_DenseAdd *stub, JSObject *obj) +{ + size_t numShapes = stub->protoChainDepth() + 1; + for (size_t i = 0; i < numShapes; i++) { + static const size_t MAX_DEPTH = ICSetElem_DenseAdd::MAX_PROTO_CHAIN_DEPTH; + if (obj->lastProperty() != stub->toImplUnchecked<MAX_DEPTH>()->shape(i)) + return false; + obj = obj->getProto(); + if (!obj && i != numShapes - 1) + return false; + } + + return true; +} + +static bool DenseSetElemStubExists(JSContext *cx, ICStub::Kind kind, ICSetElem_Fallback *stub, HandleObject obj) { JS_ASSERT(kind == ICStub::SetElem_Dense || kind == ICStub::SetElem_DenseAdd); for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) { if (kind == ICStub::SetElem_Dense && iter->isSetElem_Dense()) { ICSetElem_Dense *dense = iter->toSetElem_Dense(); if (obj->lastProperty() == dense->shape() && obj->getType(cx) == dense->type()) return true; } if (kind == ICStub::SetElem_DenseAdd && iter->isSetElem_DenseAdd()) { ICSetElem_DenseAdd *dense = iter->toSetElem_DenseAdd(); - if (obj->lastProperty() == dense->toImplUnchecked<0>()->shape(0) && - obj->getType(cx) == dense->type()) - { + if (obj->getType(cx) == dense->type() && SetElemDenseAddHasSameShapes(dense, obj)) return true; - } } } return false; } static bool TypedArraySetElemStubExists(ICSetElem_Fallback *stub, HandleObject obj, bool expectOOB) {
--- a/js/src/jit/BaselineIC.h +++ b/js/src/jit/BaselineIC.h @@ -3550,16 +3550,17 @@ class ICSetElem_DenseAdd : public ICUpda static size_t offsetOfType() { return offsetof(ICSetElem_DenseAdd, type_); } HeapPtrTypeObject &type() { return type_; } size_t protoChainDepth() const { + MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH); return extra_; } template <size_t ProtoChainDepth> ICSetElem_DenseAddImpl<ProtoChainDepth> *toImplUnchecked() { return static_cast<ICSetElem_DenseAddImpl<ProtoChainDepth> *>(this); }
--- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -3011,53 +3011,43 @@ jit::TraceIonScripts(JSTracer* trc, JSSc AutoDebugModeInvalidation::~AutoDebugModeInvalidation() { MOZ_ASSERT(!!comp_ != !!zone_); if (needInvalidation_ == NoNeed) return; - // Invalidate the stack if any compartments toggled from on->off, because - // we allow scripts to be on stack when turning off debug mode. - bool invalidateStack = needInvalidation_ == ToggledOff; Zone *zone = zone_ ? zone_ : comp_->zone(); JSRuntime *rt = zone->runtimeFromMainThread(); FreeOp *fop = rt->defaultFreeOp(); if (comp_) { StopAllOffThreadCompilations(comp_); } else { for (CompartmentsInZoneIter comp(zone_); !comp.done(); comp.next()) StopAllOffThreadCompilations(comp); } - if (invalidateStack) { - jit::MarkActiveBaselineScripts(zone); - - for (JitActivationIterator iter(rt); !iter.done(); ++iter) { - JSCompartment *comp = iter.activation()->compartment(); - if ((comp_ && comp_ == comp) || - (zone_ && zone_ == comp->zone() && comp->principals)) - { - IonContext ictx(CompileRuntime::get(rt)); - AutoFlushCache afc("AutoDebugModeInvalidation", rt->jitRuntime()); - IonSpew(IonSpew_Invalidate, "Invalidating frames for debug mode toggle"); - InvalidateActivation(fop, iter.jitTop(), true); - } + jit::MarkActiveBaselineScripts(zone); + + for (JitActivationIterator iter(rt); !iter.done(); ++iter) { + JSCompartment *comp = iter.activation()->compartment(); + if ((comp_ && comp_ == comp) || (zone_ && zone_ == comp->zone())) { + IonContext ictx(CompileRuntime::get(rt)); + AutoFlushCache afc("AutoDebugModeInvalidation", rt->jitRuntime()); + IonSpew(IonSpew_Invalidate, "Invalidating frames for debug mode toggle"); + InvalidateActivation(fop, iter.jitTop(), true); } } for (gc::CellIter i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); - if ((comp_ && script->compartment() == comp_) || - (zone_ && script->compartment()->principals)) - { + if ((comp_ && script->compartment() == comp_) || zone_) { FinishInvalidation<SequentialExecution>(fop, script); FinishInvalidation<ParallelExecution>(fop, script); FinishDiscardBaselineScript(fop, script); - // script->clearAnalysis(); script->resetUseCount(); } else if (script->hasBaselineScript()) { script->baselineScript()->resetActive(); } } }
--- a/js/src/js.msg +++ b/js/src/js.msg @@ -432,8 +432,10 @@ MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, MSG_DEF(JSMSG_NO_EXPORT_NAME, 378, 0, JSEXN_SYNTAXERR, "missing export name") MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT, 379, 0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword") MSG_DEF(JSMSG_INVALID_PROTOTYPE, 380, 0, JSEXN_TYPEERR, "prototype field is not an object") MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 381, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type") MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 382, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}") MSG_DEF(JSMSG_INVALID_ARG_TYPE, 383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}") MSG_DEF(JSMSG_TERMINATED, 384, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}") MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP, 385, 1, JSEXN_ERR, "No such property on self-hosted object: {0}") +MSG_DEF(JSMSG_PROXY_EXTENSIBILITY, 386, 0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target") +MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT, 387, 0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object")
--- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1072,22 +1072,16 @@ ScriptedIndirectProxyHandler::fun_toStri return nullptr; } RootedObject obj(cx, &proxy->as<ProxyObject>().extra(0).toObject().getReservedSlot(0).toObject()); return fun_toStringHelper(cx, obj, indent); } ScriptedIndirectProxyHandler ScriptedIndirectProxyHandler::singleton; -static JSObject * -GetDirectProxyHandlerObject(JSObject *proxy) -{ - return proxy->as<ProxyObject>().extra(0).toObjectOrNull(); -} - /* Derived class for all scripted direct proxy handlers. */ class ScriptedDirectProxyHandler : public DirectProxyHandler { public: ScriptedDirectProxyHandler(); virtual ~ScriptedDirectProxyHandler(); /* ES5 Harmony fundamental proxy traps. */ virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE; @@ -1109,16 +1103,19 @@ class ScriptedDirectProxyHandler : publi virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id, MutableHandleValue vp) MOZ_OVERRIDE; virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id, bool strict, MutableHandleValue vp) MOZ_OVERRIDE; virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp) MOZ_OVERRIDE; + /* ES6 Harmony traps */ + virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE; + /* Spidermonkey extensions. */ virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE; virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE; virtual bool isScripted() MOZ_OVERRIDE { return true; } static ScriptedDirectProxyHandler singleton; }; @@ -1360,16 +1357,26 @@ IdToValue(JSContext *cx, HandleId id, Mu value.set(IdToValue(id)); // Re-use out-param to avoid Rooted overhead. JSString *name = ToString<CanGC>(cx, value); if (!name) return false; value.set(StringValue(name)); return true; } +// Get the [[ProxyHandler]] of a scripted direct proxy. +// +// NB: This *must* stay synched with proxy(). +static JSObject * +GetDirectProxyHandlerObject(JSObject *proxy) +{ + JS_ASSERT(proxy->as<ProxyObject>().handler() == &ScriptedDirectProxyHandler::singleton); + return proxy->as<ProxyObject>().extra(0).toObjectOrNull(); +} + // TrapGetOwnProperty(O, P) static bool TrapGetOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandleValue rval) { // step 1 RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 @@ -2220,16 +2227,52 @@ ScriptedDirectProxyHandler::keys(JSConte v, js::NullPtr(), bytes.ptr()); return false; } // steps g-n are shared return ArrayToIdVector(cx, proxy, target, trapResult, props, JSITER_OWNONLY, cx->names().keys); } +// ES6 (5 April, 2014) 9.5.3 Proxy.[[IsExtensible]](P) +bool +ScriptedDirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) +{ + RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); + + RootedObject target(cx, proxy->as<ProxyObject>().target()); + + RootedValue trap(cx); + if (!JSObject::getProperty(cx, handler, handler, cx->names().isExtensible, &trap)) + return false; + + if (trap.isUndefined()) + return DirectProxyHandler::isExtensible(cx, proxy, extensible); + + Value argv[] = { + ObjectValue(*target) + }; + RootedValue trapResult(cx); + if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult)) + return false; + + bool booleanTrapResult = ToBoolean(trapResult); + bool targetResult; + if (!JSObject::isExtensible(cx, target, &targetResult)) + return false; + + if (targetResult != booleanTrapResult) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_EXTENSIBILITY); + return false; + } + + *extensible = booleanTrapResult; + return true; +} + bool ScriptedDirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp) { // FIXME: Provide a proper implementation for this trap, see bug 787004 return DirectProxyHandler::iterate(cx, proxy, flags, vp); } @@ -2300,17 +2343,23 @@ ScriptedDirectProxyHandler::construct(JS return DirectProxyHandler::construct(cx, proxy, args); // step 6 Value constructArgv[] = { ObjectValue(*target), ObjectValue(*argsArray) }; RootedValue thisValue(cx, ObjectValue(*handler)); - return Invoke(cx, thisValue, trap, ArrayLength(constructArgv), constructArgv, args.rval()); + if (!Invoke(cx, thisValue, trap, ArrayLength(constructArgv), constructArgv, args.rval())) + return false; + if (!args.rval().isObject()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_CONSTRUCT_OBJECT); + return false; + } + return true; } ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton; #define INVOKE_ON_PROTOTYPE(cx, handler, proxy, protoCall) \ JS_BEGIN_MACRO \ RootedObject proto(cx); \ if (!JSObject::getProto(cx, proxy, &proto)) \
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/Proxy/proxy-constructNonObject.js @@ -0,0 +1,18 @@ +function bogusConstruct(target) { return 4; } +function bogusConstructUndefined(target) { } + +var handler = { construct: bogusConstruct } + +function callable() {} + +var p = new Proxy(callable, handler); + +assertThrowsInstanceOf(function () { new p(); }, TypeError, + "[[Construct must throw if an object is not returned."); + +handler.construct = bogusConstructUndefined; +assertThrowsInstanceOf(function () { new p(); }, TypeError, + "[[Construct must throw if an object is not returned."); + +if (typeof reportCompare === "function") + reportCompare(0,0, "OK");
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/Proxy/proxy-isExtensible.js @@ -0,0 +1,94 @@ +// Test ES6 Proxy trap compliance for Object.isExtensible() on exotic proxy +// objects. +var unsealed = {}; +var sealed = Object.seal({}); +var handler = {}; + +assertEq(Object.isExtensible(unsealed), true); +assertEq(Object.isExtensible(sealed), false); + +var targetSealed = new Proxy(sealed, handler); +var targetUnsealed = new Proxy(unsealed, handler); + +var handlerCalled = false; + +// without traps, forward to the target +// First, make sure we get the obvious answer on a non-exotic target. +assertEq(Object.isExtensible(targetSealed), false, "Must forward to target without hook."); +assertEq(Object.isExtensible(targetUnsealed), true, "Must forward to target without hook."); + +// Now, keep everyone honest. What if the target itself is a proxy? +function ensureCalled() { handlerCalled = true; return true; } +var proxyTarget = new Proxy({}, { isExtensible : ensureCalled }); +assertEq(Object.isExtensible(new Proxy(proxyTarget, {})), true, "Must forward to target without hook."); +assertEq(handlerCalled, true, "Must forward to target without hook."); + +// with traps, makes sure that the handler is called, and that we throw if the +// trap disagrees with the target +function testExtensible(obj, shouldThrow, expectedResult) +{ + handlerCalled = false; + if (shouldThrow) + assertThrowsInstanceOf(function () { Object.isExtensible(obj); }, + TypeError, "Must throw if handler and target disagree."); + else + assertEq(Object.isExtensible(obj), expectedResult, "Must return the correct value."); + assertEq(handlerCalled, true, "Must call handler trap if present"); +} + +// What if the trap says it's necessarily sealed? +function fakeSealed() { handlerCalled = true; return false; } +handler.isExtensible = fakeSealed; +testExtensible(targetSealed, false, false); +testExtensible(targetUnsealed, true); + +// What if the trap says it's never sealed? +function fakeUnsealed() { handlerCalled = true; return true; } +handler.isExtensible = fakeUnsealed; +testExtensible(targetSealed, true); +testExtensible(targetUnsealed, false, true); + +// make sure we are able to prevent further extensions mid-flight and throw if the +// hook tries to lie. +function makeSealedTruth(target) { handlerCalled = true; Object.preventExtensions(target); return false; } +function makeSealedLie(target) { handlerCalled = true; Object.preventExtensions(target); return true; } +handler.isExtensible = makeSealedTruth; +testExtensible(new Proxy({}, handler), false, false); +handler.isExtensible = makeSealedLie; +testExtensible(new Proxy({}, handler), true); + +// What if the trap doesn't directly return a boolean? +function falseyNonBool() { handlerCalled = true; return undefined; } +handler.isExtensible = falseyNonBool; +testExtensible(targetSealed, false, false); +testExtensible(targetUnsealed, true); + +function truthyNonBool() { handlerCalled = true; return {}; } +handler.isExtensible = truthyNonBool; +testExtensible(targetSealed, true); +testExtensible(targetUnsealed, false, true); + +// What if the trap throws? +function ExtensibleError() { } +ExtensibleError.prototype = new Error(); +ExtensibleError.prototype.constructor = ExtensibleError; +function throwFromTrap() { throw new ExtensibleError(); } +handler.isExtensible = throwFromTrap; + +// exercise some other code paths and make sure that they invoke the trap and +// can handle the ensuing error. +assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); }, + ExtensibleError, "Must throw if the trap does."); +assertThrowsInstanceOf(function () { Object.isFrozen(targetSealed); }, + ExtensibleError, "Must throw if the trap does."); +assertThrowsInstanceOf(function () { Object.isSealed(targetSealed); }, + ExtensibleError, "Must throw if the trap does."); + + +// What if the trap likes to re-ask old questions? +function recurse() { return Object.isExtensible(targetSealed); } +handler.isExtensible = recurse; +assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); }, + InternalError, "Should allow and detect infinite recurison."); + +reportCompare(0, 0, "OK");
--- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -98,16 +98,17 @@ macro(isFinite, isFinite, "isFinite") \ macro(isNaN, isNaN, "isNaN") \ macro(isPrototypeOf, isPrototypeOf, "isPrototypeOf") \ macro(iterate, iterate, "iterate") \ macro(Infinity, Infinity, "Infinity") \ macro(int8, int8, "int8") \ macro(int16, int16, "int16") \ macro(int32, int32, "int32") \ + macro(isExtensible, isExtensible, "isExtensible") \ macro(iterator, iterator, "iterator") \ macro(iteratorIntrinsic, iteratorIntrinsic, "__iterator__") \ macro(join, join, "join") \ macro(keys, keys, "keys") \ macro(lastIndex, lastIndex, "lastIndex") \ macro(length, length, "length") \ macro(let, let, "let") \ macro(line, line, "line") \
--- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -281,17 +281,17 @@ 1234567890123456789012345678901234567890 macro(JSOP_UNUSED47, 47, "unused47", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED48, 48, "unused48", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED49, 49, "unused49", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED50, 50, "unused50", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED51, 51, "unused51", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED52, 52, "unused52", NULL, 1, 0, 0, JOF_BYTE) \ \ macro(JSOP_GETPROP, 53, "getprop", NULL, 5, 1, 1, JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_TMPSLOT3) \ - macro(JSOP_SETPROP, 54, "setprop", NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING|JOF_TMPSLOT) \ + macro(JSOP_SETPROP, 54, "setprop", NULL, 5, 2, 1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) \ macro(JSOP_GETELEM, 55, "getelem", NULL, 1, 2, 1, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC) \ macro(JSOP_SETELEM, 56, "setelem", NULL, 1, 3, 1, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING) \ macro(JSOP_UNUSED57, 57, "unused57", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_CALL, 58, "call", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \ macro(JSOP_NAME, 59, "name", NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_TYPESET) \ macro(JSOP_DOUBLE, 60, "double", NULL, 5, 0, 1, JOF_DOUBLE) \ macro(JSOP_STRING, 61, "string", NULL, 5, 0, 1, JOF_ATOM) \ macro(JSOP_ZERO, 62, "zero", "0", 1, 0, 1, JOF_BYTE) \
--- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -41,19 +41,20 @@ enum LayerState { // when the layer has rounded rect clips. LAYER_ACTIVE_FORCE, // Special layer that is metadata only. LAYER_ACTIVE_EMPTY, // Inactive style layer for rendering SVG effects. LAYER_SVG_EFFECTS }; -class RefCountedRegion : public RefCounted<RefCountedRegion> { +class RefCountedRegion { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(RefCountedRegion) + NS_INLINE_DECL_REFCOUNTING(RefCountedRegion) + RefCountedRegion() : mIsInfinite(false) {} nsRegion mRegion; bool mIsInfinite; }; struct ContainerLayerParameters { ContainerLayerParameters() : mXScale(1), mYScale(1), mAncestorClipRect(nullptr),
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -5392,31 +5392,22 @@ nsLayoutUtils::SurfaceFromElement(nsIIma int32_t imgWidth, imgHeight; rv = imgContainer->GetWidth(&imgWidth); nsresult rv2 = imgContainer->GetHeight(&imgHeight); if (NS_FAILED(rv) || NS_FAILED(rv2)) return result; if (!noRasterize || imgContainer->GetType() == imgIContainer::TYPE_RASTER) { - bool wantImageSurface = (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) != 0; - if (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA) { - wantImageSurface = true; + if (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) { + frameFlags |= imgIContainer::FLAG_WANT_DATA_SURFACE; } - - nsRefPtr<gfxASurface> gfxsurf = - imgContainer->GetFrame(whichFrame, frameFlags); - if (!gfxsurf) + result.mSourceSurface = imgContainer->GetFrame(whichFrame, frameFlags); + if (!result.mSourceSurface) { return result; - - if (wantImageSurface) { - result.mSourceSurface = gfxPlatform::GetPlatform()->GetWrappedDataSourceSurface(gfxsurf); - } - if (!result.mSourceSurface) { - result.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTarget, gfxsurf); } } else { result.mDrawInfo.mImgContainer = imgContainer; result.mDrawInfo.mWhichFrame = whichFrame; result.mDrawInfo.mDrawingFlags = frameFlags; } int32_t corsmode;
--- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -1079,17 +1079,17 @@ static const mozilla::Module::ContractID { "@mozilla.org/layout/xul-boxobject-tree;1", &kNS_TREEBOXOBJECT_CID }, #endif // MOZ_XUL #ifdef MOZ_XUL { "@mozilla.org/inspector/dom-view;1", &kIN_DOMVIEW_CID }, #endif { "@mozilla.org/inspector/deep-tree-walker;1", &kIN_DEEPTREEWALKER_CID }, { "@mozilla.org/inspector/flasher;1", &kIN_FLASHER_CID }, { "@mozilla.org/inspector/search;1?type=cssvalue", &kIN_CSSVALUESEARCH_CID }, - { "@mozilla.org/inspector/dom-utils;1", &kIN_DOMUTILS_CID }, + { IN_DOMUTILS_CONTRACTID, &kIN_DOMUTILS_CID }, { "@mozilla.org/xml/xml-document;1", &kNS_XMLDOCUMENT_CID }, { "@mozilla.org/svg/svg-document;1", &kNS_SVGDOCUMENT_CID }, { NS_DOMMULTIPARTBLOB_CONTRACTID, &kNS_DOMMULTIPARTBLOB_CID }, { NS_DOMMULTIPARTFILE_CONTRACTID, &kNS_DOMMULTIPARTFILE_CID }, { "@mozilla.org/content/dom-selection;1", &kNS_DOMSELECTION_CID }, { "@mozilla.org/content/post-content-iterator;1", &kNS_CONTENTITERATOR_CID }, { "@mozilla.org/content/pre-content-iterator;1", &kNS_PRECONTENTITERATOR_CID }, { "@mozilla.org/content/subtree-content-iterator;1", &kNS_SUBTREEITERATOR_CID },
--- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -210,17 +210,17 @@ static void BlitSurface(DrawTarget* aDes void nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame); nsPoint offset = ToReferenceFrame(); nsRect bgClipRect = frame->CanvasArea() + offset; - nsRenderingContext context; + nsRefPtr<nsRenderingContext> context; nsRefPtr<gfxContext> dest = aCtx->ThebesContext(); nsRefPtr<gfxASurface> surf; RefPtr<DrawTarget> dt; nsRefPtr<gfxContext> ctx; gfxRect destRect; #ifndef MOZ_GFX_OPTIMIZE_MOBILE if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) && aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() && @@ -249,23 +249,24 @@ nsDisplayCanvasBackgroundImage::Paint(ns } if (surf || dt) { if (surf) { ctx = new gfxContext(surf); } else { ctx = new gfxContext(dt); } ctx->Translate(-gfxPoint(destRect.x, destRect.y)); - context.Init(aCtx->DeviceContext(), ctx); + context = new nsRenderingContext(); + context->Init(aCtx->DeviceContext(), ctx); } } #endif PaintInternal(aBuilder, - (surf || dt) ? &context : aCtx, + (surf || dt) ? context.get() : aCtx, (surf || dt) ? bgClipRect: mVisibleRect, &bgClipRect); if (surf) { BlitSurface(dest, destRect, surf); frame->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().take()); }
--- a/layout/inspector/inDOMView.cpp +++ b/layout/inspector/inDOMView.cpp @@ -19,16 +19,17 @@ #include "nsIDOMMutationEvent.h" #include "nsBindingManager.h" #include "nsNameSpaceManager.h" #include "nsIDocument.h" #include "nsIServiceManager.h" #include "nsITreeColumns.h" #include "nsITreeBoxObject.h" #include "mozilla/dom/Element.h" +#include "mozilla/Services.h" #ifdef ACCESSIBILITY #include "nsIAccessible.h" #include "nsIAccessibilityService.h" #endif using namespace mozilla; @@ -785,17 +786,17 @@ inDOMView::ContentInserted(nsIDocument * { if (!mTree) return; nsresult rv; nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(aChild)); nsCOMPtr<nsIDOMNode> parent; if (!mDOMUtils) { - mDOMUtils = do_GetService("@mozilla.org/inspector/dom-utils;1"); + mDOMUtils = services::GetInDOMUtils(); if (!mDOMUtils) { return; } } mDOMUtils->GetParentForNode(childDOMNode, mShowAnonymous, getter_AddRefs(parent)); // find the inDOMViewNode for the parent of the inserted content @@ -1184,17 +1185,17 @@ inDOMView::GetChildNodesFor(nsIDOMNode* AppendAttrsToArray(attrs, aResult); } } } if (mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT) { nsCOMPtr<nsIDOMNodeList> kids; if (!mDOMUtils) { - mDOMUtils = do_GetService("@mozilla.org/inspector/dom-utils;1"); + mDOMUtils = services::GetInDOMUtils(); if (!mDOMUtils) { return NS_ERROR_FAILURE; } } mDOMUtils->GetChildrenForNode(aNode, mShowAnonymous, getter_AddRefs(kids)); @@ -1229,17 +1230,17 @@ inDOMView::AppendKidsToArray(nsIDOMNodeL { uint32_t l = 0; aKids->GetLength(&l); nsCOMPtr<nsIDOMNode> kid; uint16_t nodeType = 0; // Try and get DOM Utils in case we don't have one yet. if (!mShowWhitespaceNodes && !mDOMUtils) { - mDOMUtils = do_CreateInstance("@mozilla.org/inspector/dom-utils;1"); + mDOMUtils = services::GetInDOMUtils(); } for (uint32_t i = 0; i < l; ++i) { aKids->Item(i, getter_AddRefs(kid)); kid->GetNodeType(&nodeType); NS_ASSERTION(nodeType && nodeType <= nsIDOMNode::NOTATION_NODE, "Unknown node type. "
--- a/layout/inspector/inIDOMUtils.idl +++ b/layout/inspector/inIDOMUtils.idl @@ -99,8 +99,12 @@ interface inIDOMUtils : nsISupports * Parse CSS and update the style sheet in place. * * @param DOMCSSStyleSheet aSheet * @param DOMString aInput * The new source string for the style sheet. */ void parseStyleSheet(in nsIDOMCSSStyleSheet aSheet, in DOMString aInput); }; + +%{ C++ +#define IN_DOMUTILS_CONTRACTID "@mozilla.org/inspector/dom-utils;1" +%}
--- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -653,43 +653,30 @@ public: { if (mTouchSensitiveRegion.IsEmpty()) return false; *aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds()); return true; } - virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid) + virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, + APZStateChange aChange, + int aArg) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( FROM_HERE, - NewRunnableMethod(this, &RemoteContentController::NotifyTransformBegin, - aGuid)); + NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange, + aGuid, aChange, aArg)); return; } if (mRenderFrame) { TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); - browser->NotifyTransformBegin(aGuid.mScrollId); - } - } - - virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid) - { - if (MessageLoop::current() != mUILoop) { - mUILoop->PostTask( - FROM_HERE, - NewRunnableMethod(this, &RemoteContentController::NotifyTransformEnd, - aGuid)); - return; - } - if (mRenderFrame) { - TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); - browser->NotifyTransformEnd(aGuid.mScrollId); + browser->NotifyAPZStateChange(aGuid.mScrollId, aChange, aArg); } } // Methods used by RenderFrameParent to set fields stored here. void SaveZoomConstraints(const ZoomConstraints& aConstraints) { mHaveZoomConstraints = true;
--- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -313,21 +313,21 @@ nsFilterInstance::BuildSourcePaint(Sourc if (!offscreenDT) { return NS_ERROR_OUT_OF_MEMORY; } ctx = new gfxContext(offscreenDT); } ctx->Translate(-neededRect.TopLeft()); - nsRenderingContext tmpCtx; - tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx); + nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext()); + tmpCtx->Init(mTargetFrame->PresContext()->DeviceContext(), ctx); gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert(); - gfxContext *gfx = tmpCtx.ThebesContext(); + gfxContext *gfx = tmpCtx->ThebesContext(); gfx->Multiply(deviceToFilterSpace); gfx->Save(); gfxMatrix matrix = nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING, mTransformRoot); if (!matrix.IsSingular()) { @@ -396,18 +396,18 @@ nsFilterInstance::BuildSourceImage(gfxAS if (!offscreenDT) { return NS_ERROR_OUT_OF_MEMORY; } ctx = new gfxContext(offscreenDT); } ctx->Translate(-neededRect.TopLeft()); - nsRenderingContext tmpCtx; - tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx); + nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext()); + tmpCtx->Init(mTargetFrame->PresContext()->DeviceContext(), ctx); gfxRect r = FilterSpaceToUserSpace(neededRect); r.RoundOut(); nsIntRect dirty; if (!gfxUtils::GfxRectToIntRect(r, &dirty)) return NS_ERROR_FAILURE; // SVG graphics paint to device space, so we need to set an initial device @@ -417,18 +417,18 @@ nsFilterInstance::BuildSourceImage(gfxAS // (In theory it would be better to minimize error by having filtered SVG // graphics temporarily paint to user space when painting the sources and // only set a user space to filter space transform on the gfxContext // (since that would eliminate the transform multiplications from user // space to device space and back again). However, that would make the // code more complex while being hard to get right without introducing // subtle bugs, and in practice it probably makes no real difference.) gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert(); - tmpCtx.ThebesContext()->Multiply(deviceToFilterSpace); - mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty, mTransformRoot); + tmpCtx->ThebesContext()->Multiply(deviceToFilterSpace); + mPaintCallback->Paint(tmpCtx, mTargetFrame, &dirty, mTransformRoot); RefPtr<SourceSurface> sourceGraphicSource; if (offscreenSurface) { sourceGraphicSource = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface); } else { sourceGraphicSource = offscreenDT->Snapshot();
--- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -600,18 +600,18 @@ PaintFrameCallback::operator()(gfxContex const GraphicsFilter& aFilter, const gfxMatrix& aTransform) { if (mFrame->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER) return false; mFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); - nsRenderingContext context; - context.Init(mFrame->PresContext()->DeviceContext(), aContext); + nsRefPtr<nsRenderingContext> context(new nsRenderingContext()); + context->Init(mFrame->PresContext()->DeviceContext(), aContext); aContext->Save(); // Clip to aFillRect so that we don't paint outside. aContext->NewPath(); aContext->Rectangle(aFillRect); aContext->Clip(); aContext->Multiply(gfxMatrix(aTransform).Invert()); @@ -639,17 +639,17 @@ PaintFrameCallback::operator()(gfxContex nsRect dirty(-offset.x, -offset.y, mPaintServerSize.width, mPaintServerSize.height); uint32_t flags = nsLayoutUtils::PAINT_IN_TRANSFORM | nsLayoutUtils::PAINT_ALL_CONTINUATIONS; if (mFlags & nsSVGIntegrationUtils::FLAG_SYNC_DECODE_IMAGES) { flags |= nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES; } - nsLayoutUtils::PaintFrame(&context, mFrame, + nsLayoutUtils::PaintFrame(context, mFrame, dirty, NS_RGBA(0, 0, 0, 0), flags); aContext->Restore(); mFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); return true;
--- a/layout/svg/nsSVGMaskFrame.cpp +++ b/layout/svg/nsSVGMaskFrame.cpp @@ -221,35 +221,35 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRende // 'image'. However, we need to set the same matrix on the temporary context // and pattern that we create below as is currently set on 'gfx'. // Unfortunately, any device offset set by SetDeviceOffset() is affected by // the transform passed to the SetMatrix() calls, so to avoid that we account // for the device offset in the transform rather than use SetDeviceOffset(). gfxMatrix matrix = gfx->CurrentMatrix() * gfxMatrix().Translate(-clipExtents.TopLeft()); - nsRenderingContext tmpCtx; - tmpCtx.Init(this->PresContext()->DeviceContext(), image); - tmpCtx.ThebesContext()->SetMatrix(matrix); + nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext); + tmpCtx->Init(this->PresContext()->DeviceContext(), image); + tmpCtx->ThebesContext()->SetMatrix(matrix); mMaskParent = aParent; if (mMaskParentMatrix) { *mMaskParentMatrix = aMatrix; } else { mMaskParentMatrix = new gfxMatrix(aMatrix); } for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) { // The CTM of each frame referencing us can be different nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED); } - nsSVGUtils::PaintFrameWithEffects(&tmpCtx, nullptr, kid); + nsSVGUtils::PaintFrameWithEffects(tmpCtx, nullptr, kid); } uint8_t *data = image->Data(); int32_t stride = image->Stride(); nsIntRect rect(0, 0, surfaceSize.width, surfaceSize.height); if (StyleSVGReset()->mMaskType == NS_STYLE_MASK_TYPE_LUMINANCE) { if (StyleSVG()->mColorInterpolation ==
--- a/layout/svg/nsSVGPatternFrame.cpp +++ b/layout/svg/nsSVGPatternFrame.cpp @@ -367,19 +367,19 @@ nsSVGPatternFrame::PaintPattern(gfxASurf } nsRefPtr<gfxASurface> tmpSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(surfaceSize, gfxContentType::COLOR_ALPHA); if (!tmpSurface || tmpSurface->CairoStatus()) return NS_ERROR_FAILURE; - nsRenderingContext context; - context.Init(aSource->PresContext()->DeviceContext(), tmpSurface); - gfxContext* gfx = context.ThebesContext(); + nsRefPtr<nsRenderingContext> context(new nsRenderingContext()); + context->Init(aSource->PresContext()->DeviceContext(), tmpSurface); + gfxContext* gfx = context->ThebesContext(); // Fill with transparent black gfx->SetOperator(gfxContext::OPERATOR_CLEAR); gfx->Paint(); gfx->SetOperator(gfxContext::OPERATOR_OVER); if (aGraphicOpacity != 1.0f) { gfx->Save(); @@ -401,17 +401,17 @@ nsSVGPatternFrame::PaintPattern(gfxASurf patternFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); for (nsIFrame* kid = firstKid; kid; kid = kid->GetNextSibling()) { // The CTM of each frame referencing us can be different nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED); } - nsSVGUtils::PaintFrameWithEffects(&context, nullptr, kid); + nsSVGUtils::PaintFrameWithEffects(context, nullptr, kid); } patternFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); } patternFrame->mSource = nullptr; if (aGraphicOpacity != 1.0f) { gfx->PopGroupToSource();
--- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -1466,21 +1466,22 @@ nsSVGUtils::PaintSVGGlyph(Element* aElem DrawMode aDrawMode, gfxTextContextPaint* aContextPaint) { nsIFrame* frame = aElement->GetPrimaryFrame(); nsISVGChildFrame* svgFrame = do_QueryFrame(frame); if (!svgFrame) { return false; } - nsRenderingContext context; - context.Init(frame->PresContext()->DeviceContext(), aContext); - context.AddUserData(&gfxTextContextPaint::sUserDataKey, aContextPaint, nullptr); + nsRefPtr<nsRenderingContext> context(new nsRenderingContext()); + context->Init(frame->PresContext()->DeviceContext(), aContext); + context->AddUserData(&gfxTextContextPaint::sUserDataKey, aContextPaint, + nullptr); svgFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED); - nsresult rv = svgFrame->PaintSVG(&context, nullptr, frame); + nsresult rv = svgFrame->PaintSVG(context, nullptr, frame); return NS_SUCCEEDED(rv); } bool nsSVGUtils::GetSVGGlyphExtents(Element* aElement, const gfxMatrix& aSVGToAppSpace, gfxRect* aResult) {
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp_token.c +++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp_token.c @@ -1573,17 +1573,17 @@ sdp_result_e sdp_build_media (sdp_t *sdp flex_string_sprintf(fs, " %s", sdp_get_payload_name((sdp_payload_e)mca_p->payload_type[i])); } else { flex_string_sprintf(fs, " %u", mca_p->payload_type[i]); } } } else { /* Add port to SDP if transport is DTLS/SCTP */ - flex_string_sprintf(fs, " %u ", (u32)mca_p->sctpport); + flex_string_sprintf(fs, " %u", (u32)mca_p->sctpport); } flex_string_sprintf(fs, "\r\n"); if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) { SDP_PRINT("%s Built m= media line", sdp_p->debug_str); } return (SDP_SUCCESS);
--- a/media/webrtc/signaling/test/signaling_unittests.cpp +++ b/media/webrtc/signaling/test/signaling_unittests.cpp @@ -2812,17 +2812,17 @@ TEST_F(SignalingTest, missingUfrag) "a=rtpmap:120 VP8/90000\r\n" "a=recvonly\r\n" "a=candidate:0 1 UDP 2113601791 192.168.178.20 49929 typ host\r\n" "a=candidate:1 1 UDP 1694236671 77.9.79.167 49929 typ srflx raddr " "192.168.178.20 rport 49929\r\n" "a=candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ host\r\n" "a=candidate:1 2 UDP 1694236670 77.9.79.167 50769 typ srflx raddr " "192.168.178.20 rport 50769\r\n" - "m=application 54054 DTLS/SCTP 5000 \r\n" + "m=application 54054 DTLS/SCTP 5000\r\n" "c=IN IP4 77.9.79.167\r\n" "a=fmtp:HuRUu]Dtcl\\zM,7(OmEU%O$gU]x/z\tD protocol=webrtc-datachannel;" "streams=16\r\n" "a=sendrecv\r\n"; // Need to create an offer, since that's currently required by our // FSM. This may change in the future. a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
--- a/netwerk/base/src/NetworkActivityMonitor.cpp +++ b/netwerk/base/src/NetworkActivityMonitor.cpp @@ -146,47 +146,54 @@ nsNetMon_AcceptRead(PRFileDesc *listenSo if (ret > 0) NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kDownload); return ret; } class NotifyNetworkActivity : public nsRunnable { public: - NotifyNetworkActivity(nsIObserverService* aObs, - NetworkActivityMonitor::Direction aDirection) - : mObs(aObs) - , mDirection(aDirection) + NotifyNetworkActivity(NetworkActivityMonitor::Direction aDirection) + : mDirection(aDirection) {} NS_IMETHOD Run() { - mObs->NotifyObservers(nullptr, - mDirection == NetworkActivityMonitor::kUpload - ? NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC - : NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, - nullptr); + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (!obs) + return NS_ERROR_FAILURE; + + obs->NotifyObservers(nullptr, + mDirection == NetworkActivityMonitor::kUpload + ? NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC + : NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, + nullptr); return NS_OK; } private: nsCOMPtr<nsIObserverService> mObs; NetworkActivityMonitor::Direction mDirection; }; NetworkActivityMonitor * NetworkActivityMonitor::gInstance = nullptr; NetworkActivityMonitor::NetworkActivityMonitor() : mLayerIdentity(PR_INVALID_IO_LAYER) , mBlipInterval(PR_INTERVAL_NO_TIMEOUT) { + MOZ_COUNT_CTOR(NetworkActivityMonitor); + NS_ASSERTION(gInstance==nullptr, "multiple NetworkActivityMonitor instances!"); } NetworkActivityMonitor::~NetworkActivityMonitor() { + MOZ_COUNT_DTOR(NetworkActivityMonitor); gInstance = nullptr; } nsresult NetworkActivityMonitor::Init(int32_t blipInterval) { nsresult rv; @@ -224,20 +231,16 @@ NetworkActivityMonitor::Init_Internal(in mLayerMethods.write = nsNetMon_Write; mLayerMethods.writev = nsNetMon_Writev; mLayerMethods.recv = nsNetMon_Recv; mLayerMethods.send = nsNetMon_Send; mLayerMethods.recvfrom = nsNetMon_RecvFrom; mLayerMethods.sendto = nsNetMon_SendTo; mLayerMethods.acceptread = nsNetMon_AcceptRead; - mObserverService = mozilla::services::GetObserverService(); - if (!mObserverService) - return NS_ERROR_FAILURE; - mBlipInterval = PR_MillisecondsToInterval(blipInterval); // Set the last notification times to time that has just expired, so any // activity even right now will trigger notification. mLastNotificationTime[kUpload] = PR_IntervalNow() - mBlipInterval; mLastNotificationTime[kDownload] = mLastNotificationTime[kUpload]; return NS_OK; } @@ -282,12 +285,11 @@ NetworkActivityMonitor::DataInOut(Direct } return NS_OK; } void NetworkActivityMonitor::PostNotification(Direction direction) { - nsRefPtr<nsIRunnable> ev = new NotifyNetworkActivity(mObserverService, - direction); + nsRefPtr<nsIRunnable> ev = new NotifyNetworkActivity(direction); NS_DispatchToMainThread(ev); }
--- a/netwerk/base/src/NetworkActivityMonitor.h +++ b/netwerk/base/src/NetworkActivityMonitor.h @@ -2,22 +2,21 @@ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NetworkActivityMonitor_h___ #define NetworkActivityMonitor_h___ -#include "nsCOMPtr.h" +#include <stdint.h> +#include "nscore.h" #include "prio.h" #include "prinrval.h" -class nsIObserverService; - namespace mozilla { namespace net { class NetworkActivityMonitor { public: enum Direction { kUpload = 0, kDownload = 1 @@ -36,14 +35,13 @@ private: nsresult Init_Internal(int32_t blipInterval); void PostNotification(Direction direction); static NetworkActivityMonitor * gInstance; PRDescIdentity mLayerIdentity; PRIOMethods mLayerMethods; PRIntervalTime mBlipInterval; PRIntervalTime mLastNotificationTime[2]; - nsCOMPtr<nsIObserverService> mObserverService; }; }} // namespace mozilla::net #endif /* NetworkActivityMonitor_h___ */
--- a/security/manager/ssl/src/SharedCertVerifier.h +++ b/security/manager/ssl/src/SharedCertVerifier.h @@ -6,32 +6,34 @@ #define mozilla_psm__SharedCertVerifier_h #include "certt.h" #include "CertVerifier.h" #include "mozilla/RefPtr.h" namespace mozilla { namespace psm { -class SharedCertVerifier : public mozilla::psm::CertVerifier, - public mozilla::AtomicRefCounted<SharedCertVerifier> +class SharedCertVerifier : public mozilla::psm::CertVerifier { +protected: + ~SharedCertVerifier(); + public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(SharedCertVerifier) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedCertVerifier) + SharedCertVerifier(implementation_config ic, #ifndef NSS_NO_LIBPKIX missing_cert_download_config ac, crl_download_config cdc, #endif ocsp_download_config odc, ocsp_strict_config osc, ocsp_get_config ogc) : mozilla::psm::CertVerifier(ic, #ifndef NSS_NO_LIBPKIX ac, cdc, #endif odc, osc, ogc) { } - ~SharedCertVerifier(); }; } } // namespace mozilla::psm #endif // mozilla_psm__SharedCertVerifier_h
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp +++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp @@ -134,13 +134,17 @@ GetOCSPResponseForType(OCSPResponseType SECItem* response = CreateEncodedOCSPResponse(context); if (!response) { PrintPRError("CreateEncodedOCSPResponse failed"); return nullptr; } SECItemArray* arr = SECITEM_AllocArray(aArena, nullptr, 1); - arr->items[0].data = response ? response->data : nullptr; - arr->items[0].len = response ? response->len : 0; + if (!arr) { + PrintPRError("SECITEM_AllocArray failed"); + return nullptr; + } + arr->items[0].data = response->data; + arr->items[0].len = response->len; return arr; }
--- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -14,16 +14,18 @@ var _quit = false; var _passed = true; var _tests_pending = 0; var _passedChecks = 0, _falsePassedChecks = 0; var _todoChecks = 0; var _cleanupFunctions = []; var _pendingTimers = []; var _profileInitialized = false; +let _Promise = Components.utils.import("resource://gre/modules/Promise.jsm", this).Promise; + let _log = function (action, params) { if (typeof _XPCSHELL_PROCESS != "undefined") { params.process = _XPCSHELL_PROCESS; } params.action = action; params._time = Date.now(); dump("\n" + JSON.stringify(params) + "\n"); } @@ -175,17 +177,17 @@ function _do_main() { while (thr.hasPendingEvents()) thr.processNextEvent(true); } function _do_quit() { _log("test_info", {_message: "TEST-INFO | (xpcshell/head.js) | exiting test\n"}); - + _Promise.Debugging.flushUncaughtErrors(); _quit = true; } function _format_exception_stack(stack) { if (typeof stack == "object" && stack.caller) { let frame = stack; let strStack = ""; while (frame != null) { @@ -343,16 +345,25 @@ function _register_protocol_handlers() { function _execute_test() { _register_protocol_handlers(); // Override idle service by default. // Call do_get_idle() to restore the factory and get the service. _fakeIdleService.activate(); + _Promise.Debugging.clearUncaughtErrorObservers(); + _Promise.Debugging.addUncaughtErrorObserver(function observer({message, date, fileName, stack, lineNumber}) { + let text = "Once bug 976205 has landed, THIS ERROR WILL CAUSE A TEST FAILURE.\n" + + " A promise chain failed to handle a rejection: " + + message + " - rejection date: " + date; + _log_message_with_stack("test_known_fail", + text, stack, fileName); + }); + // _HEAD_FILES is dynamically defined by <runxpcshelltests.py>. _load_files(_HEAD_FILES); // _TEST_FILE is dynamically defined by <runxpcshelltests.py>. _load_files(_TEST_FILE); // Support a common assertion library, Assert.jsm. let Assert = Components.utils.import("resource://testing-common/Assert.jsm", null).Assert; // Pass a custom report function for xpcshell-test style reporting. @@ -1423,20 +1434,22 @@ let _gTestIndex = 0; // The index of the let _gTaskRunning = false; function run_next_test() { if (_gTaskRunning) { throw new Error("run_next_test() called from an add_task() test function. " + "run_next_test() should not be called from inside add_task() " + "under any circumstances!"); } - + function _run_next_test() { if (_gTestIndex < _gTests.length) { + // Flush uncaught errors as early and often as possible. + _Promise.Debugging.flushUncaughtErrors(); let _isTask; [_isTask, _gRunningTest] = _gTests[_gTestIndex++]; print("TEST-INFO | " + _TEST_FILE + " | Starting " + _gRunningTest.name); do_test_pending(_gRunningTest.name); if (_isTask) { _gTaskRunning = true; _Task.spawn(_gRunningTest).then(
--- a/toolkit/content/widgets/findbar.xml +++ b/toolkit/content/widgets/findbar.xml @@ -169,23 +169,16 @@ xbl:inherits="accesskey=findpreviousaccesskey"/> <xul:toolbarbutton anonid="find-next" class="findbar-find-next tabbable" tooltiptext="&next.tooltip;" oncommand="onFindAgainCommand(false);" disabled="true" xbl:inherits="accesskey=findnextaccesskey"/> </xul:hbox> - <xul:image anonid="find-status-icon" class="findbar-find-fast find-status-icon"/> - <xul:description anonid="find-status" - control="findbar-textbox" - class="findbar-find-fast findbar-find-status"> - <!-- Do not use value, first child is used because it provides a11y with text change events --> - </xul:description> - <xul:spacer flex="1"/> <xul:toolbarbutton anonid="highlight" class="findbar-highlight tabbable" label="&highlightAll.label;" accesskey="&highlightAll.accesskey;" tooltiptext="&highlightAll.tooltiptext;" oncommand="toggleHighlight(this.checked);" type="checkbox" xbl:inherits="accesskey=highlightaccesskey"/> @@ -193,16 +186,22 @@ class="findbar-case-sensitive tabbable" label="&caseSensitive.label;" accesskey="&caseSensitive.accesskey;" tooltiptext="&caseSensitive.tooltiptext;" oncommand="_setCaseSensitivity(this.checked);" type="checkbox" xbl:inherits="accesskey=matchcaseaccesskey"/> <xul:label anonid="match-case-status" class="findbar-find-fast"/> + <xul:image anonid="find-status-icon" class="findbar-find-fast find-status-icon"/> + <xul:description anonid="find-status" + control="findbar-textbox" + class="findbar-find-fast findbar-find-status"> + <!-- Do not use value, first child is used because it provides a11y with text change events --> + </xul:description> </xul:hbox> <xul:toolbarbutton anonid="find-closebutton" class="findbar-closebutton close-icon" tooltiptext="&findCloseButton.tooltip;" oncommand="close();"/> </content> <implementation implements="nsIDOMEventListener, nsIEditActionListener">
--- a/toolkit/modules/Promise-backend.js +++ b/toolkit/modules/Promise-backend.js @@ -73,18 +73,37 @@ const N_WITNESS = Name("witness"); // In this snippet, the error is reported both by p1 and by p2. // XPCOMUtils.defineLazyServiceGetter(this, "FinalizationWitnessService", "@mozilla.org/toolkit/finalizationwitness;1", "nsIFinalizationWitnessService"); let PendingErrors = { + // An internal counter, used to generate unique id. _counter: 0, + // Functions registered to be notified when a pending error + // is reported as uncaught. + _observers: new Set(), _map: new Map(), + + /** + * Initialize PendingErrors + */ + init: function() { + Services.obs.addObserver(function observe(aSubject, aTopic, aValue) { + PendingErrors.report(aValue); + }, "promise-finalization-witness", false); + }, + + /** + * Register an error as tracked. + * + * @return The unique identifier of the error. + */ register: function(error) { let id = "pending-error-" + (this._counter++); // // At this stage, ideally, we would like to store the error itself // and delay any treatment until we are certain that we will need // to report that error. However, in the (unlikely but possible) // case the error holds a reference to the promise itself, doing so // would prevent the promise from being garbabe-collected, which @@ -161,56 +180,112 @@ let PendingErrors = { } } } catch (ex) { // Ignore value } this._map.set(id, value); return id; }, - extract: function(id) { + + /** + * Notify all observers that a pending error is now uncaught. + * + * @param id The identifier of the pending error, as returned by + * |register|. + */ + report: function(id) { let value = this._map.get(id); + if (!value) { + return; // The error has already been reported + } this._map.delete(id); - return value; + for (let obs of this._observers.values()) { + obs(value); + } }, + + /** + * Mark all pending errors are uncaught, notify the observers. + */ + flush: function() { + // Since we are going to modify the map while walking it, + // let's copying the keys first. + let keys = [key for (key of this._map.keys())]; + for (let key of keys) { + this.report(key); + } + }, + + /** + * Stop tracking an error, as this error has been caught, + * eventually. + */ unregister: function(id) { this._map.delete(id); + }, + + /** + * Add an observer notified when an error is reported as uncaught. + * + * @param {function} observer A function notified when an error is + * reported as uncaught. Its arguments are + * {message, date, fileName, stack, lineNumber} + * All arguments are optional. + */ + addObserver: function(observer) { + this._observers.add(observer); + }, + + /** + * Remove an observer added with addObserver + */ + removeObserver: function(observer) { + this._observers.delete(observer); + }, + + /** + * Remove all the observers added with addObserver + */ + removeAllObservers: function() { + this._observers.clear(); } }; +PendingErrors.init(); -// Actually print the finalization warning. -Services.obs.addObserver(function observe(aSubject, aTopic, aValue) { - let error = PendingErrors.extract(aValue); - let {message, date, fileName, stack, lineNumber} = error; +// Default mechanism for displaying errors +PendingErrors.addObserver(function(details) { let error = Cc['@mozilla.org/scripterror;1'].createInstance(Ci.nsIScriptError); if (!error || !Services.console) { // Too late during shutdown to use the nsIConsole dump("*************************\n"); dump("A promise chain failed to handle a rejection\n\n"); - dump("On: " + date + "\n"); - dump("Full message: " + message + "\n"); + dump("On: " + details.date + "\n"); + dump("Full message: " + details.message + "\n"); dump("See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise\n"); - dump("Full stack: " + (stack||"not available") + "\n"); + dump("Full stack: " + (details.stack||"not available") + "\n"); dump("*************************\n"); return; } - if (stack) { - message += "\nFull Stack: " + stack; + let message = details.message; + if (details.stack) { + message += "\nFull Stack: " + details.stack; } error.init( /*message*/"A promise chain failed to handle a rejection.\n\n" + - "Date: " + date + "\nFull Message: " + message, - /*sourceName*/ fileName, - /*sourceLine*/ lineNumber?("" + lineNumber):0, - /*lineNumber*/ lineNumber || 0, + "Date: " + details.date + "\nFull Message: " + details.message, + /*sourceName*/ details.fileName, + /*sourceLine*/ details.lineNumber?("" + details.lineNumber):0, + /*lineNumber*/ details.lineNumber || 0, /*columnNumber*/ 0, /*flags*/ Ci.nsIScriptError.errorFlag, /*category*/ "chrome javascript"); Services.console.logMessage(error); -}, "promise-finalization-witness", false); +}); + ///////// Additional warnings for developers // // The following error types are considered programmer errors, which should be // reported (possibly redundantly) so as to let programmers fix their code. const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"]; //////////////////////////////////////////////////////////////////////////////// @@ -491,16 +566,56 @@ Promise.race = function (aValues) return new Promise((resolve, reject) => { for (let value of aValues) { Promise.resolve(value).then(resolve, reject); } }); }; +Promise.Debugging = { + /** + * Add an observer notified when an error is reported as uncaught. + * + * @param {function} observer A function notified when an error is + * reported as uncaught. Its arguments are + * {message, date, fileName, stack, lineNumber} + * All arguments are optional. + */ + addUncaughtErrorObserver: function(observer) { + PendingErrors.addObserver(observer); + }, + + /** + * Remove an observer added with addUncaughtErrorObserver + * + * @param {function} An observer registered with + * addUncaughtErrorObserver. + */ + removeUncaughtErrorObserver: function(observer) { + PendingErrors.removeObserver(observer); + }, + + /** + * Remove all the observers added with addUncaughtErrorObserver + */ + clearUncaughtErrorObservers: function() { + PendingErrors.removeAllObservers(); + }, + + /** + * Force all pending errors to be reported immediately as uncaught. + * Note that this may cause some false positives. + */ + flushUncaughtErrors: function() { + PendingErrors.flush(); + }, +}; +Object.freeze(Promise.Debugging); + Object.freeze(Promise); //////////////////////////////////////////////////////////////////////////////// //// PromiseWalker /** * This singleton object invokes the handlers registered on resolved and * rejected promises, ensuring that processing is not recursive and is done in
--- a/toolkit/modules/tests/xpcshell/test_Promise.js +++ b/toolkit/modules/tests/xpcshell/test_Promise.js @@ -1,16 +1,20 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; Components.utils.import("resource://gre/modules/Promise.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Task.jsm"); +// Deactivate the standard xpcshell observer, as it turns uncaught +// rejections into failures, which we don't want here. +Promise.Debugging.clearUncaughtErrorObservers(); + //////////////////////////////////////////////////////////////////////////////// //// Test runner let run_promise_tests = function run_promise_tests(tests, cb) { let loop = function loop(index) { if (index >= tests.length) { if (cb) { cb.call(); @@ -954,38 +958,36 @@ tests.push( function wait_for_uncaught(aMustAppear, aTimeout = undefined) { let remaining = new Set(); for (let k of aMustAppear) { remaining.add(k); } let deferred = Promise.defer(); let print = do_print; let execute_soon = do_execute_soon; - let observer = function(aMessage) { - execute_soon(function() { - let message = aMessage.message; - print("Observing " + message); - for (let expected of remaining) { - if (message.indexOf(expected) != -1) { - print("I found " + expected); - remaining.delete(expected); - } + let observer = function({message, stack}) { + let data = message + stack; + print("Observing " + message + ", looking for " + aMustAppear.join(", ")); + for (let expected of remaining) { + if (data.indexOf(expected) != -1) { + print("I found " + expected); + remaining.delete(expected); } if (remaining.size == 0 && observer) { - Services.console.unregisterListener(observer); + Promise.Debugging.removeUncaughtErrorObserver(observer); observer = null; deferred.resolve(); } - }); + } }; - Services.console.registerListener(observer); + Promise.Debugging.addUncaughtErrorObserver(observer); if (aTimeout) { do_timeout(aTimeout, function timeout() { if (observer) { - Services.console.unregisterListener(observer); + Promise.Debugging.removeUncaughtErrorObserver(observer); observer = null; } deferred.reject(new Error("Timeout")); }); } return deferred.promise; } @@ -1050,16 +1052,17 @@ function wait_for_uncaught(aMustAppear, // // Unfortunately, we might still have intermittent failures, // materialized as timeouts. // for (let i = 0; i < 100; ++i) { Promise.reject(error); } })(); + do_print("Posted all rejections"); Components.utils.forceGC(); Components.utils.forceCC(); Components.utils.forceShrinkingGC(); return promise; })); } })();
--- a/widget/cocoa/nsClipboard.mm +++ b/widget/cocoa/nsClipboard.mm @@ -461,25 +461,19 @@ nsClipboard::PasteboardDictFromTransfera ptrPrimitive->GetData(getter_AddRefs(primitiveData)); nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData)); if (!image) { NS_WARNING("Image isn't an imgIContainer in transferable"); continue; } - nsRefPtr<gfxASurface> thebesSurface = + RefPtr<SourceSurface> surface = image->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); - if (!thebesSurface) { - continue; - } - RefPtr<SourceSurface> surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface( - gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(), thebesSurface); if (!surface) { continue; } CGImageRef imageRef = NULL; nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef); if (NS_FAILED(rv) || !imageRef) { continue; }
--- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -1,15 +1,16 @@ /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gfxImageSurface.h" #include "gfxPlatform.h" +#include "gfxUtils.h" #include "nsCocoaUtils.h" #include "nsChildView.h" #include "nsMenuBarX.h" #include "nsCocoaWindow.h" #include "nsCOMPtr.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIAppShellService.h" #include "nsIXULWindow.h" @@ -21,17 +22,22 @@ #include "mozilla/gfx/2D.h" #include "mozilla/MiscEvents.h" #include "mozilla/Preferences.h" #include "mozilla/TextEvents.h" using namespace mozilla; using namespace mozilla::widget; +using mozilla::gfx::BackendType; using mozilla::gfx::DataSourceSurface; +using mozilla::gfx::DrawTarget; +using mozilla::gfx::Factory; +using mozilla::gfx::IntPoint; +using mozilla::gfx::IntRect; using mozilla::gfx::IntSize; using mozilla::gfx::SurfaceFormat; using mozilla::gfx::SourceSurface; static float MenuBarScreenHeight() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; @@ -273,20 +279,29 @@ void data_ss_release_callback(void *aDat static_cast<DataSourceSurface*>(aDataSourceSurface)->Unmap(); static_cast<DataSourceSurface*>(aDataSourceSurface)->Release(); } } nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface, CGImageRef* aResult) { - RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface(); + RefPtr<DataSourceSurface> dataSurface; - MOZ_ASSERT(dataSurface->GetFormat() == SurfaceFormat::B8G8R8A8, - "We assume B8G8R8A8 when calling CGImageCreate"); + if (aSurface->GetFormat() == SurfaceFormat::B8G8R8A8) { + dataSurface = aSurface->GetDataSurface(); + } else { + // CGImageCreate only supports 16- and 32-bit bit-depth + // Convert format to SurfaceFormat::B8G8R8A8 + dataSurface = gfxUtils:: + CopySurfaceToDataSourceSurfaceWithFormat(aSurface, + SurfaceFormat::B8G8R8A8); + } + + NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); int32_t width = dataSurface->GetSize().width; int32_t height = dataSurface->GetSize().height; if (height < 1 || width < 1) { return NS_ERROR_FAILURE; } DataSourceSurface::MappedSurface map; @@ -396,27 +411,17 @@ nsresult nsCocoaUtils::CreateNSImageFrom gfxRect(0.0f, 0.0f, scaledWidth, scaledHeight), nsIntRect(0, 0, width, height), nsIntSize(scaledWidth, scaledHeight), nullptr, aWhichFrame, imgIContainer::FLAG_SYNC_DECODE); surface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, frame); } else { - nsRefPtr<gfxASurface> thebesSurface = - aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE); - - nsRefPtr<gfxImageSurface> thebesImageSurface = - thebesSurface->GetAsReadableARGB32ImageSurface(); - NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE); - - surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, - thebesImageSurface); + surface = aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE); } NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); CGImageRef imageRef = NULL; nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef); if (NS_FAILED(rv) || !imageRef) { return NS_ERROR_FAILURE;
--- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -382,28 +382,24 @@ nsMenuItemIconX::OnStopFrame(imgIRequest mImageRegionRect.YMost() > origHeight)) { [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; } if (mImageRegionRect.IsEmpty()) { mImageRegionRect.SetRect(0, 0, origWidth, origHeight); } - - nsRefPtr<gfxASurface> thebesSurface = + + RefPtr<SourceSurface> surface = imageContainer->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_NONE); - if (!thebesSurface) { + if (!surface) { [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; } - RefPtr<SourceSurface> surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, - thebesSurface); - NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); CGImageRef origImage = NULL; nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &origImage); if (NS_FAILED(rv) || !origImage) { [mNativeMenuItem setImage:nil]; return NS_ERROR_FAILURE; }
--- a/widget/gtk/nsImageToPixbuf.cpp +++ b/widget/gtk/nsImageToPixbuf.cpp @@ -38,33 +38,28 @@ NS_IMETHODIMP_(GdkPixbuf*) nsImageToPixbuf::ConvertImageToPixbuf(imgIContainer* aImage) { return ImageToPixbuf(aImage); } GdkPixbuf* nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage) { - nsRefPtr<gfxASurface> thebesSurface = + RefPtr<SourceSurface> surface = aImage->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); // If the last call failed, it was probably because our call stack originates // in an imgINotificationObserver event, meaning that we're not allowed request // a sync decode. Presumably the originating event is something sensible like // OnStopFrame(), so we can just retry the call without a sync decode. - if (!thebesSurface) - thebesSurface = aImage->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_NONE); + if (!surface) + surface = aImage->GetFrame(imgIContainer::FRAME_CURRENT, + imgIContainer::FLAG_NONE); - NS_ENSURE_TRUE(thebesSurface, nullptr); - - RefPtr<SourceSurface> surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, - thebesSurface); NS_ENSURE_TRUE(surface, nullptr); return SourceSurfaceToPixbuf(surface, surface->GetSize().width, surface->GetSize().height); } GdkPixbuf*
--- a/widget/qt/nsClipboard.cpp +++ b/widget/qt/nsClipboard.cpp @@ -174,25 +174,19 @@ nsClipboard::SetNativeClipboardData( nsI continue; nsCOMPtr<nsISupports> primitiveData; ptrPrimitive->GetData(getter_AddRefs(primitiveData)); nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData)); if (!image) // Not getting an image for an image mime type!? continue; - nsRefPtr<gfxASurface> thebesSurface = + RefPtr<SourceSurface> surface = image->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); - if (!thebesSurface) - continue; - - RefPtr<SourceSurface> surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, - thebesSurface); if (!surface) continue; RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface(); if (!dataSurface) continue;
--- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -726,22 +726,18 @@ AsyncFaviconDataReady::OnComplete(nsIURI nsAutoCString mimeTypeOfInputData; mimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon"); nsCOMPtr<imgIContainer> container; nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1"); rv = imgtool->DecodeImageData(stream, aMimeType, getter_AddRefs(container)); NS_ENSURE_SUCCESS(rv, rv); - nsRefPtr<gfxASurface> imgFrame = + RefPtr<SourceSurface> surface = container->GetFrame(imgIContainer::FRAME_FIRST, 0); - NS_ENSURE_TRUE(imgFrame, NS_ERROR_FAILURE); - - RefPtr<SourceSurface> surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, imgFrame); NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); RefPtr<DataSourceSurface> dataSurface; IntSize size; if (mURLShortcut) { // Create a 48x48 surface and paint the icon into the central 16x16 rect. size.width = 48;
--- a/widget/windows/nsImageClipboard.cpp +++ b/widget/windows/nsImageClipboard.cpp @@ -1,17 +1,20 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsImageClipboard.h" + +#include "gfxUtils.h" #include "mozilla/gfx/2D.h" +#include "mozilla/gfx/DataSurfaceHelpers.h" #include "mozilla/RefPtr.h" #include "nsITransferable.h" -#include "nsImageClipboard.h" #include "nsGfxCIID.h" #include "nsMemory.h" #include "prmem.h" #include "imgIEncoder.h" #include "nsLiteralString.h" #include "nsComponentManagerUtils.h" #define BFH_LENGTH 14 @@ -115,32 +118,34 @@ nsImageToClipboard::CalcSpanLength(uint3 // image. // nsresult nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap ) { nsresult rv; *outBitmap = nullptr; - nsRefPtr<gfxASurface> thebesSurface = + RefPtr<SourceSurface> surface = inImage->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - nsRefPtr<gfxImageSurface> thebesImageSurface = - thebesSurface->GetAsReadableARGB32ImageSurface(); - NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE); + MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 || + surface->GetFormat() == SurfaceFormat::B8G8R8X8); - IntSize surfaceSize(thebesImageSurface->GetSize().width, - thebesImageSurface->GetSize().height); - RefPtr<DataSourceSurface> dataSurface = - Factory::CreateWrappingDataSourceSurface(thebesImageSurface->Data(), - thebesImageSurface->Stride(), - surfaceSize, - SurfaceFormat::B8G8R8A8); + RefPtr<DataSourceSurface> dataSurface; + if (surface->GetFormat() == SurfaceFormat::B8G8R8A8) { + dataSurface = surface->GetDataSurface(); + } else { + // XXXjwatt Bug 995923 - get rid of this copy and handle B8G8R8X8 + // directly below once bug 995807 is fixed. + dataSurface = gfxUtils:: + CopySurfaceToDataSourceSurfaceWithFormat(surface, + SurfaceFormat::B8G8R8A8); + } NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv); NS_ENSURE_SUCCESS(rv, rv); uint32_t format; nsAutoString options; if (mWantDIBV5) { @@ -148,21 +153,25 @@ nsImageToClipboard::CreateFromImage ( im } else { options.AppendLiteral("version=3;bpp="); } switch (dataSurface->GetFormat()) { case SurfaceFormat::B8G8R8A8: format = imgIEncoder::INPUT_FORMAT_HOSTARGB; options.AppendInt(32); break; +#if 0 + // XXXjwatt Bug 995923 - fix |format| and reenable once bug 995807 is fixed. case SurfaceFormat::B8G8R8X8: format = imgIEncoder::INPUT_FORMAT_RGB; options.AppendInt(24); break; +#endif default: + NS_NOTREACHED("Unexpected surface format"); return NS_ERROR_INVALID_ARG; } DataSourceSurface::MappedSurface map; bool mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map); NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE); rv = encoder->InitFromData(map.mData, 0,
--- a/widget/windows/nsWindowGfx.cpp +++ b/widget/windows/nsWindowGfx.cpp @@ -48,17 +48,16 @@ using mozilla::plugins::PluginInstancePa #ifdef MOZ_ENABLE_D3D10_LAYER #include "LayerManagerD3D10.h" #endif #include "mozilla/layers/CompositorParent.h" #include "ClientLayerManager.h" #include "nsUXThemeData.h" #include "nsUXThemeConstants.h" -#include "mozilla/gfx/2D.h" extern "C" { #define PIXMAN_DONT_DEFINE_STDINT #include "pixman.h" } using namespace mozilla; using namespace mozilla::gfx; @@ -611,57 +610,52 @@ nsresult nsWindowGfx::CreateIcon(imgICon uint32_t aHotspotY, gfxIntSize aScaledSize, HICON *aIcon) { MOZ_ASSERT((aScaledSize.width > 0 && aScaledSize.height > 0) || (aScaledSize.width == 0 && aScaledSize.height == 0)); // Get the image data - nsRefPtr<gfxASurface> thebesSurface = + RefPtr<SourceSurface> surface = aContainer->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(thebesSurface, NS_ERROR_NOT_AVAILABLE); + NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE); - RefPtr<SourceSurface> surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, - thebesSurface); - NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - - IntSize surfaceSize(surface->GetSize().width, surface->GetSize().height); - if (surfaceSize.IsEmpty()) { + IntSize frameSize = surface->GetSize(); + if (frameSize.IsEmpty()) { return NS_ERROR_FAILURE; } IntSize iconSize(aScaledSize.width, aScaledSize.height); if (iconSize == IntSize(0, 0)) { // use frame's intrinsic size - iconSize = surfaceSize; + iconSize = frameSize; } RefPtr<DataSourceSurface> dataSurface; bool mappedOK; DataSourceSurface::MappedSurface map; - if (iconSize != surfaceSize) { + if (iconSize != frameSize) { // Scale the surface dataSurface = Factory::CreateDataSourceSurface(iconSize, SurfaceFormat::B8G8R8A8); NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map); NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE); RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(BackendType::CAIRO, map.mData, dataSurface->GetSize(), map.mStride, SurfaceFormat::B8G8R8A8); dt->DrawSurface(surface, Rect(0, 0, iconSize.width, iconSize.height), - Rect(0, 0, surfaceSize.width, surfaceSize.height), + Rect(0, 0, frameSize.width, frameSize.height), DrawSurfaceOptions(), DrawOptions(1.0f, CompositionOp::OP_SOURCE)); } else if (surface->GetFormat() != SurfaceFormat::B8G8R8A8) { // Convert format to SurfaceFormat::B8G8R8A8 dataSurface = gfxUtils:: CopySurfaceToDataSourceSurfaceWithFormat(surface, SurfaceFormat::B8G8R8A8); NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
--- a/widget/windows/winrt/APZController.cpp +++ b/widget/windows/winrt/APZController.cpp @@ -298,30 +298,42 @@ class TransformedEndEvent : public nsRun { NS_IMETHOD Run() { MetroUtils::FireObserver("apzc-transform-end", L""); return NS_OK; } }; void -APZController::NotifyTransformBegin(const ScrollableLayerGuid& aGuid) +APZController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, + APZStateChange aChange, + int aArg) { - if (NS_IsMainThread()) { - MetroUtils::FireObserver("apzc-transform-begin", L""); - return; + switch (aChange) { + case APZStateChange::TransformBegin: + { + if (NS_IsMainThread()) { + MetroUtils::FireObserver("apzc-transform-begin", L""); + return; + } + nsCOMPtr<nsIRunnable> runnable = new TransformedStartEvent(); + NS_DispatchToMainThread(runnable); + break; + } + case APZStateChange::TransformEnd: + { + if (NS_IsMainThread()) { + MetroUtils::FireObserver("apzc-transform-end", L""); + return; + } + nsCOMPtr<nsIRunnable> runnable = new TransformedEndEvent(); + NS_DispatchToMainThread(runnable); + break; + } + default: + { + // We don't currently care about other state changes. + break; + } } - nsCOMPtr<nsIRunnable> runnable = new TransformedStartEvent(); - NS_DispatchToMainThread(runnable); -} - -void -APZController::NotifyTransformEnd(const ScrollableLayerGuid& aGuid) -{ - if (NS_IsMainThread()) { - MetroUtils::FireObserver("apzc-transform-end", L""); - return; - } - nsCOMPtr<nsIRunnable> runnable = new TransformedEndEvent(); - NS_DispatchToMainThread(runnable); } } } }
--- a/widget/windows/winrt/APZController.h +++ b/widget/windows/winrt/APZController.h @@ -44,18 +44,19 @@ public: int32_t aModifiers, const mozilla::layers::ScrollableLayerGuid& aGuid); virtual void HandleLongTapUp(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const mozilla::layers::ScrollableLayerGuid& aGuid); virtual void SendAsyncScrollDOMEvent(bool aIsRoot, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize); virtual void PostDelayedTask(Task* aTask, int aDelayMs); virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints); - virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid); - virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid); + virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, + APZStateChange aChange, + int aArg); void SetWidgetListener(nsIWidgetListener* aWidgetListener); bool HitTestAPZC(mozilla::ScreenIntPoint& aPoint); void TransformCoordinateToGecko(const mozilla::ScreenIntPoint& aPoint, LayoutDeviceIntPoint* aRefPointOut); void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault); nsEventStatus ReceiveInputEvent(mozilla::WidgetInputEvent* aEvent,
new file mode 100644 --- /dev/null +++ b/widget/xpwidgets/ActiveElementManager.cpp @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ActiveElementManager.h" +#include "mozilla/EventStates.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "inIDOMUtils.h" +#include "nsIDOMDocument.h" +#include "nsIDOMElement.h" +#include "nsIDOMEventTarget.h" +#include "base/message_loop.h" +#include "base/task.h" + +namespace mozilla { +namespace widget { + +static int32_t sActivationDelayMs = 100; +static bool sActivationDelayMsSet = false; + +ActiveElementManager::ActiveElementManager() + : mDomUtils(services::GetInDOMUtils()), + mCanBePan(false), + mCanBePanSet(false), + mSetActiveTask(nullptr) +{ + if (!sActivationDelayMsSet) { + Preferences::AddIntVarCache(&sActivationDelayMs, + "ui.touch_activation.delay_ms", + sActivationDelayMs); + sActivationDelayMsSet = true; + } +} + +ActiveElementManager::~ActiveElementManager() {} + +void +ActiveElementManager::SetTargetElement(nsIDOMEventTarget* aTarget) +{ + if (mTarget) { + // Multiple fingers on screen (since HandleTouchEnd clears mTarget). + ResetActive(); + return; + } + + mTarget = do_QueryInterface(aTarget); + TriggerElementActivation(); +} + +void +ActiveElementManager::HandleTouchStart(bool aCanBePan) +{ + mCanBePan = aCanBePan; + mCanBePanSet = true; + TriggerElementActivation(); +} + +void +ActiveElementManager::TriggerElementActivation() +{ + // Both HandleTouchStart() and SetTargetElement() call this. They can be + // called in either order. One will set mCanBePanSet, and the other, mTarget. + // We want to actually trigger the activation once both are set. + if (!(mTarget && mCanBePanSet)) { + return; + } + + // If the touch cannot be a pan, make mTarget :active right away. + // Otherwise, wait a bit to see if the user will pan or not. + if (!mCanBePan) { + SetActive(mTarget); + } else { + mSetActiveTask = NewRunnableMethod( + this, &ActiveElementManager::SetActiveTask, mTarget); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, mSetActiveTask, sActivationDelayMs); + } +} + +void +ActiveElementManager::HandlePanStart() +{ + // The user started to pan, so we don't want mTarget to be :active. + // Make it not :active, and clear any pending task to make it :active. + CancelTask(); + ResetActive(); +} + +void +ActiveElementManager::HandleTouchEnd(bool aWasClick) +{ + // If the touch was a click, make mTarget :active right away. + // nsEventStateManager will reset the active element when processing + // the mouse-down event generated by the click. + CancelTask(); + if (aWasClick) { + SetActive(mTarget); + } + + // Clear mTarget for next touch. + mTarget = nullptr; +} + +void +ActiveElementManager::SetActive(nsIDOMElement* aTarget) +{ + if (mDomUtils) { + mDomUtils->SetContentState(aTarget, NS_EVENT_STATE_ACTIVE.GetInternalValue());; + } +} + +void +ActiveElementManager::ResetActive() +{ + // Clear the :active flag from mTarget by setting it on the document root. + if (mTarget) { + nsCOMPtr<nsIDOMDocument> doc; + mTarget->GetOwnerDocument(getter_AddRefs(doc)); + if (doc) { + nsCOMPtr<nsIDOMElement> root; + doc->GetDocumentElement(getter_AddRefs(root)); + if (root) { + SetActive(root); + } + } + } +} + +void +ActiveElementManager::SetActiveTask(nsIDOMElement* aTarget) +{ + // This gets called from mSetActiveTask's Run() method. The message loop + // deletes the task right after running it, so we need to null out + // mSetActiveTask to make sure we're not left with a dangling pointer. + mSetActiveTask = nullptr; + SetActive(aTarget); +} + +void +ActiveElementManager::CancelTask() +{ + if (mSetActiveTask) { + mSetActiveTask->Cancel(); + mSetActiveTask = nullptr; + } +} + +} +} \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/widget/xpwidgets/ActiveElementManager.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __mozilla_widget_ActiveElementManager_h__ +#define __mozilla_widget_ActiveElementManager_h__ + +#include "nsCOMPtr.h" +#include "nsISupportsImpl.h" + +class inIDOMUtils; +class nsIDOMEventTarget; +class nsIDOMElement; +class CancelableTask; + +namespace mozilla { +namespace widget { + +/** + * Manages setting and clearing the ':active' CSS pseudostate in the presence + * of touch input. + */ +class ActiveElementManager { +public: + NS_INLINE_DECL_REFCOUNTING(ActiveElementManager) + + ActiveElementManager(); + ~ActiveElementManager(); + + /** + * Specify the target of a touch. Typically this should be called right + * before HandleTouchStart(), but we give callers the flexibility to specify + * the target later if they don't know it at the time they call + * HandleTouchStart(). + * |aTarget| may be nullptr. + */ + void SetTargetElement(nsIDOMEventTarget* aTarget); + /** + * Handle a touch-start event. + * @param aCanBePan whether the touch can be a pan + */ + void HandleTouchStart(bool aCanBePan); + /** + * Handle the start of panning. + */ + void HandlePanStart(); + /** + * Handle a touch-end or touch-cancel event. + * @param aWasClick whether the touch was a click + */ + void HandleTouchEnd(bool aWasClick); +private: + nsCOMPtr<inIDOMUtils> mDomUtils; + /** + * The target of the first touch point in the current touch block. + */ + nsCOMPtr<nsIDOMElement> mTarget; + /** + * Whether the current touch block can be a pan. Set in HandleTouchStart(). + */ + bool mCanBePan; + /** + * Whether mCanBePan has been set for the current touch block. + * We need to keep track of this to allow HandleTouchStart() and + * SetTargetElement() to be called in either order. + */ + bool mCanBePanSet; + /** + * A task for calling SetActive() after a timeout. + */ + CancelableTask* mSetActiveTask; + + // Helpers + void TriggerElementActivation(); + void SetActive(nsIDOMElement* aTarget); + void ResetActive(); + void SetActiveTask(nsIDOMElement* aTarget); + void CancelTask(); +}; + +} +} + +#endif /*__mozilla_widget_ActiveElementManager_h__ */
--- a/widget/xpwidgets/moz.build +++ b/widget/xpwidgets/moz.build @@ -1,23 +1,25 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. EXPORTS += [ + 'ActiveElementManager.h', 'APZCCallbackHelper.h', 'ContentHelper.h', 'GfxDriverInfo.h', 'GfxInfoBase.h', 'GfxInfoCollector.h', ] UNIFIED_SOURCES += [ + 'ActiveElementManager.cpp', 'APZCCallbackHelper.cpp', 'ContentHelper.cpp', 'GfxDriverInfo.cpp', 'GfxInfoBase.cpp', 'GfxInfoCollector.cpp', 'GfxInfoWebGL.cpp', 'InputData.cpp', 'nsBaseAppShell.cpp',
--- a/xpcom/build/ServiceList.h +++ b/xpcom/build/ServiceList.h @@ -9,16 +9,17 @@ MOZ_SERVICE(AccessibilityService, nsIAcc MOZ_SERVICE(ChromeRegistryService, nsIChromeRegistry, "@mozilla.org/chrome/chrome-registry;1") MOZ_SERVICE(ToolkitChromeRegistryService, nsIToolkitChromeRegistry, "@mozilla.org/chrome/chrome-registry;1") MOZ_SERVICE(XULChromeRegistryService, nsIXULChromeRegistry, "@mozilla.org/chrome/chrome-registry;1") MOZ_SERVICE(XULOverlayProviderService, nsIXULOverlayProvider, "@mozilla.org/chrome/chrome-registry;1") MOZ_SERVICE(IOService, nsIIOService, "@mozilla.org/network/io-service;1") MOZ_SERVICE(ObserverService, nsIObserverService, "@mozilla.org/observer-service;1") MOZ_SERVICE(StringBundleService, nsIStringBundleService, "@mozilla.org/intl/stringbundle;1") MOZ_SERVICE(XPConnect, nsIXPConnect, "@mozilla.org/js/xpc/XPConnect;1") +MOZ_SERVICE(InDOMUtils, inIDOMUtils, "@mozilla.org/inspector/dom-utils;1") #ifdef MOZ_USE_NAMESPACE namespace mozilla { #endif MOZ_SERVICE(HistoryService, IHistory, "@mozilla.org/browser/history;1")
--- a/xpcom/build/Services.cpp +++ b/xpcom/build/Services.cpp @@ -15,16 +15,17 @@ #include "nsNetCID.h" #include "nsObserverService.h" #include "nsXPCOMPrivate.h" #include "nsIStringBundle.h" #include "nsIToolkitChromeRegistry.h" #include "nsIXULOverlayProvider.h" #include "IHistory.h" #include "nsIXPConnect.h" +#include "inIDOMUtils.h" using namespace mozilla; using namespace mozilla::services; /* * Define a global variable and a getter for every service in ServiceList. * eg. gIOService and GetIOService() */
--- a/xpcom/ds/moz.build +++ b/xpcom/ds/moz.build @@ -48,18 +48,16 @@ EXPORTS += [ 'nsAtomService.h', 'nsCharSeparatedTokenizer.h', 'nsCheapSets.h', 'nsCRT.h', 'nsExpirationTracker.h', 'nsHashPropertyBag.h', 'nsHashtable.h', 'nsMathUtils.h', - 'nsObserverList.h', - 'nsObserverService.h', 'nsStaticAtom.h', 'nsStaticNameTable.h', 'nsStringEnumerator.h', 'nsSupportsArray.h', 'nsSupportsPrimitives.h', 'nsVariant.h', 'nsWhitespaceTokenizer.h', ]
--- a/xpcom/ds/nsObserverService.cpp +++ b/xpcom/ds/nsObserverService.cpp @@ -217,17 +217,17 @@ nsObserverService::Create(nsISupports* o NS_NewRunnableMethod(os, &nsObserverService::RegisterReporter); NS_DispatchToCurrentThread(registerRunnable); return os->QueryInterface(aIID, aInstancePtr); } #define NS_ENSURE_VALIDCALL \ if (!NS_IsMainThread()) { \ - NS_ERROR("Using observer service off the main thread!"); \ + MOZ_CRASH("Using observer service off the main thread!"); \ return NS_ERROR_UNEXPECTED; \ } \ if (mShuttingDown) { \ NS_ERROR("Using observer service after XPCOM shutdown!"); \ return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; \ } NS_IMETHODIMP
--- a/xpcom/ds/nsObserverService.h +++ b/xpcom/ds/nsObserverService.h @@ -22,17 +22,17 @@ class nsObserverService MOZ_FINAL : public nsIObserverService , public nsIMemoryReporter { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_OBSERVERSERVICE_CID) nsObserverService(); - NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVERSERVICE NS_DECL_NSIMEMORYREPORTER void Shutdown(); static nsresult Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
--- a/xpcom/threads/BackgroundHangMonitor.cpp +++ b/xpcom/threads/BackgroundHangMonitor.cpp @@ -23,17 +23,17 @@ #include <algorithm> namespace mozilla { /** * BackgroundHangManager is the global object that * manages all instances of BackgroundHangThread. */ -class BackgroundHangManager : public AtomicRefCounted<BackgroundHangManager> +class BackgroundHangManager { private: // Background hang monitor thread function static void MonitorThread(void* aData) { PR_SetCurrentThreadName("BgHangManager"); #ifdef MOZ_NUWA_PROCESS @@ -57,17 +57,17 @@ private: // Stop hang monitoring bool mShutdown; BackgroundHangManager(const BackgroundHangManager&); BackgroundHangManager& operator=(const BackgroundHangManager&); void RunMonitorThread(); public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(BackgroundHangManager) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BackgroundHangManager) static StaticRefPtr<BackgroundHangManager> sInstance; // Lock for access to members of this class Monitor mLock; // Current time as seen by hang monitors PRIntervalTime mIntervalNow; // List of BackgroundHangThread instances associated with each thread LinkedList<BackgroundHangThread> mHangThreads;