From 1c5959ee6e088e453dd0f14a683973e13b5985e4 Mon Sep 17 00:00:00 2001 From: Roy Tam Date: Sat, 23 Feb 2019 00:31:49 +0800 Subject: [PATCH] import changes from rmottola/Arctic-Fox: - Bug 1125750 - Check the overflow region direction to avoid unnecesary reflow for scrollable frame. (6b5067631) - Bug 1125750 - Add auto test to detect error when using mOuter to check overflow area of a scrollable frame. (4e9c43e31) - override -> MOZ_OVERRIDE (ed1ecc151) - Bug 990907 - Don't add text-overflow markers while being actively scrolled by APZ. (523bc5a3e) - Bug 945584: Part 6 - Implementation of scroll snapping (v10 Patch) (bf64eb0f3) - Bug 945584: Part 7 - Implement Scroll Snapping for Autoscroll, - Triggering scroll snapping at the end of an autoscroll. - This enables text selection to be unencumbered by scroll snapping, while restoring the scroll position to a valid snapping position when the drag operation is completed. (db9ce9811) - Bug 945584: Part 8 - Implement Scroll Snapping for Middle Mouse Button Scrolls (v2 Patch) (06d1b733d) - some MacOS 10.5 Leopard support (6a37f6745) - Bug 945584: Part 9 - Tests for scroll snapping (v4 Patch) (f67175387) - Bug 1102427 - Ensure scroll parents of an active scrollframe are layerized. (910d43ec5) - Bug 1142731 followup. Check isInterpreted() before we call environment(), because of the asmjs lambdas. (29b2acdc7) - Bug 1161627 - part 1 - add move constructor and assignment operator for already_AddRefed&& to RefPtr; This change is prep work for future mass rewriting. (98416d45c) - Bug 1161627 - part 2 - machine-convert TemporaryRef to already_AddRefed; (336e96af7) - Bug 1161627 - part 3 - remove TemporaryRef from RefPtr.h (6c3acdaed) - Bug 940273 - Part 3 - Service Worker Cache webidl. (4b6803d0a) - Bug 940273 - Part 4 - Initial implementation of Service Worker Cache. (74498c108) - Bug 1133861 - Bustage fix. (4a81437c2) --- dom/base/Element.cpp | 9 + dom/base/Element.h | 1 + dom/base/ImageEncoder.cpp | 10 +- dom/base/nsDOMWindowUtils.cpp | 2 +- dom/base/nsGlobalWindow.cpp | 10 + dom/base/nsGlobalWindow.h | 1 + dom/bindings/Bindings.conf | 8 + dom/bindings/Errors.msg | 1 + dom/cache/Action.cpp | 40 + dom/cache/Action.h | 88 + dom/cache/ActorChild.cpp | 53 + dom/cache/ActorChild.h | 47 + dom/cache/ActorUtils.h | 65 + dom/cache/AutoUtils.cpp | 438 ++++ dom/cache/AutoUtils.h | 176 ++ dom/cache/Cache.cpp | 586 ++++++ dom/cache/Cache.h | 133 ++ dom/cache/CacheChild.cpp | 187 ++ dom/cache/CacheChild.h | 75 + dom/cache/CacheInitData.ipdlh | 24 + dom/cache/CacheParent.cpp | 291 +++ dom/cache/CacheParent.h | 87 + dom/cache/CacheStorage.cpp | 631 ++++++ dom/cache/CacheStorage.h | 165 ++ dom/cache/CacheStorageChild.cpp | 174 ++ dom/cache/CacheStorageChild.h | 72 + dom/cache/CacheStorageParent.cpp | 450 ++++ dom/cache/CacheStorageParent.h | 108 + dom/cache/CacheStreamControlChild.cpp | 137 ++ dom/cache/CacheStreamControlChild.h | 53 + dom/cache/CacheStreamControlParent.cpp | 147 ++ dom/cache/CacheStreamControlParent.h | 57 + dom/cache/Context.cpp | 630 ++++++ dom/cache/Context.h | 109 + dom/cache/DBAction.cpp | 169 ++ dom/cache/DBAction.h | 77 + dom/cache/DBSchema.cpp | 1322 ++++++++++++ dom/cache/DBSchema.h | 141 ++ dom/cache/Feature.cpp | 108 + dom/cache/Feature.h | 54 + dom/cache/FetchPut.cpp | 451 ++++ dom/cache/FetchPut.h | 122 ++ dom/cache/FileUtils.cpp | 286 +++ dom/cache/FileUtils.h | 68 + dom/cache/IPCUtils.h | 22 + dom/cache/Manager.cpp | 1869 +++++++++++++++++ dom/cache/Manager.h | 285 +++ dom/cache/ManagerId.cpp | 91 + dom/cache/ManagerId.h | 81 + dom/cache/PCache.ipdl | 46 + dom/cache/PCacheStorage.ipdl | 44 + dom/cache/PCacheStreamControl.ipdl | 28 + dom/cache/PCacheTypes.ipdlh | 89 + dom/cache/PrincipalVerifier.cpp | 208 ++ dom/cache/PrincipalVerifier.h | 75 + dom/cache/QuotaClient.cpp | 214 ++ dom/cache/QuotaClient.h | 23 + dom/cache/ReadStream.cpp | 543 +++++ dom/cache/ReadStream.h | 102 + dom/cache/SavedTypes.h | 50 + dom/cache/StreamList.cpp | 160 ++ dom/cache/StreamList.h | 64 + dom/cache/StreamUtils.cpp | 151 ++ dom/cache/StreamUtils.h | 39 + dom/cache/TypeUtils.cpp | 481 +++++ dom/cache/TypeUtils.h | 123 ++ dom/cache/Types.h | 44 + dom/cache/moz.build | 83 + dom/canvas/CanvasRenderingContext2D.cpp | 8 +- dom/canvas/CanvasRenderingContext2D.h | 10 +- dom/canvas/WebGLContext.cpp | 2 +- dom/canvas/WebGLContext.h | 2 +- dom/canvas/WebGLContextLossHandler.cpp | 2 +- dom/canvas/WebGLProgram.cpp | 2 +- .../nsICanvasRenderingContextInternal.h | 2 +- dom/events/EventStateManager.cpp | 12 +- dom/fetch/FetchDriver.cpp | 8 + dom/fetch/FetchDriver.h | 7 +- dom/html/HTMLCanvasElement.cpp | 2 +- dom/html/HTMLCanvasElement.h | 2 +- ...BackgroundIDBVersionChangeTransaction.ipdl | 1 + dom/ipc/PBrowser.ipdl | 1 + dom/ipc/TabChild.cpp | 8 + dom/ipc/TabChild.h | 2 + dom/ipc/TabParent.cpp | 9 + dom/ipc/TabParent.h | 2 + dom/media/MediaTaskQueue.cpp | 10 +- dom/media/MediaTaskQueue.h | 15 +- dom/media/SharedThreadPool.cpp | 2 +- dom/media/SharedThreadPool.h | 2 +- dom/media/VideoUtils.cpp | 2 +- dom/media/VideoUtils.h | 2 +- dom/media/directshow/AudioSinkInputPin.cpp | 2 +- dom/media/directshow/AudioSinkInputPin.h | 2 +- dom/media/directshow/DirectShowUtils.cpp | 2 +- dom/media/platforms/wmf/MFTDecoder.cpp | 2 +- dom/media/platforms/wmf/MFTDecoder.h | 2 +- .../platforms/wmf/WMFAudioMFTManager.cpp | 2 +- dom/media/platforms/wmf/WMFAudioMFTManager.h | 2 +- dom/media/platforms/wmf/WMFMediaDataDecoder.h | 2 +- .../platforms/wmf/WMFVideoMFTManager.cpp | 2 +- dom/media/platforms/wmf/WMFVideoMFTManager.h | 2 +- dom/media/webaudio/PannerNode.cpp | 4 +- .../webaudio/blink/HRTFDatabaseLoader.cpp | 2 +- dom/media/webaudio/blink/HRTFDatabaseLoader.h | 2 +- dom/media/webaudio/blink/HRTFPanner.cpp | 2 +- dom/media/webaudio/blink/HRTFPanner.h | 2 +- dom/moz.build | 1 + dom/plugins/base/nsNPAPIPluginInstance.cpp | 2 +- dom/plugins/base/nsNPAPIPluginInstance.h | 2 +- dom/quota/Client.h | 9 + dom/quota/QuotaManager.cpp | 6 +- dom/svg/SVGCircleElement.cpp | 2 +- dom/svg/SVGCircleElement.h | 2 +- dom/svg/SVGContentUtils.cpp | 2 +- dom/svg/SVGContentUtils.h | 2 +- dom/svg/SVGEllipseElement.cpp | 2 +- dom/svg/SVGEllipseElement.h | 2 +- dom/svg/SVGImageElement.cpp | 2 +- dom/svg/SVGImageElement.h | 2 +- dom/svg/SVGLineElement.cpp | 2 +- dom/svg/SVGLineElement.h | 2 +- dom/svg/SVGMotionSMILPathUtils.cpp | 2 +- dom/svg/SVGMotionSMILPathUtils.h | 2 +- dom/svg/SVGPathData.cpp | 4 +- dom/svg/SVGPathData.h | 4 +- dom/svg/SVGPathElement.cpp | 4 +- dom/svg/SVGPathElement.h | 4 +- dom/svg/SVGPolygonElement.cpp | 2 +- dom/svg/SVGPolygonElement.h | 2 +- dom/svg/SVGPolylineElement.cpp | 2 +- dom/svg/SVGPolylineElement.h | 2 +- dom/svg/SVGRectElement.cpp | 2 +- dom/svg/SVGRectElement.h | 2 +- dom/svg/nsSVGPathGeometryElement.cpp | 4 +- dom/svg/nsSVGPathGeometryElement.h | 6 +- dom/system/gonk/MozMtpDatabase.cpp | 2 +- dom/system/gonk/MozMtpDatabase.h | 2 +- dom/system/gonk/VolumeManager.cpp | 6 +- dom/system/gonk/VolumeManager.h | 6 +- dom/webidl/Cache.webidl | 45 + dom/webidl/CacheStorage.webidl | 26 + dom/webidl/Element.webidl | 5 + dom/webidl/Window.webidl | 5 + dom/webidl/moz.build | 2 + gfx/2d/2D.h | 74 +- gfx/2d/DataSourceSurface.cpp | 2 +- gfx/2d/DataSurfaceHelpers.cpp | 2 +- gfx/2d/DataSurfaceHelpers.h | 2 +- gfx/2d/DrawTarget.cpp | 2 +- gfx/2d/DrawTargetCG.cpp | 14 +- gfx/2d/DrawTargetCG.h | 16 +- gfx/2d/DrawTargetCairo.cpp | 18 +- gfx/2d/DrawTargetCairo.h | 18 +- gfx/2d/DrawTargetCapture.cpp | 2 +- gfx/2d/DrawTargetCapture.h | 16 +- gfx/2d/DrawTargetD2D.cpp | 32 +- gfx/2d/DrawTargetD2D.h | 32 +- gfx/2d/DrawTargetD2D1.cpp | 26 +- gfx/2d/DrawTargetD2D1.h | 30 +- gfx/2d/DrawTargetDual.cpp | 2 +- gfx/2d/DrawTargetDual.h | 16 +- gfx/2d/DrawTargetRecording.cpp | 18 +- gfx/2d/DrawTargetRecording.h | 16 +- gfx/2d/DrawTargetSkia.cpp | 16 +- gfx/2d/DrawTargetSkia.h | 16 +- gfx/2d/DrawTargetTiled.cpp | 2 +- gfx/2d/DrawTargetTiled.h | 18 +- gfx/2d/Factory.cpp | 42 +- gfx/2d/FilterNodeD2D1.cpp | 4 +- gfx/2d/FilterNodeD2D1.h | 2 +- gfx/2d/FilterNodeSoftware.cpp | 56 +- gfx/2d/FilterNodeSoftware.h | 48 +- gfx/2d/FilterProcessing.cpp | 14 +- gfx/2d/FilterProcessing.h | 32 +- gfx/2d/FilterProcessingSIMD-inl.h | 12 +- gfx/2d/FilterProcessingSSE2.cpp | 10 +- gfx/2d/FilterProcessingScalar.cpp | 8 +- gfx/2d/HelpersD2D.h | 10 +- gfx/2d/MacIOSurface.cpp | 8 +- gfx/2d/MacIOSurface.h | 8 +- gfx/2d/PathCG.cpp | 10 +- gfx/2d/PathCG.h | 6 +- gfx/2d/PathCairo.cpp | 6 +- gfx/2d/PathCairo.h | 6 +- gfx/2d/PathD2D.cpp | 6 +- gfx/2d/PathD2D.h | 6 +- gfx/2d/PathHelpers.h | 6 +- gfx/2d/PathRecording.cpp | 6 +- gfx/2d/PathRecording.h | 6 +- gfx/2d/PathSkia.cpp | 6 +- gfx/2d/PathSkia.h | 6 +- gfx/2d/QuartzSupport.mm | 1 - gfx/2d/RadialGradientEffectD2D1.cpp | 2 +- gfx/2d/RadialGradientEffectD2D1.h | 2 +- gfx/2d/SVGTurbulenceRenderer-inl.h | 4 +- gfx/2d/ScaledFontBase.cpp | 2 +- gfx/2d/ScaledFontBase.h | 2 +- gfx/2d/ScaledFontDWrite.cpp | 2 +- gfx/2d/ScaledFontDWrite.h | 2 +- gfx/2d/ScaledFontMac.cpp | 2 +- gfx/2d/ScaledFontMac.h | 2 +- gfx/2d/SourceSurfaceCG.cpp | 2 +- gfx/2d/SourceSurfaceCG.h | 4 +- gfx/2d/SourceSurfaceCairo.cpp | 2 +- gfx/2d/SourceSurfaceCairo.h | 2 +- gfx/2d/SourceSurfaceD2D.cpp | 2 +- gfx/2d/SourceSurfaceD2D.h | 2 +- gfx/2d/SourceSurfaceD2D1.cpp | 2 +- gfx/2d/SourceSurfaceD2D1.h | 2 +- gfx/2d/SourceSurfaceD2DTarget.cpp | 2 +- gfx/2d/SourceSurfaceD2DTarget.h | 2 +- gfx/2d/SourceSurfaceDual.h | 2 +- gfx/gl/AndroidSurfaceTexture.cpp | 4 +- gfx/gl/AndroidSurfaceTexture.h | 4 +- gfx/gl/GLReadTexImageHelper.cpp | 6 +- gfx/gl/GLReadTexImageHelper.h | 4 +- gfx/gl/GLTextureImage.cpp | 2 +- gfx/gl/GLTextureImage.h | 2 +- gfx/gl/SharedSurface.cpp | 2 +- gfx/gl/SharedSurface.h | 2 +- gfx/layers/Compositor.h | 8 +- gfx/layers/D3D11ShareHandleImage.cpp | 2 +- gfx/layers/D3D11ShareHandleImage.h | 2 +- gfx/layers/D3D9SurfaceImage.cpp | 2 +- gfx/layers/D3D9SurfaceImage.h | 2 +- gfx/layers/Effects.h | 8 +- gfx/layers/GLImages.cpp | 2 +- gfx/layers/GLImages.h | 2 +- gfx/layers/GrallocImages.cpp | 2 +- gfx/layers/GrallocImages.h | 2 +- gfx/layers/IMFYCbCrImage.cpp | 2 +- gfx/layers/ImageContainer.cpp | 8 +- gfx/layers/ImageContainer.h | 12 +- gfx/layers/ImageDataSerializer.cpp | 4 +- gfx/layers/ImageDataSerializer.h | 6 +- gfx/layers/Layers.cpp | 6 +- gfx/layers/Layers.h | 8 +- gfx/layers/MacIOSurfaceImage.cpp | 2 +- gfx/layers/MacIOSurfaceImage.h | 2 +- gfx/layers/RotatedBuffer.cpp | 4 +- gfx/layers/RotatedBuffer.h | 8 +- gfx/layers/TextureDIB.cpp | 2 +- gfx/layers/TextureDIB.h | 4 +- gfx/layers/YCbCrImageDataSerializer.cpp | 2 +- gfx/layers/YCbCrImageDataSerializer.h | 4 +- .../apz/public/GoannaContentController.h | 8 + gfx/layers/apz/src/AsyncPanZoomController.cpp | 32 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 40 + gfx/layers/apz/util/APZCCallbackHelper.h | 8 + .../apz/util/ChromeProcessController.cpp | 7 + gfx/layers/apz/util/ChromeProcessController.h | 18 +- gfx/layers/basic/BasicCompositor.cpp | 6 +- gfx/layers/basic/BasicCompositor.h | 6 +- gfx/layers/basic/BasicImageLayer.cpp | 4 +- gfx/layers/basic/BasicImages.cpp | 4 +- gfx/layers/basic/BasicImplData.h | 2 +- .../basic/MacIOSurfaceTextureHostBasic.h | 2 +- gfx/layers/basic/TextureClientX11.cpp | 2 +- gfx/layers/basic/TextureClientX11.h | 2 +- gfx/layers/basic/TextureHostBasic.cpp | 2 +- gfx/layers/basic/X11BasicCompositor.cpp | 2 +- gfx/layers/basic/X11BasicCompositor.h | 2 +- gfx/layers/client/CanvasClient.cpp | 16 +- gfx/layers/client/CanvasClient.h | 6 +- gfx/layers/client/CompositableClient.cpp | 4 +- gfx/layers/client/CompositableClient.h | 6 +- gfx/layers/client/ContentClient.cpp | 4 +- gfx/layers/client/ContentClient.h | 6 +- gfx/layers/client/ImageClient.cpp | 6 +- gfx/layers/client/ImageClient.h | 8 +- gfx/layers/client/TextureClient.cpp | 14 +- gfx/layers/client/TextureClient.h | 18 +- gfx/layers/client/TextureClientPool.cpp | 2 +- gfx/layers/client/TextureClientPool.h | 2 +- .../client/TextureClientRecycleAllocator.cpp | 6 +- .../client/TextureClientRecycleAllocator.h | 2 +- gfx/layers/composite/CompositableHost.cpp | 2 +- gfx/layers/composite/CompositableHost.h | 6 +- gfx/layers/composite/ContentHost.cpp | 6 +- gfx/layers/composite/ContentHost.h | 6 +- gfx/layers/composite/FPSCounter.h | 2 +- gfx/layers/composite/ImageHost.cpp | 4 +- gfx/layers/composite/ImageHost.h | 4 +- .../composite/LayerManagerComposite.cpp | 6 +- gfx/layers/composite/LayerManagerComposite.h | 6 +- gfx/layers/composite/TextureHost.cpp | 14 +- gfx/layers/composite/TextureHost.h | 18 +- gfx/layers/composite/X11TextureHost.h | 2 +- gfx/layers/d3d11/CompositorD3D11.cpp | 6 +- gfx/layers/d3d11/CompositorD3D11.h | 6 +- gfx/layers/d3d11/TextureD3D11.cpp | 8 +- gfx/layers/d3d11/TextureD3D11.h | 14 +- gfx/layers/d3d9/CompositorD3D9.cpp | 6 +- gfx/layers/d3d9/CompositorD3D9.h | 6 +- gfx/layers/d3d9/DeviceManagerD3D9.cpp | 2 +- gfx/layers/d3d9/DeviceManagerD3D9.h | 2 +- gfx/layers/d3d9/TextureD3D9.cpp | 14 +- gfx/layers/d3d9/TextureD3D9.h | 20 +- gfx/layers/ipc/CompositorBench.cpp | 12 +- gfx/layers/ipc/ISurfaceAllocator.cpp | 4 +- gfx/layers/ipc/ISurfaceAllocator.h | 4 +- gfx/layers/ipc/ImageBridgeChild.cpp | 4 +- gfx/layers/ipc/ImageBridgeChild.h | 6 +- gfx/layers/ipc/SharedPlanarYCbCrImage.cpp | 2 +- gfx/layers/ipc/SharedPlanarYCbCrImage.h | 2 +- gfx/layers/ipc/SharedRGBImage.cpp | 2 +- gfx/layers/ipc/SharedRGBImage.h | 2 +- .../opengl/CompositingRenderTargetOGL.cpp | 2 +- .../opengl/CompositingRenderTargetOGL.h | 6 +- gfx/layers/opengl/CompositorOGL.cpp | 6 +- gfx/layers/opengl/CompositorOGL.h | 8 +- gfx/layers/opengl/GrallocTextureClient.cpp | 4 +- gfx/layers/opengl/GrallocTextureClient.h | 4 +- gfx/layers/opengl/GrallocTextureHost.cpp | 2 +- gfx/layers/opengl/GrallocTextureHost.h | 2 +- .../opengl/MacIOSurfaceTextureClientOGL.cpp | 4 +- .../opengl/MacIOSurfaceTextureClientOGL.h | 6 +- .../opengl/MacIOSurfaceTextureHostOGL.h | 2 +- gfx/layers/opengl/TextureClientOGL.h | 4 +- gfx/layers/opengl/TextureHostOGL.cpp | 2 +- gfx/layers/opengl/TextureHostOGL.h | 4 +- gfx/src/FilterSupport.cpp | 32 +- .../gtest/TestAsyncPanZoomController.cpp | 1 + gfx/tests/gtest/TestCompositor.cpp | 4 +- gfx/thebes/gfxAndroidPlatform.cpp | 2 +- gfx/thebes/gfxAndroidPlatform.h | 2 +- gfx/thebes/gfxBlur.cpp | 2 +- gfx/thebes/gfxBlur.h | 2 +- gfx/thebes/gfxContext.cpp | 4 +- gfx/thebes/gfxContext.h | 4 +- gfx/thebes/gfxDWriteFonts.cpp | 4 +- gfx/thebes/gfxDWriteFonts.h | 4 +- gfx/thebes/gfxFT2Fonts.cpp | 2 +- gfx/thebes/gfxFT2Fonts.h | 2 +- gfx/thebes/gfxFont.h | 4 +- gfx/thebes/gfxImageSurface.cpp | 2 +- gfx/thebes/gfxImageSurface.h | 2 +- gfx/thebes/gfxMacFont.cpp | 4 +- gfx/thebes/gfxMacFont.h | 4 +- gfx/thebes/gfxPangoFonts.cpp | 4 +- gfx/thebes/gfxPlatform.cpp | 20 +- gfx/thebes/gfxPlatform.h | 20 +- gfx/thebes/gfxPlatformGtk.cpp | 2 +- gfx/thebes/gfxPlatformGtk.h | 2 +- gfx/thebes/gfxPlatformMac.cpp | 2 +- gfx/thebes/gfxPlatformMac.h | 2 +- gfx/thebes/gfxQtPlatform.cpp | 2 +- gfx/thebes/gfxQtPlatform.h | 2 +- gfx/thebes/gfxUtils.cpp | 8 +- gfx/thebes/gfxUtils.h | 6 +- gfx/thebes/gfxWindowsPlatform.cpp | 4 +- gfx/thebes/gfxWindowsPlatform.h | 4 +- image/ClippedImage.cpp | 8 +- image/ClippedImage.h | 4 +- image/DynamicImage.cpp | 2 +- image/FrozenImage.cpp | 2 +- image/FrozenImage.h | 2 +- image/ImageWrapper.cpp | 2 +- image/OrientedImage.cpp | 2 +- image/OrientedImage.h | 2 +- image/RasterImage.cpp | 6 +- image/RasterImage.h | 4 +- image/VectorImage.cpp | 2 +- image/imgFrame.cpp | 10 +- image/imgFrame.h | 6 +- image/imgIContainer.idl | 2 +- ipc/glue/BackgroundChildImpl.cpp | 50 + ipc/glue/BackgroundChildImpl.h | 18 + ipc/glue/BackgroundParentImpl.cpp | 46 + ipc/glue/BackgroundParentImpl.h | 18 + ipc/glue/PBackground.ipdl | 15 + js/src/jsobjinlines.h | 4 +- layout/base/DisplayItemClip.cpp | 2 +- layout/base/DisplayItemClip.h | 2 +- layout/base/nsCSSRenderingBorders.cpp | 4 +- layout/base/nsCSSRenderingBorders.h | 4 +- layout/base/nsDisplayList.cpp | 3 +- layout/base/nsDisplayList.h | 36 +- layout/base/nsIPresShell.h | 4 +- layout/base/nsPresShell.cpp | 18 +- layout/base/nsPresShell.h | 6 +- layout/base/tests/mochitest.ini | 2 + layout/base/tests/test_scroll_snapping.html | 785 +++++++ layout/generic/TextOverflow.cpp | 17 +- layout/generic/TextOverflow.h | 4 + layout/generic/nsFrame.cpp | 9 + layout/generic/nsGfxScrollFrame.cpp | 491 ++++- layout/generic/nsGfxScrollFrame.h | 180 +- layout/generic/nsIScrollableFrame.h | 32 +- layout/ipc/RenderFrameParent.cpp | 18 + layout/reftests/scrolling/move-item-ref.html | 27 + layout/reftests/scrolling/move-item.html | 31 + layout/reftests/scrolling/reftest.list | 1 + layout/svg/SVGTextFrame.cpp | 2 +- layout/svg/SVGTextFrame.h | 2 +- layout/svg/nsSVGMaskFrame.cpp | 2 +- layout/svg/nsSVGMaskFrame.h | 2 +- layout/svg/nsSVGPatternFrame.cpp | 2 +- layout/svg/nsSVGPatternFrame.h | 2 +- media/mtransport/dtlsidentity.cpp | 2 +- media/mtransport/dtlsidentity.h | 2 +- .../peerconnection/PeerConnectionMedia.cpp | 2 +- .../src/peerconnection/PeerConnectionMedia.h | 2 +- mfbt/RefPtr.h | 66 +- mfbt/tests/TestRefPtr.cpp | 13 +- mozglue/linker/BaseElf.cpp | 2 +- mozglue/linker/BaseElf.h | 2 +- mozglue/linker/CustomElf.cpp | 2 +- mozglue/linker/CustomElf.h | 2 +- mozglue/linker/ElfLoader.cpp | 6 +- mozglue/linker/ElfLoader.h | 6 +- mozglue/linker/Zip.cpp | 6 +- mozglue/linker/Zip.h | 8 +- security/manager/ssl/src/nsCertTree.cpp | 2 +- security/manager/ssl/src/nsCertTree.h | 2 +- security/manager/ssl/src/nsNSSComponent.cpp | 4 +- security/manager/ssl/src/nsNSSComponent.h | 6 +- toolkit/content/browser-content.js | 1 + widget/android/APZCCallbackHandler.cpp | 7 + widget/android/APZCCallbackHandler.h | 2 + widget/cocoa/nsChildView.h | 2 +- widget/cocoa/nsChildView.mm | 6 +- widget/cocoa/nsCocoaWindow.mm | 4 + widget/cocoa/nsColorPicker.mm | 5 + widget/cocoa/nsMenuBarX.mm | 5 +- .../gonk/nativewindow/GonkBufferQueueJB.cpp | 2 +- widget/gonk/nativewindow/GonkBufferQueueJB.h | 2 +- .../gonk/nativewindow/GonkBufferQueueKK.cpp | 2 +- widget/gonk/nativewindow/GonkBufferQueueKK.h | 2 +- .../GonkBufferQueueConsumer.cpp | 2 +- .../GonkBufferQueueConsumer.h | 2 +- .../gonk/nativewindow/GonkNativeWindowICS.cpp | 4 +- .../gonk/nativewindow/GonkNativeWindowICS.h | 4 +- .../gonk/nativewindow/GonkNativeWindowJB.cpp | 4 +- widget/gonk/nativewindow/GonkNativeWindowJB.h | 4 +- .../gonk/nativewindow/GonkNativeWindowKK.cpp | 4 +- widget/gonk/nativewindow/GonkNativeWindowKK.h | 4 +- .../gonk/nativewindow/GonkNativeWindowLL.cpp | 4 +- widget/gonk/nativewindow/GonkNativeWindowLL.h | 4 +- .../IGonkGraphicBufferConsumerLL.cpp | 2 +- .../IGonkGraphicBufferConsumerLL.h | 2 +- widget/gonk/nsWindow.cpp | 2 +- widget/gonk/nsWindow.h | 2 +- widget/gtk/nsWindow.cpp | 2 +- widget/gtk/nsWindow.h | 2 +- widget/nsBaseWidget.cpp | 2 +- widget/nsBaseWidget.h | 2 +- widget/nsIWidget.h | 2 +- widget/qt/nsWindow.cpp | 2 +- widget/qt/nsWindow.h | 2 +- widget/windows/nsWindow.cpp | 2 +- widget/windows/nsWindow.h | 2 +- 453 files changed, 15688 insertions(+), 1099 deletions(-) create mode 100644 dom/cache/Action.cpp create mode 100644 dom/cache/Action.h create mode 100644 dom/cache/ActorChild.cpp create mode 100644 dom/cache/ActorChild.h create mode 100644 dom/cache/ActorUtils.h create mode 100644 dom/cache/AutoUtils.cpp create mode 100644 dom/cache/AutoUtils.h create mode 100644 dom/cache/Cache.cpp create mode 100644 dom/cache/Cache.h create mode 100644 dom/cache/CacheChild.cpp create mode 100644 dom/cache/CacheChild.h create mode 100644 dom/cache/CacheInitData.ipdlh create mode 100644 dom/cache/CacheParent.cpp create mode 100644 dom/cache/CacheParent.h create mode 100644 dom/cache/CacheStorage.cpp create mode 100644 dom/cache/CacheStorage.h create mode 100644 dom/cache/CacheStorageChild.cpp create mode 100644 dom/cache/CacheStorageChild.h create mode 100644 dom/cache/CacheStorageParent.cpp create mode 100644 dom/cache/CacheStorageParent.h create mode 100644 dom/cache/CacheStreamControlChild.cpp create mode 100644 dom/cache/CacheStreamControlChild.h create mode 100644 dom/cache/CacheStreamControlParent.cpp create mode 100644 dom/cache/CacheStreamControlParent.h create mode 100644 dom/cache/Context.cpp create mode 100644 dom/cache/Context.h create mode 100644 dom/cache/DBAction.cpp create mode 100644 dom/cache/DBAction.h create mode 100644 dom/cache/DBSchema.cpp create mode 100644 dom/cache/DBSchema.h create mode 100644 dom/cache/Feature.cpp create mode 100644 dom/cache/Feature.h create mode 100644 dom/cache/FetchPut.cpp create mode 100644 dom/cache/FetchPut.h create mode 100644 dom/cache/FileUtils.cpp create mode 100644 dom/cache/FileUtils.h create mode 100644 dom/cache/IPCUtils.h create mode 100644 dom/cache/Manager.cpp create mode 100644 dom/cache/Manager.h create mode 100644 dom/cache/ManagerId.cpp create mode 100644 dom/cache/ManagerId.h create mode 100644 dom/cache/PCache.ipdl create mode 100644 dom/cache/PCacheStorage.ipdl create mode 100644 dom/cache/PCacheStreamControl.ipdl create mode 100644 dom/cache/PCacheTypes.ipdlh create mode 100644 dom/cache/PrincipalVerifier.cpp create mode 100644 dom/cache/PrincipalVerifier.h create mode 100644 dom/cache/QuotaClient.cpp create mode 100644 dom/cache/QuotaClient.h create mode 100644 dom/cache/ReadStream.cpp create mode 100644 dom/cache/ReadStream.h create mode 100644 dom/cache/SavedTypes.h create mode 100644 dom/cache/StreamList.cpp create mode 100644 dom/cache/StreamList.h create mode 100644 dom/cache/StreamUtils.cpp create mode 100644 dom/cache/StreamUtils.h create mode 100644 dom/cache/TypeUtils.cpp create mode 100644 dom/cache/TypeUtils.h create mode 100644 dom/cache/Types.h create mode 100644 dom/cache/moz.build create mode 100644 dom/webidl/Cache.webidl create mode 100644 dom/webidl/CacheStorage.webidl create mode 100644 layout/base/tests/test_scroll_snapping.html create mode 100644 layout/reftests/scrolling/move-item-ref.html create mode 100644 layout/reftests/scrolling/move-item.html diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index de338e9e67..5c5a398946 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -803,6 +803,15 @@ Element::ScrollByNoFlush(int32_t aDx, int32_t aDy) return (before != after); } +void +Element::MozScrollSnap() +{ + nsIScrollableFrame* sf = GetScrollFrame(nullptr, false); + if (sf) { + sf->ScrollSnap(); + } +} + static nsSize GetScrollRectSizeForOverflowVisibleFrame(nsIFrame* aFrame) { if (!aFrame) { diff --git a/dom/base/Element.h b/dom/base/Element.h index f639bf9122..dd391d0390 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -792,6 +792,7 @@ public: void SetScrollLeft(int32_t aScrollLeft); int32_t ScrollWidth(); int32_t ScrollHeight(); + void MozScrollSnap(); int32_t ClientTop() { return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y); diff --git a/dom/base/ImageEncoder.cpp b/dom/base/ImageEncoder.cpp index 410763c173..f61354e98a 100644 --- a/dom/base/ImageEncoder.cpp +++ b/dom/base/ImageEncoder.cpp @@ -21,7 +21,7 @@ namespace dom { // template parameter, we need to move this class outside. class SurfaceHelper : public nsRunnable { public: - explicit SurfaceHelper(TemporaryRef aImage) : mImage(aImage) {} + explicit SurfaceHelper(already_AddRefed aImage) : mImage(aImage) {} // It retrieves a SourceSurface reference and convert color format on main // thread and passes DataSourceSurface to caller thread. @@ -40,7 +40,7 @@ public: return NS_OK; } - TemporaryRef GetDataSurfaceSafe() { + already_AddRefed GetDataSurfaceSafe() { nsCOMPtr mainThread = do_GetMainThread(); MOZ_ASSERT(mainThread); SyncRunnable::DispatchToThread(mainThread, this, false); @@ -58,10 +58,10 @@ private: // image formats should be referenced or dereferenced on main thread, it uses a // sync class SurfaceHelper to retrieve SourceSurface and convert to B8G8R8A8 on // main thread. -TemporaryRef -GetBRGADataSourceSurfaceSync(TemporaryRef aImage) +already_AddRefed +GetBRGADataSourceSurfaceSync(already_AddRefed aImage) { - nsRefPtr helper = new SurfaceHelper(aImage); + nsRefPtr helper = new SurfaceHelper(Move(aImage)); return helper->GetDataSurfaceSafe(); } diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 6f73863e34..7ffe8ed1b2 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1712,7 +1712,7 @@ nsDOMWindowUtils::GetTranslationNodes(nsIDOMNode* aRoot, return NS_OK; } -static TemporaryRef +static already_AddRefed CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas) { nsCOMPtr node = do_QueryInterface(aCanvas); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 856447adde..a910587538 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -7387,6 +7387,16 @@ nsGlobalWindow::ScrollByPages(int32_t numPages, } } +void +nsGlobalWindow::MozScrollSnap() +{ + FlushPendingNotifications(Flush_Layout); + nsIScrollableFrame *sf = GetScrollFrame(); + if (sf) { + sf->ScrollSnap(); + } +} + void nsGlobalWindow::MozRequestOverfill(OverfillCallback& aCallback, mozilla::ErrorResult& aError) diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 619d6e6ec3..cc8f7b65f7 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -946,6 +946,7 @@ public: const mozilla::dom::ScrollOptions& aOptions); void ScrollByPages(int32_t numPages, const mozilla::dom::ScrollOptions& aOptions); + void MozScrollSnap(); int32_t GetInnerWidth(mozilla::ErrorResult& aError); void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError); int32_t GetInnerHeight(mozilla::ErrorResult& aError); diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 4c27042a35..f043420dde 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -176,6 +176,14 @@ DOMInterfaces = { 'resultNotAddRefed': ['element'], }, +'Cache': { + 'nativeType': 'mozilla::dom::cache::Cache', +}, + +'CacheStorage': { + 'nativeType': 'mozilla::dom::cache::CacheStorage', +}, + 'CameraCapabilities': { 'nativeType': 'mozilla::dom::CameraCapabilities', 'headerFile': 'DOMCameraCapabilities.h' diff --git a/dom/bindings/Errors.msg b/dom/bindings/Errors.msg index 44428ff5e1..bdf0318e30 100644 --- a/dom/bindings/Errors.msg +++ b/dom/bindings/Errors.msg @@ -71,4 +71,5 @@ MSG_DEF(MSG_INVALID_ZOOMANDPAN_VALUE_ERROR, 0, JSEXN_RANGEERR, "Invalid zoom and MSG_DEF(MSG_INVALID_TRANSFORM_ANGLE_ERROR, 0, JSEXN_RANGEERR, "Invalid transform angle.") MSG_DEF(MSG_INVALID_RESPONSE_STATUSCODE_ERROR, 0, JSEXN_RANGEERR, "Invalid response status code.") MSG_DEF(MSG_INVALID_REDIRECT_STATUSCODE_ERROR, 0, JSEXN_RANGEERR, "Invalid redirect status code.") +MSG_DEF(MSG_INVALID_URL_SCHEME, 2, JSEXN_TYPEERR, "{0} URL {1} must be either http:// or https://.") MSG_DEF(MSG_RESPONSE_URL_IS_NULL, 0, JSEXN_TYPEERR, "Cannot set Response.finalURL when Response.url is null.") diff --git a/dom/cache/Action.cpp b/dom/cache/Action.cpp new file mode 100644 index 0000000000..6315b58e84 --- /dev/null +++ b/dom/cache/Action.cpp @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/Action.h" + +namespace mozilla { +namespace dom { +namespace cache { + +NS_IMPL_ISUPPORTS0(mozilla::dom::cache::Action::Resolver); + +void +Action::CancelOnInitiatingThread() +{ + NS_ASSERT_OWNINGTHREAD(Action); + MOZ_ASSERT(!mCanceled); + mCanceled = true; +} + +Action::Action() + : mCanceled(false) +{ +} + +Action::~Action() +{ +} + +bool +Action::IsCanceled() const +{ + return mCanceled; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/Action.h b/dom/cache/Action.h new file mode 100644 index 0000000000..d8c916e941 --- /dev/null +++ b/dom/cache/Action.h @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_Action_h +#define mozilla_dom_cache_Action_h + +#include "mozilla/Atomics.h" +#include "mozilla/dom/cache/Types.h" +#include "nsISupportsImpl.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class Action +{ +public: + class Resolver : public nsISupports + { + protected: + // virtual because deleted through base class pointer + virtual ~Resolver() { } + + public: + // Note: Action must drop Resolver ref after calling Resolve()! + // Note: Must be called on the same thread used to execute + // Action::RunOnTarget(). + virtual void Resolve(nsresult aRv) = 0; + + // We must use ISUPPORTS for our refcounting here because sub-classes also + // want to inherit interfaces like nsIRunnable. + NS_DECL_THREADSAFE_ISUPPORTS + }; + + // Execute operations on the target thread. Once complete call + // Resolver::Resolve(). This can be done sync or async. + // Note: Action should hold Resolver ref until its ready to call Resolve(). + // Note: The "target" thread is determined when the Action is scheduled on + // Context. The Action should not assume any particular thread is used. + virtual void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo) = 0; + + // Called on initiating thread when the Action is canceled. The Action is + // responsible for calling Resolver::Resolve() as normal; either with a + // normal error code or NS_ERROR_ABORT. If CancelOnInitiatingThread() is + // called after Resolve() has already occurred, then the cancel can be + // ignored. + // + // Cancellation is a best effort to stop processing as soon as possible, but + // does not guarantee the Action will not run. + // + // Default implementation sets an internal cancellation flag that can be + // queried with IsCanceled(). + virtual void CancelOnInitiatingThread(); + + // Executed on the initiating thread and is passed the nsresult given to + // Resolver::Resolve(). + virtual void CompleteOnInitiatingThread(nsresult aRv) { } + + // Executed on the initiating thread. If this Action will operate on the + // given cache ID then override this to return true. + virtual bool MatchesCacheId(CacheId aCacheId) const { return false; } + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(cache::Action) + NS_DECL_OWNINGTHREAD + +protected: + Action(); + + // virtual because deleted through base class pointer + virtual ~Action(); + + // Check if this Action has been canceled. May be called from any thread, + // but typically used from the target thread. + bool IsCanceled() const; + +private: + // Accessible from any thread. + Atomic mCanceled; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_Action_h diff --git a/dom/cache/ActorChild.cpp b/dom/cache/ActorChild.cpp new file mode 100644 index 0000000000..581073f3f8 --- /dev/null +++ b/dom/cache/ActorChild.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/ActorChild.h" + +#include "mozilla/dom/cache/Feature.h" + +namespace mozilla { +namespace dom { +namespace cache { + +void +ActorChild::SetFeature(Feature* aFeature) +{ + MOZ_ASSERT(!mFeature); + mFeature = aFeature; + if (mFeature) { + mFeature->AddActor(this); + } +} + +void +ActorChild::RemoveFeature() +{ + if (mFeature) { + mFeature->RemoveActor(this); + mFeature = nullptr; + } +} + +Feature* +ActorChild::GetFeature() const +{ + return mFeature; +} + +bool +ActorChild::FeatureNotified() const +{ + return mFeature && mFeature->Notified(); +} + +ActorChild::~ActorChild() +{ + MOZ_ASSERT(!mFeature); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/ActorChild.h b/dom/cache/ActorChild.h new file mode 100644 index 0000000000..eeb9c9a629 --- /dev/null +++ b/dom/cache/ActorChild.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_ActioChild_h +#define mozilla_dom_cache_ActioChild_h + +#include "mozilla/nsRefPtr.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class Feature; + +class ActorChild +{ +public: + virtual void + StartDestroy() = 0; + + void + SetFeature(Feature* aFeature); + + void + RemoveFeature(); + + Feature* + GetFeature() const; + + bool + FeatureNotified() const; + +protected: + ~ActorChild(); + +private: + nsRefPtr mFeature; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_ActioChild_h diff --git a/dom/cache/ActorUtils.h b/dom/cache/ActorUtils.h new file mode 100644 index 0000000000..d0acba222e --- /dev/null +++ b/dom/cache/ActorUtils.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_ActorUtils_h +#define mozilla_dom_cache_ActorUtils_h + +#include "mozilla/dom/cache/Types.h" + +namespace mozilla { + +namespace ipc { +class PBackgroundParent; +class PrincipalInfo; +} + +namespace dom { +namespace cache { + +class PCacheChild; +class PCacheParent; +class PCacheStreamControlChild; +class PCacheStreamControlParent; +class PCacheStorageChild; +class PCacheStorageParent; + +// Factory methods for use in ipc/glue methods. Implemented in individual actor +// cpp files. + +PCacheChild* +AllocPCacheChild(); + +void +DeallocPCacheChild(PCacheChild* aActor); + +void +DeallocPCacheParent(PCacheParent* aActor); + +PCacheStreamControlChild* +AllocPCacheStreamControlChild(); + +void +DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor); + +void +DeallocPCacheStreamControlParent(PCacheStreamControlParent* aActor); + +PCacheStorageParent* +AllocPCacheStorageParent(mozilla::ipc::PBackgroundParent* aManagingActor, + Namespace aNamespace, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo); + +void +DeallocPCacheStorageChild(PCacheStorageChild* aActor); + +void +DeallocPCacheStorageParent(PCacheStorageParent* aActor); + +} // namesapce cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_ActorUtils_h diff --git a/dom/cache/AutoUtils.cpp b/dom/cache/AutoUtils.cpp new file mode 100644 index 0000000000..be36beb96d --- /dev/null +++ b/dom/cache/AutoUtils.cpp @@ -0,0 +1,438 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/AutoUtils.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/cache/CacheStreamControlParent.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/dom/cache/SavedTypes.h" +#include "mozilla/dom/cache/StreamList.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "mozilla/ipc/FileDescriptorSetChild.h" +#include "mozilla/ipc/FileDescriptorSetParent.h" +#include "mozilla/ipc/PBackgroundParent.h" + +namespace { + +using mozilla::unused; +using mozilla::dom::cache::PCacheReadStream; +using mozilla::dom::cache::PCacheReadStreamOrVoid; +using mozilla::ipc::FileDescriptor; +using mozilla::ipc::FileDescriptorSetChild; +using mozilla::ipc::FileDescriptorSetParent; +using mozilla::ipc::OptionalFileDescriptorSet; + +enum CleanupAction +{ + ForgetFds, + DeleteFds +}; + +void +CleanupChildFds(PCacheReadStream& aReadStream, CleanupAction aAction) +{ + if (aReadStream.fds().type() != + OptionalFileDescriptorSet::TPFileDescriptorSetChild) { + return; + } + + nsAutoTArray fds; + + FileDescriptorSetChild* fdSetActor = + static_cast(aReadStream.fds().get_PFileDescriptorSetChild()); + MOZ_ASSERT(fdSetActor); + + if (aAction == DeleteFds) { + unused << fdSetActor->Send__delete__(fdSetActor); + } + + // FileDescriptorSet doesn't clear its fds in its ActorDestroy, so we + // unconditionally forget them here. The fds themselves are auto-closed in + // ~FileDescriptor since they originated in this process. + fdSetActor->ForgetFileDescriptors(fds); +} + +void +CleanupChildFds(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction) +{ + if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) { + return; + } + + CleanupChildFds(aReadStreamOrVoid.get_PCacheReadStream(), aAction); +} + +void +CleanupParentFds(PCacheReadStream& aReadStream, CleanupAction aAction) +{ + if (aReadStream.fds().type() != + OptionalFileDescriptorSet::TPFileDescriptorSetParent) { + return; + } + + nsAutoTArray fds; + + FileDescriptorSetParent* fdSetActor = + static_cast(aReadStream.fds().get_PFileDescriptorSetParent()); + MOZ_ASSERT(fdSetActor); + + if (aAction == DeleteFds) { + unused << fdSetActor->Send__delete__(fdSetActor); + } + + // FileDescriptorSet doesn't clear its fds in its ActorDestroy, so we + // unconditionally forget them here. The fds themselves are auto-closed in + // ~FileDescriptor since they originated in this process. + fdSetActor->ForgetFileDescriptors(fds); +} + +void +CleanupParentFds(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction) +{ + if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) { + return; + } + + CleanupParentFds(aReadStreamOrVoid.get_PCacheReadStream(), aAction); +} + +} // anonymous namespace + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::ipc::PBackgroundParent; + +AutoChildBase::AutoChildBase(TypeUtils* aTypeUtils) + : mTypeUtils(aTypeUtils) + , mSent(false) +{ + MOZ_ASSERT(mTypeUtils); +} + +AutoChildBase::~AutoChildBase() +{ +} + +// -------------------------------------------- + +AutoChildRequest::AutoChildRequest(TypeUtils* aTypeUtils) + : AutoChildBase(aTypeUtils) +{ + mRequestOrVoid = void_t(); +} + +AutoChildRequest::~AutoChildRequest() +{ + if (mRequestOrVoid.type() != PCacheRequestOrVoid::TPCacheRequest) { + return; + } + + CleanupAction action = mSent ? ForgetFds : DeleteFds; + CleanupChildFds(mRequestOrVoid.get_PCacheRequest().body(), action); +} + +void +AutoChildRequest::Add(InternalRequest* aRequest, BodyAction aBodyAction, + ReferrerAction aReferrerAction, SchemeAction aSchemeAction, + ErrorResult& aRv) +{ + MOZ_ASSERT(!mSent); + MOZ_ASSERT(mRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t); + mRequestOrVoid = PCacheRequest(); + mTypeUtils->ToPCacheRequest(mRequestOrVoid.get_PCacheRequest(), aRequest, + aBodyAction, aReferrerAction, aSchemeAction, aRv); +} + +const PCacheRequest& +AutoChildRequest::SendAsRequest() +{ + MOZ_ASSERT(mRequestOrVoid.type() == PCacheRequestOrVoid::TPCacheRequest); + return mRequestOrVoid.get_PCacheRequest(); +} + +const PCacheRequestOrVoid& +AutoChildRequest::SendAsRequestOrVoid() +{ + return mRequestOrVoid; +} + +// -------------------------------------------- + +AutoChildRequestList::AutoChildRequestList(TypeUtils* aTypeUtils, + uint32_t aCapacity) + : AutoChildBase(aTypeUtils) +{ + mRequestList.SetCapacity(aCapacity); +} + +AutoChildRequestList::~AutoChildRequestList() +{ + CleanupAction action = mSent ? ForgetFds : DeleteFds; + for (uint32_t i = 0; i < mRequestList.Length(); ++i) { + CleanupChildFds(mRequestList[i].body(), action); + } +} + +void +AutoChildRequestList::Add(InternalRequest* aRequest, BodyAction aBodyAction, + ReferrerAction aReferrerAction, + SchemeAction aSchemeAction, ErrorResult& aRv) +{ + MOZ_ASSERT(!mSent); + + // The FileDescriptorSetChild asserts in its destructor that all fds have + // been removed. The copy constructor, however, simply duplicates the + // fds without removing any. This means each temporary and copy must be + // explicitly cleaned up. + // + // Avoid a lot of this hassle by making sure we only create one here. On + // error we remove it. + + PCacheRequest* request = mRequestList.AppendElement(); + mTypeUtils->ToPCacheRequest(*request, aRequest, aBodyAction, aReferrerAction, + aSchemeAction, aRv); + if (aRv.Failed()) { + mRequestList.RemoveElementAt(mRequestList.Length() - 1); + } +} + +const nsTArray& +AutoChildRequestList::SendAsRequestList() +{ + MOZ_ASSERT(!mSent); + mSent = true; + return mRequestList; +} + +// -------------------------------------------- + +AutoChildRequestResponse::AutoChildRequestResponse(TypeUtils* aTypeUtils) + : AutoChildBase(aTypeUtils) +{ + // Default IPC-generated constructor does not initialize these correctly + // and we check them later when cleaning up. + mRequestResponse.request().body() = void_t(); + mRequestResponse.response().body() = void_t(); +} + +AutoChildRequestResponse::~AutoChildRequestResponse() +{ + CleanupAction action = mSent ? ForgetFds : DeleteFds; + CleanupChildFds(mRequestResponse.request().body(), action); + CleanupChildFds(mRequestResponse.response().body(), action); +} + +void +AutoChildRequestResponse::Add(InternalRequest* aRequest, BodyAction aBodyAction, + ReferrerAction aReferrerAction, + SchemeAction aSchemeAction, ErrorResult& aRv) +{ + MOZ_ASSERT(!mSent); + mTypeUtils->ToPCacheRequest(mRequestResponse.request(), aRequest, aBodyAction, + aReferrerAction, aSchemeAction, aRv); +} + +void +AutoChildRequestResponse::Add(Response& aResponse, ErrorResult& aRv) +{ + MOZ_ASSERT(!mSent); + mTypeUtils->ToPCacheResponse(mRequestResponse.response(), aResponse, aRv); +} + +const CacheRequestResponse& +AutoChildRequestResponse::SendAsRequestResponse() +{ + MOZ_ASSERT(!mSent); + mSent = true; + return mRequestResponse; +} + +// -------------------------------------------- + +AutoParentBase::AutoParentBase(PBackgroundParent* aManager) + : mManager(aManager) + , mStreamControl(nullptr) + , mSent(false) +{ + MOZ_ASSERT(mManager); +} + +AutoParentBase::~AutoParentBase() +{ + if (!mSent && mStreamControl) { + unused << PCacheStreamControlParent::Send__delete__(mStreamControl); + } +} + +void +AutoParentBase::SerializeReadStream(const nsID& aId, StreamList* aStreamList, + PCacheReadStream* aReadStreamOut) +{ + MOZ_ASSERT(aStreamList); + MOZ_ASSERT(aReadStreamOut); + MOZ_ASSERT(!mSent); + + nsCOMPtr stream = aStreamList->Extract(aId); + MOZ_ASSERT(stream); + + if (!mStreamControl) { + mStreamControl = static_cast( + mManager->SendPCacheStreamControlConstructor(new CacheStreamControlParent())); + + // If this failed, then the child process is gone. Warn and allow actor + // cleanup to proceed as normal. + if (!mStreamControl) { + NS_WARNING("Cache failed to create stream control actor."); + return; + } + } + + aStreamList->SetStreamControl(mStreamControl); + + nsRefPtr readStream = ReadStream::Create(mStreamControl, + aId, stream); + readStream->Serialize(aReadStreamOut); +} + +// -------------------------------------------- + +AutoParentRequestList::AutoParentRequestList(PBackgroundParent* aManager, + uint32_t aCapacity) + : AutoParentBase(aManager) +{ + mRequestList.SetCapacity(aCapacity); +} + +AutoParentRequestList::~AutoParentRequestList() +{ + CleanupAction action = mSent ? ForgetFds : DeleteFds; + for (uint32_t i = 0; i < mRequestList.Length(); ++i) { + CleanupParentFds(mRequestList[i].body(), action); + } +} + +void +AutoParentRequestList::Add(const SavedRequest& aSavedRequest, + StreamList* aStreamList) +{ + MOZ_ASSERT(!mSent); + + mRequestList.AppendElement(aSavedRequest.mValue); + PCacheRequest& request = mRequestList.LastElement(); + + if (!aSavedRequest.mHasBodyId) { + request.body() = void_t(); + return; + } + + request.body() = PCacheReadStream(); + SerializeReadStream(aSavedRequest.mBodyId, aStreamList, + &request.body().get_PCacheReadStream()); +} + +const nsTArray& +AutoParentRequestList::SendAsRequestList() +{ + MOZ_ASSERT(!mSent); + mSent = true; + return mRequestList; +} + +// -------------------------------------------- + +AutoParentResponseList::AutoParentResponseList(PBackgroundParent* aManager, + uint32_t aCapacity) + : AutoParentBase(aManager) +{ + mResponseList.SetCapacity(aCapacity); +} + +AutoParentResponseList::~AutoParentResponseList() +{ + CleanupAction action = mSent ? ForgetFds : DeleteFds; + for (uint32_t i = 0; i < mResponseList.Length(); ++i) { + CleanupParentFds(mResponseList[i].body(), action); + } +} + +void +AutoParentResponseList::Add(const SavedResponse& aSavedResponse, + StreamList* aStreamList) +{ + MOZ_ASSERT(!mSent); + + mResponseList.AppendElement(aSavedResponse.mValue); + PCacheResponse& response = mResponseList.LastElement(); + + if (!aSavedResponse.mHasBodyId) { + response.body() = void_t(); + return; + } + + response.body() = PCacheReadStream(); + SerializeReadStream(aSavedResponse.mBodyId, aStreamList, + &response.body().get_PCacheReadStream()); +} + +const nsTArray& +AutoParentResponseList::SendAsResponseList() +{ + MOZ_ASSERT(!mSent); + mSent = true; + return mResponseList; +} + +// -------------------------------------------- + +AutoParentResponseOrVoid::AutoParentResponseOrVoid(ipc::PBackgroundParent* aManager) + : AutoParentBase(aManager) +{ + mResponseOrVoid = void_t(); +} + +AutoParentResponseOrVoid::~AutoParentResponseOrVoid() +{ + if (mResponseOrVoid.type() != PCacheResponseOrVoid::TPCacheResponse) { + return; + } + + CleanupAction action = mSent ? ForgetFds : DeleteFds; + CleanupParentFds(mResponseOrVoid.get_PCacheResponse().body(), action); +} + +void +AutoParentResponseOrVoid::Add(const SavedResponse& aSavedResponse, + StreamList* aStreamList) +{ + MOZ_ASSERT(!mSent); + + mResponseOrVoid = aSavedResponse.mValue; + PCacheResponse& response = mResponseOrVoid.get_PCacheResponse(); + + if (!aSavedResponse.mHasBodyId) { + response.body() = void_t(); + return; + } + + response.body() = PCacheReadStream(); + SerializeReadStream(aSavedResponse.mBodyId, aStreamList, + &response.body().get_PCacheReadStream()); +} + +const PCacheResponseOrVoid& +AutoParentResponseOrVoid::SendAsResponseOrVoid() +{ + MOZ_ASSERT(!mSent); + mSent = true; + return mResponseOrVoid; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/AutoUtils.h b/dom/cache/AutoUtils.h new file mode 100644 index 0000000000..c7996772cc --- /dev/null +++ b/dom/cache/AutoUtils.h @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_AutoUtils_h +#define mozilla_dom_cache_AutoUtils_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "nsTArray.h" + +struct nsID; + +namespace mozilla { + +class ErrorResult; + +namespace ipc { +class PBackgroundParent; +} + +namespace dom { + +class InternalRequest; +class OwningRequestOrUSVString; +class RequestOrUSVString; +template class Optional; + +namespace cache { + +class CacheStreamControlParent; +struct SavedRequest; +struct SavedResponse; +class StreamList; + +// A collection of RAII-style helper classes to ensure that IPC +// FileDescriptorSet actors are properly cleaned up. The user of these actors +// must manually either Forget() the Fds or Send__delete__() the actor +// depending on if the descriptors were actually sent. +// +// Note, these should only be used when *sending* streams across IPC. The +// deserialization case is handled by creating a ReadStream object. + +class MOZ_STACK_CLASS AutoChildBase +{ +protected: + typedef TypeUtils::BodyAction BodyAction; + typedef TypeUtils::ReferrerAction ReferrerAction; + typedef TypeUtils::SchemeAction SchemeAction; + + AutoChildBase(TypeUtils* aTypeUtils); + virtual ~AutoChildBase() = 0; + + TypeUtils* mTypeUtils; + bool mSent; +}; + +class MOZ_STACK_CLASS AutoChildRequest MOZ_FINAL : public AutoChildBase +{ +public: + explicit AutoChildRequest(TypeUtils* aTypeUtils); + ~AutoChildRequest(); + + void Add(InternalRequest* aRequest, BodyAction aBodyAction, + ReferrerAction aReferrerAction, SchemeAction aSchemeAction, + ErrorResult& aRv); + + const PCacheRequest& SendAsRequest(); + const PCacheRequestOrVoid& SendAsRequestOrVoid(); + +private: + PCacheRequestOrVoid mRequestOrVoid; +}; + +class MOZ_STACK_CLASS AutoChildRequestList MOZ_FINAL : public AutoChildBase +{ +public: + AutoChildRequestList(TypeUtils* aTypeUtils, uint32_t aCapacity); + ~AutoChildRequestList(); + + void Add(InternalRequest* aRequest, BodyAction aBodyAction, + ReferrerAction aReferrerAction, SchemeAction aSchemeAction, + ErrorResult& aRv); + + const nsTArray& SendAsRequestList(); + +private: + // Allocates ~5k inline in the stack-only class + nsAutoTArray mRequestList; +}; + +class MOZ_STACK_CLASS AutoChildRequestResponse MOZ_FINAL : public AutoChildBase +{ +public: + explicit AutoChildRequestResponse(TypeUtils* aTypeUtils); + ~AutoChildRequestResponse(); + + void Add(InternalRequest* aRequest, BodyAction aBodyAction, + ReferrerAction aReferrerAction, SchemeAction aSchemeAction, + ErrorResult& aRv); + void Add(Response& aResponse, ErrorResult& aRv); + + const CacheRequestResponse& SendAsRequestResponse(); + +private: + CacheRequestResponse mRequestResponse; +}; + +class MOZ_STACK_CLASS AutoParentBase +{ +protected: + explicit AutoParentBase(mozilla::ipc::PBackgroundParent* aManager); + virtual ~AutoParentBase() = 0; + + void SerializeReadStream(const nsID& aId, StreamList* aStreamList, + PCacheReadStream* aReadStreamOut); + + mozilla::ipc::PBackgroundParent* mManager; + CacheStreamControlParent* mStreamControl; + bool mSent; +}; + +class MOZ_STACK_CLASS AutoParentRequestList MOZ_FINAL : public AutoParentBase +{ +public: + AutoParentRequestList(mozilla::ipc::PBackgroundParent* aManager, + uint32_t aCapacity); + ~AutoParentRequestList(); + + void Add(const SavedRequest& aSavedRequest, StreamList* aStreamList); + + const nsTArray& SendAsRequestList(); + +private: + // Allocates ~5k inline in the stack-only class + nsAutoTArray mRequestList; +}; + +class MOZ_STACK_CLASS AutoParentResponseList MOZ_FINAL : public AutoParentBase +{ +public: + AutoParentResponseList(mozilla::ipc::PBackgroundParent* aManager, + uint32_t aCapacity); + ~AutoParentResponseList(); + + void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList); + + const nsTArray& SendAsResponseList(); + +private: + // Allocates ~4k inline in the stack-only class + nsAutoTArray mResponseList; +}; + +class MOZ_STACK_CLASS AutoParentResponseOrVoid MOZ_FINAL : public AutoParentBase +{ +public: + explicit AutoParentResponseOrVoid(mozilla::ipc::PBackgroundParent* aManager); + ~AutoParentResponseOrVoid(); + + void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList); + + const PCacheResponseOrVoid& SendAsResponseOrVoid(); + +private: + PCacheResponseOrVoid mResponseOrVoid; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_AutoUtils_h diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp new file mode 100644 index 0000000000..0cc5bca9ea --- /dev/null +++ b/dom/cache/Cache.cpp @@ -0,0 +1,586 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/Cache.h" + +#include "mozilla/dom/Headers.h" +#include "mozilla/dom/InternalResponse.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/Response.h" +#include "mozilla/dom/WorkerPrivate.h" +#include "mozilla/dom/CacheBinding.h" +#include "mozilla/dom/cache/AutoUtils.h" +#include "mozilla/dom/cache/CacheChild.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/Preferences.h" +#include "mozilla/unused.h" +#include "nsIGlobalObject.h" +#include "nsNetUtil.h" + +namespace { + +using mozilla::ErrorResult; +using mozilla::dom::MSG_INVALID_REQUEST_METHOD; +using mozilla::dom::OwningRequestOrUSVString; +using mozilla::dom::Request; +using mozilla::dom::RequestOrUSVString; + +static bool +IsValidPutRequestMethod(const Request& aRequest, ErrorResult& aRv) +{ + nsAutoCString method; + aRequest.GetMethod(method); + bool valid = method.LowerCaseEqualsLiteral("get"); + if (!valid) { + NS_ConvertASCIItoUTF16 label(method); + aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label); + } + return valid; +} + +static bool +IsValidPutRequestMethod(const RequestOrUSVString& aRequest, + ErrorResult& aRv) +{ + // If the provided request is a string URL, then it will default to + // a valid http method automatically. + if (!aRequest.IsRequest()) { + return true; + } + return IsValidPutRequestMethod(aRequest.GetAsRequest(), aRv); +} + +static bool +IsValidPutRequestMethod(const OwningRequestOrUSVString& aRequest, + ErrorResult& aRv) +{ + if (!aRequest.IsRequest()) { + return true; + } + return IsValidPutRequestMethod(*aRequest.GetAsRequest().get(), aRv); +} + +} // anonymous namespace + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::ErrorResult; +using mozilla::unused; +using mozilla::dom::workers::GetCurrentThreadWorkerPrivate; +using mozilla::dom::workers::WorkerPrivate; + +NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::Cache); +NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::Cache); +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Cache, mGlobal, mRequestPromises) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Cache) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY +NS_INTERFACE_MAP_END + +Cache::Cache(nsIGlobalObject* aGlobal, CacheChild* aActor) + : mGlobal(aGlobal) + , mActor(aActor) +{ + MOZ_ASSERT(mGlobal); + MOZ_ASSERT(mActor); + mActor->SetListener(this); +} + +already_AddRefed +Cache::Match(const RequestOrUSVString& aRequest, + const CacheQueryOptions& aOptions, ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + nsRefPtr ir = ToInternalRequest(aRequest, IgnoreBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + AutoChildRequest request(this); + + request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv); + if (aRv.Failed()) { + return nullptr; + } + + PCacheQueryParams params; + ToPCacheQueryParams(params, aOptions); + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendMatch(requestId, request.SendAsRequest(), params); + + return promise.forget(); +} + +already_AddRefed +Cache::MatchAll(const Optional& aRequest, + const CacheQueryOptions& aOptions, ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + AutoChildRequest request(this); + + if (aRequest.WasPassed()) { + nsRefPtr ir = ToInternalRequest(aRequest.Value(), + IgnoreBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv); + if (aRv.Failed()) { + return nullptr; + } + } + + PCacheQueryParams params; + ToPCacheQueryParams(params, aOptions); + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendMatchAll(requestId, request.SendAsRequestOrVoid(), + params); + + return promise.forget(); +} + +already_AddRefed +Cache::Add(const RequestOrUSVString& aRequest, ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + if (!IsValidPutRequestMethod(aRequest, aRv)) { + return nullptr; + } + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + nsRefPtr ir = ToInternalRequest(aRequest, ReadBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + AutoChildRequestList requests(this, 1); + requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv); + if (aRv.Failed()) { + return nullptr; + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendAddAll(requestId, requests.SendAsRequestList()); + + return promise.forget(); +} + +already_AddRefed +Cache::AddAll(const Sequence& aRequests, + ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + // If there is no work to do, then resolve immediately + if (aRequests.IsEmpty()) { + promise->MaybeResolve(JS::UndefinedHandleValue); + return promise.forget(); + } + + AutoChildRequestList requests(this, aRequests.Length()); + + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + if (!IsValidPutRequestMethod(aRequests[i], aRv)) { + return nullptr; + } + + nsRefPtr ir = ToInternalRequest(aRequests[i], ReadBody, + aRv); + if (aRv.Failed()) { + return nullptr; + } + + requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, + aRv); + if (aRv.Failed()) { + return nullptr; + } + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendAddAll(requestId, requests.SendAsRequestList()); + + return promise.forget(); +} + +already_AddRefed +Cache::Put(const RequestOrUSVString& aRequest, Response& aResponse, + ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + if (!IsValidPutRequestMethod(aRequest, aRv)) { + return nullptr; + } + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + nsRefPtr ir = ToInternalRequest(aRequest, ReadBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + AutoChildRequestResponse put(this); + put.Add(ir, ReadBody, PassThroughReferrer, TypeErrorOnInvalidScheme, aRv); + if (aRv.Failed()) { + return nullptr; + } + + put.Add(aResponse, aRv); + if (aRv.Failed()) { + return nullptr; + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendPut(requestId, put.SendAsRequestResponse()); + + return promise.forget(); +} + +already_AddRefed +Cache::Delete(const RequestOrUSVString& aRequest, + const CacheQueryOptions& aOptions, ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + nsRefPtr ir = ToInternalRequest(aRequest, IgnoreBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + AutoChildRequest request(this); + request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv); + if (aRv.Failed()) { + return nullptr; + } + + PCacheQueryParams params; + ToPCacheQueryParams(params, aOptions); + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendDelete(requestId, request.SendAsRequest(), params); + + return promise.forget(); +} + +already_AddRefed +Cache::Keys(const Optional& aRequest, + const CacheQueryOptions& aOptions, ErrorResult& aRv) +{ + MOZ_ASSERT(mActor); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + AutoChildRequest request(this); + + if (aRequest.WasPassed()) { + nsRefPtr ir = ToInternalRequest(aRequest.Value(), + IgnoreBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv); + if (aRv.Failed()) { + return nullptr; + } + } + + PCacheQueryParams params; + ToPCacheQueryParams(params, aOptions); + + RequestId requestId = AddRequestPromise(promise, aRv); + + unused << mActor->SendKeys(requestId, request.SendAsRequestOrVoid(), params); + + return promise.forget(); +} + +// static +bool +Cache::PrefEnabled(JSContext* aCx, JSObject* aObj) +{ + using mozilla::dom::workers::WorkerPrivate; + using mozilla::dom::workers::GetWorkerPrivateFromContext; + + // If we're on the main thread, then check the pref directly. + if (NS_IsMainThread()) { + bool enabled = false; + Preferences::GetBool("dom.caches.enabled", &enabled); + return enabled; + } + + // Otherwise check the pref via the work private helper + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + if (!workerPrivate) { + return false; + } + + return workerPrivate->DOMCachesEnabled(); +} + +nsISupports* +Cache::GetParentObject() const +{ + return mGlobal; +} + +JSObject* +Cache::WrapObject(JSContext* aContext) +{ + return CacheBinding::Wrap(aContext, this); +} + +void +Cache::DestroyInternal(CacheChild* aActor) +{ + MOZ_ASSERT(mActor); + MOZ_ASSERT(mActor == aActor); + mActor->ClearListener(); + mActor = nullptr; +} + +void +Cache::RecvMatchResponse(RequestId aRequestId, nsresult aRv, + const PCacheResponseOrVoid& aResponse) +{ + // Convert the response immediately if its present. This ensures that + // any stream actors are cleaned up, even if we error out below. + nsRefPtr response; + if (aResponse.type() == PCacheResponseOrVoid::TPCacheResponse) { + response = ToResponse(aResponse); + } + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + if (!response) { + promise->MaybeResolve(JS::UndefinedHandleValue); + return; + } + + promise->MaybeResolve(response); +} + +void +Cache::RecvMatchAllResponse(RequestId aRequestId, nsresult aRv, + const nsTArray& aResponses) +{ + // Convert responses immediately. This ensures that any stream actors are + // cleaned up, even if we error out below. + nsAutoTArray, 256> responses; + responses.SetCapacity(aResponses.Length()); + + for (uint32_t i = 0; i < aResponses.Length(); ++i) { + nsRefPtr response = ToResponse(aResponses[i]); + responses.AppendElement(response.forget()); + } + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(responses); +} + +void +Cache::RecvAddAllResponse(RequestId aRequestId, nsresult aRv) +{ + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(JS::UndefinedHandleValue); +} + +void +Cache::RecvPutResponse(RequestId aRequestId, nsresult aRv) +{ + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(JS::UndefinedHandleValue); +} + +void +Cache::RecvDeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess) +{ + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(aSuccess); +} + +void +Cache::RecvKeysResponse(RequestId aRequestId, nsresult aRv, + const nsTArray& aRequests) +{ + // Convert requests immediately. This ensures that any stream actors are + // cleaned up, even if we error out below. + nsAutoTArray, 256> requests; + requests.SetCapacity(aRequests.Length()); + + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + nsRefPtr request = ToRequest(aRequests[i]); + requests.AppendElement(request.forget()); + } + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(requests); +} + +nsIGlobalObject* +Cache::GetGlobalObject() const +{ + return mGlobal; +} + +#ifdef DEBUG +void +Cache::AssertOwningThread() const +{ + NS_ASSERT_OWNINGTHREAD(Cache); +} +#endif + +void +Cache::ResolvedCallback(JSContext* aCx, JS::Handle aValue) +{ + // Do nothing. The Promise will automatically drop the ref to us after + // calling the callback. This is what we want as we only registered in order + // to be held alive via the Promise handle. +} + +void +Cache::RejectedCallback(JSContext* aCx, JS::Handle aValue) +{ + // Do nothing. The Promise will automatically drop the ref to us after + // calling the callback. This is what we want as we only registered in order + // to be held alive via the Promise handle. +} + +Cache::~Cache() +{ + if (mActor) { + mActor->StartDestroy(); + // DestroyInternal() is called synchronously by StartDestroy(). So we + // should have already cleared the mActor. + MOZ_ASSERT(!mActor); + } +} + +RequestId +Cache::AddRequestPromise(Promise* aPromise, ErrorResult& aRv) +{ + MOZ_ASSERT(aPromise); + MOZ_ASSERT(!mRequestPromises.Contains(aPromise)); + + // Register ourself as a promise handler so that the promise will hold us + // alive. This allows the client code to drop the ref to the Cache + // object and just keep their promise. This is fairly common in promise + // chaining code. + aPromise->AppendNativeHandler(this); + + mRequestPromises.AppendElement(aPromise); + + // (Ab)use the promise pointer as our request ID. This is a fast, thread-safe + // way to get a unique ID for the promise to be resolved later. + return reinterpret_cast(aPromise); +} + +already_AddRefed +Cache::RemoveRequestPromise(RequestId aRequestId) +{ + MOZ_ASSERT(aRequestId != INVALID_REQUEST_ID); + + for (uint32_t i = 0; i < mRequestPromises.Length(); ++i) { + nsRefPtr& promise = mRequestPromises.ElementAt(i); + // To be safe, only cast promise pointers to our integer RequestId + // type and never cast an integer to a pointer. + if (aRequestId == reinterpret_cast(promise.get())) { + nsRefPtr ref; + ref.swap(promise); + mRequestPromises.RemoveElementAt(i); + return ref.forget(); + } + } + MOZ_ASSERT_UNREACHABLE("Received response without a matching promise!"); + return nullptr; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/Cache.h b/dom/cache/Cache.h new file mode 100644 index 0000000000..7540535bb2 --- /dev/null +++ b/dom/cache/Cache.h @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_Cache_h +#define mozilla_dom_cache_Cache_h + +#include "mozilla/dom/PromiseNativeHandler.h" +#include "mozilla/dom/cache/Types.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "nsCOMPtr.h" +#include "nsISupportsImpl.h" +#include "nsString.h" +#include "nsWrapperCache.h" + +class nsIGlobalObject; + +namespace mozilla { + +class ErrorResult; + +namespace ipc { + class IProtocol; +} + +namespace dom { + +class OwningRequestOrUSVString; +class Promise; +struct CacheQueryOptions; +class RequestOrUSVString; +class Response; +template class Optional; +template class Sequence; + +namespace cache { + +class CacheChild; +class PCacheRequest; +class PCacheRequestOrVoid; +class PCacheResponse; +class PCacheResponseOrVoid; +class PCacheStreamControlChild; + +class Cache MOZ_FINAL : public PromiseNativeHandler + , public nsWrapperCache + , public TypeUtils +{ +public: + Cache(nsIGlobalObject* aGlobal, CacheChild* aActor); + + // webidl interface methods + already_AddRefed + Match(const RequestOrUSVString& aRequest, const CacheQueryOptions& aOptions, + ErrorResult& aRv); + already_AddRefed + MatchAll(const Optional& aRequest, + const CacheQueryOptions& aOptions, ErrorResult& aRv); + already_AddRefed + Add(const RequestOrUSVString& aRequest, ErrorResult& aRv); + already_AddRefed + AddAll(const Sequence& aRequests, + ErrorResult& aRv); + already_AddRefed + Put(const RequestOrUSVString& aRequest, Response& aResponse, + ErrorResult& aRv); + already_AddRefed + Delete(const RequestOrUSVString& aRequest, const CacheQueryOptions& aOptions, + ErrorResult& aRv); + already_AddRefed + Keys(const Optional& aRequest, + const CacheQueryOptions& aParams, ErrorResult& aRv); + + // binding methods + static bool PrefEnabled(JSContext* aCx, JSObject* aObj); + + nsISupports* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aContext) MOZ_OVERRIDE; + + // Called when CacheChild actor is being destroyed + void DestroyInternal(CacheChild* aActor); + + // methods forwarded from CacheChild + void RecvMatchResponse(RequestId aRequestId, nsresult aRv, + const PCacheResponseOrVoid& aResponse); + void RecvMatchAllResponse(RequestId aRequestId, nsresult aRv, + const nsTArray& aResponses); + void RecvAddAllResponse(RequestId aRequestId, nsresult aRv); + void RecvPutResponse(RequestId aRequestId, nsresult aRv); + + void RecvDeleteResponse(RequestId aRequestId, nsresult aRv, + bool aSuccess); + void RecvKeysResponse(RequestId aRequestId, nsresult aRv, + const nsTArray& aRequests); + + // TypeUtils methods + virtual nsIGlobalObject* + GetGlobalObject() const MOZ_OVERRIDE; + +#ifdef DEBUG + virtual void AssertOwningThread() const MOZ_OVERRIDE; +#endif + + // PromiseNativeHandler methods + virtual void + ResolvedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE; + + virtual void + RejectedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE; + +private: + ~Cache(); + + // TODO: Replace with actor-per-request model during refactor (bug 1110485) + RequestId AddRequestPromise(Promise* aPromise, ErrorResult& aRv); + already_AddRefed RemoveRequestPromise(RequestId aRequestId); + + nsCOMPtr mGlobal; + CacheChild* mActor; + nsTArray> mRequestPromises; + +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Cache) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_Cache_h diff --git a/dom/cache/CacheChild.cpp b/dom/cache/CacheChild.cpp new file mode 100644 index 0000000000..c4910446a3 --- /dev/null +++ b/dom/cache/CacheChild.cpp @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheChild.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/cache/ActorUtils.h" +#include "mozilla/dom/cache/Cache.h" +#include "mozilla/dom/cache/StreamUtils.h" + +namespace mozilla { +namespace dom { +namespace cache { + +// Declared in ActorUtils.h +PCacheChild* +AllocPCacheChild() +{ + return new CacheChild(); +} + +// Declared in ActorUtils.h +void +DeallocPCacheChild(PCacheChild* aActor) +{ + delete aActor; +} + +CacheChild::CacheChild() + : mListener(nullptr) +{ + MOZ_COUNT_CTOR(cache::CacheChild); +} + +CacheChild::~CacheChild() +{ + MOZ_COUNT_DTOR(cache::CacheChild); + NS_ASSERT_OWNINGTHREAD(CacheChild); + MOZ_ASSERT(!mListener); +} + +void +CacheChild::SetListener(Cache* aListener) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + MOZ_ASSERT(!mListener); + mListener = aListener; + MOZ_ASSERT(mListener); +} + +void +CacheChild::ClearListener() +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + MOZ_ASSERT(mListener); + mListener = nullptr; +} + +void +CacheChild::StartDestroy() +{ + nsRefPtr listener = mListener; + + // StartDestroy() can get called from either Cache or the Feature. + // Theoretically we can get double called if the right race happens. Handle + // that by just ignoring the second StartDestroy() call. + if (!listener) { + return; + } + + listener->DestroyInternal(this); + + // Cache listener should call ClearListener() in DestroyInternal() + MOZ_ASSERT(!mListener); + + // Start actor destruction from parent process + unused << SendTeardown(); +} + +void +CacheChild::ActorDestroy(ActorDestroyReason aReason) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + nsRefPtr listener = mListener; + if (listener) { + listener->DestroyInternal(this); + // Cache listener should call ClearListener() in DestroyInternal() + MOZ_ASSERT(!mListener); + } + + RemoveFeature(); +} + +bool +CacheChild::RecvMatchResponse(const RequestId& requestId, const nsresult& aRv, + const PCacheResponseOrVoid& aResponse) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + + AddFeatureToStreamChild(aResponse, GetFeature()); + + nsRefPtr listener = mListener; + if (!listener) { + StartDestroyStreamChild(aResponse); + return true; + } + + listener->RecvMatchResponse(requestId, aRv, aResponse); + return true; +} + +bool +CacheChild::RecvMatchAllResponse(const RequestId& requestId, const nsresult& aRv, + nsTArray&& aResponses) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + + AddFeatureToStreamChild(aResponses, GetFeature()); + + nsRefPtr listener = mListener; + if (!listener) { + StartDestroyStreamChild(aResponses); + return true; + } + + listener->RecvMatchAllResponse(requestId, aRv, aResponses); + return true; +} + +bool +CacheChild::RecvAddAllResponse(const RequestId& requestId, const nsresult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + nsRefPtr listener = mListener; + if (listener) { + listener->RecvAddAllResponse(requestId, aRv); + } + return true; +} + +bool +CacheChild::RecvPutResponse(const RequestId& aRequestId, const nsresult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + nsRefPtr listener = mListener; + if (listener) { + listener->RecvPutResponse(aRequestId, aRv); + } + return true; +} + +bool +CacheChild::RecvDeleteResponse(const RequestId& requestId, const nsresult& aRv, + const bool& result) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + nsRefPtr listener = mListener; + if (listener) { + listener->RecvDeleteResponse(requestId, aRv, result); + } + return true; +} + +bool +CacheChild::RecvKeysResponse(const RequestId& requestId, const nsresult& aRv, + nsTArray&& aRequests) +{ + NS_ASSERT_OWNINGTHREAD(CacheChild); + + AddFeatureToStreamChild(aRequests, GetFeature()); + + nsRefPtr listener = mListener; + if (!listener) { + StartDestroyStreamChild(aRequests); + return true; + } + + listener->RecvKeysResponse(requestId, aRv, aRequests); + return true; +} + +} // namespace cache +} // namespace dom +} // namesapce mozilla diff --git a/dom/cache/CacheChild.h b/dom/cache/CacheChild.h new file mode 100644 index 0000000000..a9f555c304 --- /dev/null +++ b/dom/cache/CacheChild.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheChild_h +#define mozilla_dom_cache_CacheChild_h + +#include "mozilla/dom/cache/ActorChild.h" +#include "mozilla/dom/cache/PCacheChild.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class Cache; + +class CacheChild MOZ_FINAL : public PCacheChild + , public ActorChild +{ +public: + CacheChild(); + ~CacheChild(); + + void SetListener(Cache* aListener); + + // Must be called by the associated Cache listener in its ActorDestroy() + // method. Also, Cache must Send__delete__() the actor in its destructor to + // trigger ActorDestroy() if it has not been called yet. + void ClearListener(); + + // ActorChild methods + + // Synchronously call ActorDestroy on our Cache listener and then start the + // actor destruction asynchronously from the parent-side. + virtual void StartDestroy() MOZ_OVERRIDE; + +private: + // PCacheChild methods + virtual void + ActorDestroy(ActorDestroyReason aReason) MOZ_OVERRIDE; + + virtual bool + RecvMatchResponse(const RequestId& requestId, const nsresult& aRv, + const PCacheResponseOrVoid& aResponse) MOZ_OVERRIDE; + virtual bool + RecvMatchAllResponse(const RequestId& requestId, const nsresult& aRv, + nsTArray&& responses) MOZ_OVERRIDE; + virtual bool + RecvAddAllResponse(const RequestId& requestId, + const nsresult& aRv) MOZ_OVERRIDE; + virtual bool + RecvPutResponse(const RequestId& aRequestId, + const nsresult& aRv) MOZ_OVERRIDE; + virtual bool + RecvDeleteResponse(const RequestId& requestId, const nsresult& aRv, + const bool& result) MOZ_OVERRIDE; + virtual bool + RecvKeysResponse(const RequestId& requestId, const nsresult& aRv, + nsTArray&& requests) MOZ_OVERRIDE; + + // Use a weak ref so actor does not hold DOM object alive past content use. + // The Cache object must call ClearListener() to null this before its + // destroyed. + Cache* MOZ_NON_OWNING_REF mListener; + + NS_DECL_OWNINGTHREAD +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheChild_h diff --git a/dom/cache/CacheInitData.ipdlh b/dom/cache/CacheInitData.ipdlh new file mode 100644 index 0000000000..34da66a034 --- /dev/null +++ b/dom/cache/CacheInitData.ipdlh @@ -0,0 +1,24 @@ +/* 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 PBackgroundSharedTypes; + +using mozilla::dom::cache::Namespace from "mozilla/dom/cache/Types.h"; + +namespace mozilla { +namespace dom { +namespace cache { + +// Data needed to initialize a CacheStorage or Cache backend. Don't put +// this with the other types in PCacheTypes.ipdlh since we want to import +// it into PBackground.ipdl. +struct CacheInitData +{ + Namespace namespaceEnum; + PrincipalInfo principalInfo; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/CacheParent.cpp b/dom/cache/CacheParent.cpp new file mode 100644 index 0000000000..7e14bb6260 --- /dev/null +++ b/dom/cache/CacheParent.cpp @@ -0,0 +1,291 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheParent.h" + +#include "mozilla/DebugOnly.h" +#include "mozilla/dom/cache/AutoUtils.h" +#include "mozilla/dom/cache/CacheStreamControlParent.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/dom/cache/SavedTypes.h" +#include "mozilla/dom/cache/StreamList.h" +#include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/ipc/PBackgroundParent.h" +#include "mozilla/ipc/FileDescriptorSetParent.h" +#include "mozilla/ipc/PFileDescriptorSetParent.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::ipc::FileDescriptorSetParent; +using mozilla::ipc::PFileDescriptorSetParent; + +// Declared in ActorUtils.h +void +DeallocPCacheParent(PCacheParent* aActor) +{ + delete aActor; +} + +CacheParent::CacheParent(cache::Manager* aManager, CacheId aCacheId) + : mManager(aManager) + , mCacheId(aCacheId) +{ + MOZ_COUNT_CTOR(cache::CacheParent); + MOZ_ASSERT(mManager); + mManager->AddRefCacheId(mCacheId); +} + +CacheParent::~CacheParent() +{ + MOZ_COUNT_DTOR(cache::CacheParent); + MOZ_ASSERT(!mManager); + MOZ_ASSERT(mFetchPutList.IsEmpty()); +} + +void +CacheParent::ActorDestroy(ActorDestroyReason aReason) +{ + MOZ_ASSERT(mManager); + for (uint32_t i = 0; i < mFetchPutList.Length(); ++i) { + mFetchPutList[i]->ClearListener(); + } + mFetchPutList.Clear(); + mManager->RemoveListener(this); + mManager->ReleaseCacheId(mCacheId); + mManager = nullptr; +} + +bool +CacheParent::RecvTeardown() +{ + if (!Send__delete__(this)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send delete."); + } + return true; +} + +bool +CacheParent::RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) +{ + MOZ_ASSERT(mManager); + mManager->CacheMatch(this, aRequestId, mCacheId, aRequest, + aParams); + return true; +} + +bool +CacheParent::RecvMatchAll(const RequestId& aRequestId, + const PCacheRequestOrVoid& aRequest, + const PCacheQueryParams& aParams) +{ + MOZ_ASSERT(mManager); + mManager->CacheMatchAll(this, aRequestId, mCacheId, aRequest, aParams); + return true; +} + +bool +CacheParent::RecvAddAll(const RequestId& aRequestId, + nsTArray&& aRequests) +{ + nsAutoTArray, 256> requestStreams; + requestStreams.SetCapacity(aRequests.Length()); + + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + requestStreams.AppendElement(DeserializeCacheStream(aRequests[i].body())); + } + + nsRefPtr fetchPut; + nsresult rv = FetchPut::Create(this, mManager, aRequestId, mCacheId, + aRequests, requestStreams, + getter_AddRefs(fetchPut)); + if (NS_WARN_IF(NS_FAILED(rv))) { + if (!SendAddAllResponse(aRequestId, rv)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send AddAll response."); + } + return true; + } + + mFetchPutList.AppendElement(fetchPut.forget()); + + return true; +} + +bool +CacheParent::RecvPut(const RequestId& aRequestId, + const CacheRequestResponse& aPut) +{ + MOZ_ASSERT(mManager); + + nsAutoTArray putList; + putList.AppendElement(aPut); + + nsAutoTArray, 1> requestStreamList; + nsAutoTArray, 1> responseStreamList; + + requestStreamList.AppendElement( + DeserializeCacheStream(aPut.request().body())); + responseStreamList.AppendElement( + DeserializeCacheStream(aPut.response().body())); + + + mManager->CachePutAll(this, aRequestId, mCacheId, putList, requestStreamList, + responseStreamList); + + return true; +} + +bool +CacheParent::RecvDelete(const RequestId& aRequestId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) +{ + MOZ_ASSERT(mManager); + mManager->CacheDelete(this, aRequestId, mCacheId, aRequest, aParams); + return true; +} + +bool +CacheParent::RecvKeys(const RequestId& aRequestId, + const PCacheRequestOrVoid& aRequest, + const PCacheQueryParams& aParams) +{ + MOZ_ASSERT(mManager); + mManager->CacheKeys(this, aRequestId, mCacheId, aRequest, aParams); + return true; +} + +void +CacheParent::OnCacheMatch(RequestId aRequestId, nsresult aRv, + const SavedResponse* aSavedResponse, + StreamList* aStreamList) +{ + AutoParentResponseOrVoid response(Manager()); + + // no match + if (NS_FAILED(aRv) || !aSavedResponse || !aStreamList) { + if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send Match response."); + } + return; + } + + if (aSavedResponse) { + response.Add(*aSavedResponse, aStreamList); + } + + if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send Match response."); + } +} + +void +CacheParent::OnCacheMatchAll(RequestId aRequestId, nsresult aRv, + const nsTArray& aSavedResponses, + StreamList* aStreamList) +{ + AutoParentResponseList responses(Manager(), aSavedResponses.Length()); + + for (uint32_t i = 0; i < aSavedResponses.Length(); ++i) { + responses.Add(aSavedResponses[i], aStreamList); + } + + if (!SendMatchAllResponse(aRequestId, aRv, responses.SendAsResponseList())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send MatchAll response."); + } +} + +void +CacheParent::OnCachePutAll(RequestId aRequestId, nsresult aRv) +{ + if (!SendPutResponse(aRequestId, aRv)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send Put response."); + } +} + +void +CacheParent::OnCacheDelete(RequestId aRequestId, nsresult aRv, bool aSuccess) +{ + if (!SendDeleteResponse(aRequestId, aRv, aSuccess)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send Delete response."); + } +} + +void +CacheParent::OnCacheKeys(RequestId aRequestId, nsresult aRv, + const nsTArray& aSavedRequests, + StreamList* aStreamList) +{ + AutoParentRequestList requests(Manager(), aSavedRequests.Length()); + + for (uint32_t i = 0; i < aSavedRequests.Length(); ++i) { + requests.Add(aSavedRequests[i], aStreamList); + } + + if (!SendKeysResponse(aRequestId, aRv, requests.SendAsRequestList())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send Keys response."); + } +} + +void +CacheParent::OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, nsresult aRv) +{ + aFetchPut->ClearListener(); + mFetchPutList.RemoveElement(aFetchPut); + if (!SendAddAllResponse(aRequestId, aRv)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to send AddAll response."); + } +} + +already_AddRefed +CacheParent::DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid) +{ + if (aStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) { + return nullptr; + } + + const PCacheReadStream& readStream = aStreamOrVoid.get_PCacheReadStream(); + + nsCOMPtr stream = ReadStream::Create(readStream); + if (stream) { + return stream.forget(); + } + + nsAutoTArray fds; + if (readStream.fds().type() == + OptionalFileDescriptorSet::TPFileDescriptorSetChild) { + + FileDescriptorSetParent* fdSetActor = + static_cast(readStream.fds().get_PFileDescriptorSetParent()); + MOZ_ASSERT(fdSetActor); + + fdSetActor->ForgetFileDescriptors(fds); + MOZ_ASSERT(!fds.IsEmpty()); + + if (!fdSetActor->Send__delete__(fdSetActor)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to delete fd set actor."); + } + } + + return DeserializeInputStream(readStream.params(), fds); +} + +} // namespace cache +} // namespace dom +} // namesapce mozilla diff --git a/dom/cache/CacheParent.h b/dom/cache/CacheParent.h new file mode 100644 index 0000000000..5d165cfe13 --- /dev/null +++ b/dom/cache/CacheParent.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheParent_h +#define mozilla_dom_cache_CacheParent_h + +#include "mozilla/dom/cache/FetchPut.h" +#include "mozilla/dom/cache/Manager.h" +#include "mozilla/dom/cache/PCacheParent.h" +#include "mozilla/dom/cache/Types.h" + +struct nsID; +template class nsRefPtr; + +namespace mozilla { +namespace dom { +namespace cache { + +class CacheDBConnection; +class CacheStreamControlParent; +struct SavedResponse; +struct StreamHolder; + +class CacheParent MOZ_FINAL : public PCacheParent + , public Manager::Listener + , public FetchPut::Listener +{ +public: + CacheParent(cache::Manager* aManager, CacheId aCacheId); + virtual ~CacheParent(); + +private: + // PCacheParent method + virtual void ActorDestroy(ActorDestroyReason aReason) MOZ_OVERRIDE; + virtual bool RecvTeardown() MOZ_OVERRIDE; + virtual bool + RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) MOZ_OVERRIDE; + virtual bool + RecvMatchAll(const RequestId& aRequestId, const PCacheRequestOrVoid& aRequest, + const PCacheQueryParams& aParams) MOZ_OVERRIDE; + virtual bool + RecvAddAll(const RequestId& aRequestId, + nsTArray&& aRequests) MOZ_OVERRIDE; + virtual bool + RecvPut(const RequestId& aRequestId, const CacheRequestResponse& aPut); + virtual bool + RecvDelete(const RequestId& aRequestId, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) MOZ_OVERRIDE; + virtual bool + RecvKeys(const RequestId& aRequestId, const PCacheRequestOrVoid& aRequest, + const PCacheQueryParams& aParams) MOZ_OVERRIDE; + + // Manager::Listener methods + virtual void OnCacheMatch(RequestId aRequestId, nsresult aRv, + const SavedResponse* aSavedResponse, + StreamList* aStreamList) MOZ_OVERRIDE; + virtual void OnCacheMatchAll(RequestId aRequestId, nsresult aRv, + const nsTArray& aSavedResponses, + StreamList* aStreamList) MOZ_OVERRIDE; + virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) MOZ_OVERRIDE; + virtual void OnCacheDelete(RequestId aRequestId, nsresult aRv, + bool aSuccess) MOZ_OVERRIDE; + virtual void OnCacheKeys(RequestId aRequestId, nsresult aRv, + const nsTArray& aSavedRequests, + StreamList* aStreamList) MOZ_OVERRIDE; + + // FetchPut::Listener methods + virtual void OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, + nsresult aRv) MOZ_OVERRIDE; + + already_AddRefed + DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid); + + nsRefPtr mManager; + const CacheId mCacheId; + nsTArray> mFetchPutList; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheParent_h diff --git a/dom/cache/CacheStorage.cpp b/dom/cache/CacheStorage.cpp new file mode 100644 index 0000000000..df226f26df --- /dev/null +++ b/dom/cache/CacheStorage.cpp @@ -0,0 +1,631 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheStorage.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/CacheStorageBinding.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/Response.h" +#include "mozilla/dom/cache/AutoUtils.h" +#include "mozilla/dom/cache/Cache.h" +#include "mozilla/dom/cache/CacheChild.h" +#include "mozilla/dom/cache/CacheStorageChild.h" +#include "mozilla/dom/cache/Feature.h" +#include "mozilla/dom/cache/PCacheChild.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/ipc/BackgroundUtils.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/ipc/PBackgroundSharedTypes.h" +#include "nsIGlobalObject.h" +#include "nsIScriptSecurityManager.h" +#include "WorkerPrivate.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::unused; +using mozilla::ErrorResult; +using mozilla::dom::workers::WorkerPrivate; +using mozilla::ipc::BackgroundChild; +using mozilla::ipc::PBackgroundChild; +using mozilla::ipc::IProtocol; +using mozilla::ipc::PrincipalInfo; +using mozilla::ipc::PrincipalToPrincipalInfo; + +NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::CacheStorage); +NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::CacheStorage); +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CacheStorage, mGlobal, + mRequestPromises) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CacheStorage) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback) +NS_INTERFACE_MAP_END + +// static +already_AddRefed +CacheStorage::CreateOnMainThread(Namespace aNamespace, nsIGlobalObject* aGlobal, + nsIPrincipal* aPrincipal, ErrorResult& aRv) +{ + MOZ_ASSERT(aGlobal); + MOZ_ASSERT(aPrincipal); + MOZ_ASSERT(NS_IsMainThread()); + + bool nullPrincipal; + nsresult rv = aPrincipal->GetIsNullPrincipal(&nullPrincipal); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(rv); + return nullptr; + } + + if (nullPrincipal) { + NS_WARNING("CacheStorage not supported on null principal."); + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + // An unknown appId means that this principal was created for the codebase + // without all the security information from the end document or worker. + // We require exact knowledge of this information before allowing the + // caller to touch the disk using the Cache API. + bool unknownAppId = false; + aPrincipal->GetUnknownAppId(&unknownAppId); + if (unknownAppId) { + NS_WARNING("CacheStorage not supported on principal with unknown appId."); + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + PrincipalInfo principalInfo; + rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(rv); + return nullptr; + } + + nsRefPtr ref = new CacheStorage(aNamespace, aGlobal, + principalInfo, nullptr); + return ref.forget(); +} + +// static +already_AddRefed +CacheStorage::CreateOnWorker(Namespace aNamespace, nsIGlobalObject* aGlobal, + WorkerPrivate* aWorkerPrivate, ErrorResult& aRv) +{ + MOZ_ASSERT(aGlobal); + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + nsRefPtr feature = Feature::Create(aWorkerPrivate); + if (!feature) { + NS_WARNING("Worker thread is shutting down."); + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + const PrincipalInfo& principalInfo = aWorkerPrivate->GetPrincipalInfo(); + if (principalInfo.type() == PrincipalInfo::TNullPrincipalInfo) { + NS_WARNING("CacheStorage not supported on null principal."); + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + if (principalInfo.type() == PrincipalInfo::TContentPrincipalInfo && + principalInfo.get_ContentPrincipalInfo().appId() == + nsIScriptSecurityManager::UNKNOWN_APP_ID) { + NS_WARNING("CacheStorage not supported on principal with unknown appId."); + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsRefPtr ref = new CacheStorage(aNamespace, aGlobal, + principalInfo, feature); + return ref.forget(); +} + +CacheStorage::CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal, + const PrincipalInfo& aPrincipalInfo, Feature* aFeature) + : mNamespace(aNamespace) + , mGlobal(aGlobal) + , mPrincipalInfo(MakeUnique(aPrincipalInfo)) + , mFeature(aFeature) + , mActor(nullptr) + , mFailedActor(false) +{ + MOZ_ASSERT(mGlobal); + + // If the PBackground actor is already initialized then we can + // immediately use it + PBackgroundChild* actor = BackgroundChild::GetForCurrentThread(); + if (actor) { + ActorCreated(actor); + return; + } + + // Otherwise we must begin the PBackground initialization process and + // wait for the async ActorCreated() callback. + MOZ_ASSERT(NS_IsMainThread()); + bool ok = BackgroundChild::GetOrCreateForCurrentThread(this); + if (!ok) { + ActorFailed(); + } +} + +already_AddRefed +CacheStorage::Match(const RequestOrUSVString& aRequest, + const CacheQueryOptions& aOptions, ErrorResult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + if (mFailedActor) { + promise->MaybeReject(NS_ERROR_UNEXPECTED); + return promise.forget(); + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + Entry entry; + entry.mRequestId = requestId; + entry.mOp = OP_MATCH; + entry.mOptions = aOptions; + entry.mRequest = ToInternalRequest(aRequest, IgnoreBody, aRv); + if (aRv.Failed()) { + return nullptr; + } + + mPendingRequests.AppendElement(entry); + + MaybeRunPendingRequests(); + + return promise.forget(); +} + +already_AddRefed +CacheStorage::Has(const nsAString& aKey, ErrorResult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + if (mFailedActor) { + promise->MaybeReject(NS_ERROR_UNEXPECTED); + return promise.forget(); + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + Entry* entry = mPendingRequests.AppendElement(); + entry->mRequestId = requestId; + entry->mOp = OP_HAS; + entry->mKey = aKey; + + MaybeRunPendingRequests(); + + return promise.forget(); +} + +already_AddRefed +CacheStorage::Open(const nsAString& aKey, ErrorResult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + if (mFailedActor) { + promise->MaybeReject(NS_ERROR_UNEXPECTED); + return promise.forget(); + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + Entry* entry = mPendingRequests.AppendElement(); + entry->mRequestId = requestId; + entry->mOp = OP_OPEN; + entry->mKey = aKey; + + MaybeRunPendingRequests(); + + return promise.forget(); +} + +already_AddRefed +CacheStorage::Delete(const nsAString& aKey, ErrorResult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + if (mFailedActor) { + promise->MaybeReject(NS_ERROR_UNEXPECTED); + return promise.forget(); + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + Entry* entry = mPendingRequests.AppendElement(); + entry->mRequestId = requestId; + entry->mOp = OP_DELETE; + entry->mKey = aKey; + + MaybeRunPendingRequests(); + + return promise.forget(); +} + +already_AddRefed +CacheStorage::Keys(ErrorResult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = Promise::Create(mGlobal, aRv); + if (!promise) { + return nullptr; + } + + if (mFailedActor) { + promise->MaybeReject(NS_ERROR_UNEXPECTED); + return promise.forget(); + } + + RequestId requestId = AddRequestPromise(promise, aRv); + + Entry* entry = mPendingRequests.AppendElement(); + entry->mRequestId = requestId; + entry->mOp = OP_KEYS; + + MaybeRunPendingRequests(); + + return promise.forget(); +} + +// static +bool +CacheStorage::PrefEnabled(JSContext* aCx, JSObject* aObj) +{ + return Cache::PrefEnabled(aCx, aObj); +} + +nsISupports* +CacheStorage::GetParentObject() const +{ + return mGlobal; +} + +JSObject* +CacheStorage::WrapObject(JSContext* aContext) +{ + return mozilla::dom::CacheStorageBinding::Wrap(aContext, this); +} + +void +CacheStorage::ActorCreated(PBackgroundChild* aActor) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + MOZ_ASSERT(aActor); + + if (NS_WARN_IF(mFeature && mFeature->Notified())) { + ActorFailed(); + return; + } + + // Feature ownership is passed to the CacheStorageChild actor and any actors + // it may create. The Feature will keep the worker thread alive until the + // actors can gracefully shutdown. + CacheStorageChild* newActor = new CacheStorageChild(this, mFeature); + PCacheStorageChild* constructedActor = + aActor->SendPCacheStorageConstructor(newActor, mNamespace, *mPrincipalInfo); + + if (NS_WARN_IF(!constructedActor)) { + ActorFailed(); + return; + } + + mFeature = nullptr; + + MOZ_ASSERT(constructedActor == newActor); + mActor = newActor; + + MaybeRunPendingRequests(); + MOZ_ASSERT(mPendingRequests.IsEmpty()); +} + +void +CacheStorage::ActorFailed() +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + MOZ_ASSERT(!mFailedActor); + + mFailedActor = true; + mFeature = nullptr; + + for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) { + RequestId requestId = mPendingRequests[i].mRequestId; + nsRefPtr promise = RemoveRequestPromise(requestId); + promise->MaybeReject(NS_ERROR_UNEXPECTED); + } + mPendingRequests.Clear(); +} + +void +CacheStorage::DestroyInternal(CacheStorageChild* aActor) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + MOZ_ASSERT(mActor); + MOZ_ASSERT(mActor == aActor); + mActor->ClearListener(); + mActor = nullptr; + + // Note that we will never get an actor again in case another request is + // made before this object is destructed. + ActorFailed(); +} + +void +CacheStorage::RecvMatchResponse(RequestId aRequestId, nsresult aRv, + const PCacheResponseOrVoid& aResponse) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + // Convert the response immediately if its present. This ensures that + // any stream actors are cleaned up, even if we error out below. + nsRefPtr response; + if (aResponse.type() == PCacheResponseOrVoid::TPCacheResponse) { + response = ToResponse(aResponse); + } + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + // If cache name was specified in the request options and the cache does + // not exist, then an error code will already have been set. If we + // still do not have a response, then we just resolve undefined like a + // normal Cache::Match. + if (!response) { + promise->MaybeResolve(JS::UndefinedHandleValue); + return; + } + + promise->MaybeResolve(response); +} + +void +CacheStorage::RecvHasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + + } + + promise->MaybeResolve(aSuccess); +} + +void +CacheStorage::RecvOpenResponse(RequestId aRequestId, nsresult aRv, + CacheChild* aActor) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + // Unlike most of our async callback Recv*() methods, this one gets back + // an actor. We need to make sure to clean it up in case of error. + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + if (aActor) { + // We cannot use the CacheChild::StartDestroy() method because there + // is no Cache object associated with the actor yet. Instead, just + // send the underlying Teardown message. + unused << aActor->SendTeardown(); + } + promise->MaybeReject(aRv); + return; + } + + if (!aActor) { + promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); + return; + } + + nsRefPtr cache = new Cache(mGlobal, aActor); + promise->MaybeResolve(cache); +} + +void +CacheStorage::RecvDeleteResponse(RequestId aRequestId, nsresult aRv, + bool aSuccess) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(aSuccess); +} + +void +CacheStorage::RecvKeysResponse(RequestId aRequestId, nsresult aRv, + const nsTArray& aKeys) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + nsRefPtr promise = RemoveRequestPromise(aRequestId); + + if (NS_FAILED(aRv)) { + promise->MaybeReject(aRv); + return; + } + + promise->MaybeResolve(aKeys); +} + +nsIGlobalObject* +CacheStorage::GetGlobalObject() const +{ + return mGlobal; +} + +#ifdef DEBUG +void +CacheStorage::AssertOwningThread() const +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); +} +#endif + +void +CacheStorage::ResolvedCallback(JSContext* aCx, JS::Handle aValue) +{ + // Do nothing. The Promise will automatically drop the ref to us after + // calling the callback. This is what we want as we only registered in order + // to be held alive via the Promise handle. +} + +void +CacheStorage::RejectedCallback(JSContext* aCx, JS::Handle aValue) +{ + // Do nothing. The Promise will automatically drop the ref to us after + // calling the callback. This is what we want as we only registered in order + // to be held alive via the Promise handle. +} + +CacheStorage::~CacheStorage() +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + + if (mActor) { + mActor->StartDestroy(); + // DestroyInternal() is called synchronously by StartDestroy(). So we + // should have already cleared the mActor. + MOZ_ASSERT(!mActor); + } +} + +void +CacheStorage::MaybeRunPendingRequests() +{ + if (!mActor) { + return; + } + + for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) { + // Note, the entry can be modified below due to Request/Response body + // being marked used. + Entry& entry = mPendingRequests[i]; + RequestId requestId = entry.mRequestId; + switch(entry.mOp) { + case OP_MATCH: + { + AutoChildRequest request(this); + ErrorResult rv; + request.Add(entry.mRequest, IgnoreBody, PassThroughReferrer, + IgnoreInvalidScheme, rv); + if (NS_WARN_IF(rv.Failed())) { + nsRefPtr promise = RemoveRequestPromise(requestId); + promise->MaybeReject(rv); + break; + } + + PCacheQueryParams params; + ToPCacheQueryParams(params, entry.mOptions); + + unused << mActor->SendMatch(requestId, request.SendAsRequest(), params); + break; + } + case OP_HAS: + unused << mActor->SendHas(requestId, entry.mKey); + break; + case OP_OPEN: + unused << mActor->SendOpen(requestId, entry.mKey); + break; + case OP_DELETE: + unused << mActor->SendDelete(requestId, entry.mKey); + break; + case OP_KEYS: + unused << mActor->SendKeys(requestId); + break; + default: + MOZ_ASSERT_UNREACHABLE("Unknown pending CacheStorage op."); + } + } + mPendingRequests.Clear(); +} + +RequestId +CacheStorage::AddRequestPromise(Promise* aPromise, ErrorResult& aRv) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + MOZ_ASSERT(aPromise); + MOZ_ASSERT(!mRequestPromises.Contains(aPromise)); + + // Register ourself as a promise handler so that the promise will hold us + // alive. This allows the client code to drop the ref to the CacheStorage + // object and just keep their promise. This is fairly common in promise + // chaining code. + aPromise->AppendNativeHandler(this); + + mRequestPromises.AppendElement(aPromise); + + // (Ab)use the promise pointer as our request ID. This is a fast, thread-safe + // way to get a unique ID for the promise to be resolved later. + return reinterpret_cast(aPromise); +} + +already_AddRefed +CacheStorage::RemoveRequestPromise(RequestId aRequestId) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorage); + MOZ_ASSERT(aRequestId != INVALID_REQUEST_ID); + + for (uint32_t i = 0; i < mRequestPromises.Length(); ++i) { + nsRefPtr& promise = mRequestPromises.ElementAt(i); + // To be safe, only cast promise pointers to our integer RequestId + // type and never cast an integer to a pointer. + if (aRequestId == reinterpret_cast(promise.get())) { + nsRefPtr ref; + ref.swap(promise); + mRequestPromises.RemoveElementAt(i); + return ref.forget(); + } + } + MOZ_ASSERT_UNREACHABLE("Received response without a matching promise!"); + return nullptr; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/CacheStorage.h b/dom/cache/CacheStorage.h new file mode 100644 index 0000000000..795f4b466d --- /dev/null +++ b/dom/cache/CacheStorage.h @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheStorage_h +#define mozilla_dom_cache_CacheStorage_h + +#include "mozilla/dom/CacheBinding.h" +#include "mozilla/dom/PromiseNativeHandler.h" +#include "mozilla/dom/cache/Types.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "nsISupportsImpl.h" +#include "nsTArray.h" +#include "nsWrapperCache.h" +#include "nsIIPCBackgroundChildCreateCallback.h" + +class nsIGlobalObject; + +namespace mozilla { + +class ErrorResult; + +namespace ipc { + class IProtocol; + class PrincipalInfo; +} + +namespace dom { + +class Promise; + +namespace workers { + class WorkerPrivate; +} + +namespace cache { + +class CacheChild; +class CacheStorageChild; +class Feature; +class PCacheRequest; +class PCacheResponseOrVoid; + +class CacheStorage MOZ_FINAL : public nsIIPCBackgroundChildCreateCallback + , public nsWrapperCache + , public TypeUtils + , public PromiseNativeHandler +{ + typedef mozilla::ipc::PBackgroundChild PBackgroundChild; + +public: + static already_AddRefed + CreateOnMainThread(Namespace aNamespace, nsIGlobalObject* aGlobal, + nsIPrincipal* aPrincipal, ErrorResult& aRv); + + static already_AddRefed + CreateOnWorker(Namespace aNamespace, nsIGlobalObject* aGlobal, + workers::WorkerPrivate* aWorkerPrivate, ErrorResult& aRv); + + // webidl interface methods + already_AddRefed Match(const RequestOrUSVString& aRequest, + const CacheQueryOptions& aOptions, + ErrorResult& aRv); + already_AddRefed Has(const nsAString& aKey, ErrorResult& aRv); + already_AddRefed Open(const nsAString& aKey, ErrorResult& aRv); + already_AddRefed Delete(const nsAString& aKey, ErrorResult& aRv); + already_AddRefed Keys(ErrorResult& aRv); + + // binding methods + static bool PrefEnabled(JSContext* aCx, JSObject* aObj); + + nsISupports* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aContext) MOZ_OVERRIDE; + + // nsIIPCbackgroundChildCreateCallback methods + virtual void ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE; + virtual void ActorFailed() MOZ_OVERRIDE; + + // Called when CacheStorageChild actor is being destroyed + void DestroyInternal(CacheStorageChild* aActor); + + // Methods forwarded from CacheStorageChild + void RecvMatchResponse(RequestId aRequestId, nsresult aRv, + const PCacheResponseOrVoid& aResponse); + void RecvHasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess); + void RecvOpenResponse(RequestId aRequestId, nsresult aRv, + CacheChild* aActor); + void RecvDeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess); + void RecvKeysResponse(RequestId aRequestId, nsresult aRv, + const nsTArray& aKeys); + + // TypeUtils methods + virtual nsIGlobalObject* GetGlobalObject() const MOZ_OVERRIDE; +#ifdef DEBUG + virtual void AssertOwningThread() const MOZ_OVERRIDE; +#endif + + // PromiseNativeHandler methods + virtual void + ResolvedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE; + + virtual void + RejectedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE; + +private: + CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo, Feature* aFeature); + ~CacheStorage(); + + void MaybeRunPendingRequests(); + + RequestId AddRequestPromise(Promise* aPromise, ErrorResult& aRv); + already_AddRefed RemoveRequestPromise(RequestId aRequestId); + + // Would like to use CacheInitData here, but we cannot because + // its an IPC struct which breaks webidl by including windows.h. + const Namespace mNamespace; + nsCOMPtr mGlobal; + UniquePtr mPrincipalInfo; + nsRefPtr mFeature; + CacheStorageChild* mActor; + nsTArray> mRequestPromises; + + enum Op + { + OP_MATCH, + OP_HAS, + OP_OPEN, + OP_DELETE, + OP_KEYS + }; + + struct Entry + { + RequestId mRequestId; + Op mOp; + // Would prefer to use PCacheRequest/PCacheCacheQueryOptions, but can't + // because they introduce a header dependency on windows.h which + // breaks the bindings build. + nsRefPtr mRequest; + CacheQueryOptions mOptions; + // It would also be nice to union the key with the match args above, + // but VS2013 doesn't like these types in unions because of copy + // constructors. + nsString mKey; + }; + + nsTArray mPendingRequests; + bool mFailedActor; + +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(CacheStorage, + nsIIPCBackgroundChildCreateCallback) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheStorage_h diff --git a/dom/cache/CacheStorageChild.cpp b/dom/cache/CacheStorageChild.cpp new file mode 100644 index 0000000000..54d1265f23 --- /dev/null +++ b/dom/cache/CacheStorageChild.cpp @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheStorageChild.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/cache/CacheChild.h" +#include "mozilla/dom/cache/CacheStorage.h" +#include "mozilla/dom/cache/StreamUtils.h" + +namespace mozilla { +namespace dom { +namespace cache { + +// declared in ActorUtils.h +void +DeallocPCacheStorageChild(PCacheStorageChild* aActor) +{ + delete aActor; +} + +CacheStorageChild::CacheStorageChild(CacheStorage* aListener, Feature* aFeature) + : mListener(aListener) +{ + MOZ_COUNT_CTOR(cache::CacheStorageChild); + MOZ_ASSERT(mListener); + + SetFeature(aFeature); +} + +CacheStorageChild::~CacheStorageChild() +{ + MOZ_COUNT_DTOR(cache::CacheStorageChild); + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + MOZ_ASSERT(!mListener); +} + +void +CacheStorageChild::ClearListener() +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + MOZ_ASSERT(mListener); + mListener = nullptr; +} + +void +CacheStorageChild::StartDestroy() +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + + nsRefPtr listener = mListener; + + // StartDestroy() can get called from either CacheStorage or the Feature. + // Theoretically we can get double called if the right race happens. Handle + // that by just ignoring the second StartDestroy() call. + if (!listener) { + return; + } + + listener->DestroyInternal(this); + + // CacheStorage listener should call ClearListener() in DestroyInternal() + MOZ_ASSERT(!mListener); + + // Start actor destruction from parent process + unused << SendTeardown(); +} + +void +CacheStorageChild::ActorDestroy(ActorDestroyReason aReason) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + nsRefPtr listener = mListener; + if (listener) { + listener->DestroyInternal(this); + // CacheStorage listener should call ClearListener() in DestroyInternal() + MOZ_ASSERT(!mListener); + } + + RemoveFeature(); +} + +bool +CacheStorageChild::RecvMatchResponse(const RequestId& aRequestId, + const nsresult& aRv, + const PCacheResponseOrVoid& aResponseOrVoid) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + + AddFeatureToStreamChild(aResponseOrVoid, GetFeature()); + + nsRefPtr listener = mListener; + if (!listener) { + StartDestroyStreamChild(aResponseOrVoid); + return true; + } + + listener->RecvMatchResponse(aRequestId, aRv, aResponseOrVoid); + + return true; +} + +bool +CacheStorageChild::RecvHasResponse(const RequestId& aRequestId, + const nsresult& aRv, + const bool& aSuccess) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + nsRefPtr listener = mListener; + if (listener) { + listener->RecvHasResponse(aRequestId, aRv, aSuccess); + } + return true; +} + +bool +CacheStorageChild::RecvOpenResponse(const RequestId& aRequestId, + const nsresult& aRv, + PCacheChild* aActor) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + + nsRefPtr listener = mListener; + if (!listener || FeatureNotified()) { + if (aActor) { + unused << aActor->SendTeardown(); + } + return true; + } + + CacheChild* cacheChild = static_cast(aActor); + + // Since FeatureNotified() returned false above, we are guaranteed that + // the feature won't try to shutdown the actor until after we create the + // Cache DOM object in the listener's RecvOpenResponse() method. This + // is important because StartShutdown() expects a Cache object listener. + cacheChild->SetFeature(GetFeature()); + + listener->RecvOpenResponse(aRequestId, aRv, cacheChild); + return true; +} + +bool +CacheStorageChild::RecvDeleteResponse(const RequestId& aRequestId, + const nsresult& aRv, + const bool& aResult) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + nsRefPtr listener = mListener; + if (listener) { + listener->RecvDeleteResponse(aRequestId, aRv, aResult); + } + return true; +} + +bool +CacheStorageChild::RecvKeysResponse(const RequestId& aRequestId, + const nsresult& aRv, + nsTArray&& aKeys) +{ + NS_ASSERT_OWNINGTHREAD(CacheStorageChild); + nsRefPtr listener = mListener; + if (listener) { + listener->RecvKeysResponse(aRequestId, aRv, aKeys); + } + return true; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/CacheStorageChild.h b/dom/cache/CacheStorageChild.h new file mode 100644 index 0000000000..f8e35f3490 --- /dev/null +++ b/dom/cache/CacheStorageChild.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheStorageChild_h +#define mozilla_dom_cache_CacheStorageChild_h + +#include "mozilla/dom/cache/ActorChild.h" +#include "mozilla/dom/cache/Types.h" +#include "mozilla/dom/cache/PCacheStorageChild.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class CacheStorage; +class PCacheChild; +class Feature; + +class CacheStorageChild MOZ_FINAL : public PCacheStorageChild + , public ActorChild +{ +public: + CacheStorageChild(CacheStorage* aListener, Feature* aFeature); + ~CacheStorageChild(); + + // Must be called by the associated CacheStorage listener in its + // ActorDestroy() method. Also, CacheStorage must Send__delete__() the + // actor in its destructor to trigger ActorDestroy() if it has not been + // called yet. + void ClearListener(); + + // ActorChild methods + + // Synchronously call ActorDestroy on our CacheStorage listener and then start + // the actor destruction asynchronously from the parent-side. + virtual void StartDestroy() MOZ_OVERRIDE; + +private: + // PCacheStorageChild methods + virtual void ActorDestroy(ActorDestroyReason aReason) MOZ_OVERRIDE; + virtual bool RecvMatchResponse(const RequestId& aRequestId, + const nsresult& aRv, + const PCacheResponseOrVoid& response) MOZ_OVERRIDE; + virtual bool RecvHasResponse(const cache::RequestId& aRequestId, + const nsresult& aRv, + const bool& aSuccess) MOZ_OVERRIDE; + virtual bool RecvOpenResponse(const cache::RequestId& aRequestId, + const nsresult& aRv, + PCacheChild* aActor) MOZ_OVERRIDE; + virtual bool RecvDeleteResponse(const cache::RequestId& aRequestId, + const nsresult& aRv, + const bool& aResult) MOZ_OVERRIDE; + virtual bool RecvKeysResponse(const cache::RequestId& aRequestId, + const nsresult& aRv, + nsTArray&& aKeys) MOZ_OVERRIDE; + + // Use a weak ref so actor does not hold DOM object alive past content use. + // The CacheStorage object must call ClearListener() to null this before its + // destroyed. + CacheStorage* MOZ_NON_OWNING_REF mListener; + + NS_DECL_OWNINGTHREAD +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheStorageChild_h diff --git a/dom/cache/CacheStorageParent.cpp b/dom/cache/CacheStorageParent.cpp new file mode 100644 index 0000000000..3faa63d8be --- /dev/null +++ b/dom/cache/CacheStorageParent.cpp @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheStorageParent.h" + +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/cache/ActorUtils.h" +#include "mozilla/dom/cache/AutoUtils.h" +#include "mozilla/dom/cache/CacheParent.h" +#include "mozilla/dom/cache/CacheStreamControlParent.h" +#include "mozilla/dom/cache/Manager.h" +#include "mozilla/dom/cache/ManagerId.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/dom/cache/SavedTypes.h" +#include "mozilla/dom/cache/StreamList.h" +#include "mozilla/ipc/PBackgroundParent.h" +#include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/ipc/PFileDescriptorSetParent.h" +#include "mozilla/DebugOnly.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::ipc::PBackgroundParent; +using mozilla::ipc::PFileDescriptorSetParent; +using mozilla::ipc::PrincipalInfo; + +// declared in ActorUtils.h +PCacheStorageParent* +AllocPCacheStorageParent(PBackgroundParent* aManagingActor, + Namespace aNamespace, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo) +{ + return new CacheStorageParent(aManagingActor, aNamespace, aPrincipalInfo); +} + +// declared in ActorUtils.h +void +DeallocPCacheStorageParent(PCacheStorageParent* aActor) +{ + delete aActor; +} + +CacheStorageParent::CacheStorageParent(PBackgroundParent* aManagingActor, + Namespace aNamespace, + const PrincipalInfo& aPrincipalInfo) + : mNamespace(aNamespace) + , mVerifiedStatus(NS_OK) +{ + MOZ_COUNT_CTOR(cache::CacheStorageParent); + MOZ_ASSERT(aManagingActor); + + // Start the async principal verification process immediately. + mVerifier = PrincipalVerifier::CreateAndDispatch(this, aManagingActor, + aPrincipalInfo); + MOZ_ASSERT(mVerifier); +} + +CacheStorageParent::~CacheStorageParent() +{ + MOZ_COUNT_DTOR(cache::CacheStorageParent); + MOZ_ASSERT(!mVerifier); + MOZ_ASSERT(!mManager); +} + +void +CacheStorageParent::ActorDestroy(ActorDestroyReason aReason) +{ + if (mVerifier) { + mVerifier->ClearListener(); + mVerifier = nullptr; + } + + if (mManager) { + MOZ_ASSERT(!mActiveRequests.IsEmpty()); + mManager->RemoveListener(this); + mManager = nullptr; + } +} + +bool +CacheStorageParent::RecvTeardown() +{ + if (!Send__delete__(this)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to delete actor."); + } + return true; +} + +bool +CacheStorageParent::RecvMatch(const RequestId& aRequestId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) +{ + if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) { + if (!SendMatchResponse(aRequestId, mVerifiedStatus, void_t())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Match response."); + } + return true; + } + + // queue requests if we are still waiting for principal verification + if (!mManagerId) { + Entry* entry = mPendingRequests.AppendElement(); + entry->mOp = OP_MATCH; + entry->mRequestId = aRequestId; + entry->mRequest = aRequest; + entry->mParams = aParams; + return true; + } + + nsRefPtr manager; + nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager)); + if (NS_WARN_IF(NS_FAILED(rv))) { + if (!SendMatchResponse(aRequestId, rv, void_t())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Match response."); + } + return true; + } + + manager->StorageMatch(this, aRequestId, mNamespace, aRequest, + aParams); + + return true; +} + +bool +CacheStorageParent::RecvHas(const RequestId& aRequestId, const nsString& aKey) +{ + if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) { + if (!SendHasResponse(aRequestId, mVerifiedStatus, false)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Has response."); + } + return true; + } + + // queue requests if we are still waiting for principal verification + if (!mManagerId) { + Entry* entry = mPendingRequests.AppendElement(); + entry->mOp = OP_HAS; + entry->mRequestId = aRequestId; + entry->mKey = aKey; + return true; + } + + nsRefPtr manager; + nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager)); + if (NS_WARN_IF(NS_FAILED(rv))) { + if (!SendHasResponse(aRequestId, rv, false)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Has response."); + } + return true; + } + + manager->StorageHas(this, aRequestId, mNamespace, aKey); + + return true; +} + +bool +CacheStorageParent::RecvOpen(const RequestId& aRequestId, const nsString& aKey) +{ + if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) { + if (!SendOpenResponse(aRequestId, mVerifiedStatus, nullptr)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Open response."); + } + return true; + } + + // queue requests if we are still waiting for principal verification + if (!mManagerId) { + Entry* entry = mPendingRequests.AppendElement(); + entry->mOp = OP_OPEN; + entry->mRequestId = aRequestId; + entry->mKey = aKey; + return true; + } + + nsRefPtr manager; + nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager)); + if (NS_WARN_IF(NS_FAILED(rv))) { + if (!SendOpenResponse(aRequestId, rv, nullptr)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Open response."); + } + return true; + } + + manager->StorageOpen(this, aRequestId, mNamespace, aKey); + + return true; +} + +bool +CacheStorageParent::RecvDelete(const RequestId& aRequestId, + const nsString& aKey) +{ + if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) { + if (!SendDeleteResponse(aRequestId, mVerifiedStatus, false)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Delete response."); + } + return true; + } + + // queue requests if we are still waiting for principal verification + if (!mManagerId) { + Entry* entry = mPendingRequests.AppendElement(); + entry->mOp = OP_DELETE; + entry->mRequestId = aRequestId; + entry->mKey = aKey; + return true; + } + + nsRefPtr manager; + nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager)); + if (NS_WARN_IF(NS_FAILED(rv))) { + if (!SendDeleteResponse(aRequestId, rv, false)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Delete response."); + } + return true; + } + + manager->StorageDelete(this, aRequestId, mNamespace, aKey); + + return true; +} + +bool +CacheStorageParent::RecvKeys(const RequestId& aRequestId) +{ + if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) { + if (!SendKeysResponse(aRequestId, mVerifiedStatus, nsTArray())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Keys response."); + } + } + + // queue requests if we are still waiting for principal verification + if (!mManagerId) { + Entry* entry = mPendingRequests.AppendElement(); + entry->mOp = OP_DELETE; + entry->mRequestId = aRequestId; + return true; + } + + nsRefPtr manager; + nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager)); + if (NS_WARN_IF(NS_FAILED(rv))) { + if (!SendKeysResponse(aRequestId, rv, nsTArray())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Keys response."); + } + return true; + } + + manager->StorageKeys(this, aRequestId, mNamespace); + + return true; +} + +void +CacheStorageParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId) +{ + MOZ_ASSERT(mVerifier); + MOZ_ASSERT(!mManagerId); + MOZ_ASSERT(!mManager); + MOZ_ASSERT(NS_SUCCEEDED(mVerifiedStatus)); + + if (NS_WARN_IF(NS_FAILED(aRv))) { + mVerifiedStatus = aRv; + } + + mManagerId = aManagerId; + mVerifier->ClearListener(); + mVerifier = nullptr; + + RetryPendingRequests(); +} + +void +CacheStorageParent::OnStorageMatch(RequestId aRequestId, nsresult aRv, + const SavedResponse* aSavedResponse, + StreamList* aStreamList) +{ + PCacheResponseOrVoid responseOrVoid; + + ReleaseManager(aRequestId); + + AutoParentResponseOrVoid response(Manager()); + + // no match + if (NS_FAILED(aRv) || !aSavedResponse) { + if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Match response."); + } + return; + } + + if (aSavedResponse) { + response.Add(*aSavedResponse, aStreamList); + } + + if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Match response."); + } +} + +void +CacheStorageParent::OnStorageHas(RequestId aRequestId, nsresult aRv, + bool aCacheFound) +{ + ReleaseManager(aRequestId); + if (!SendHasResponse(aRequestId, aRv, aCacheFound)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Has response."); + } +} + +void +CacheStorageParent::OnStorageOpen(RequestId aRequestId, nsresult aRv, + CacheId aCacheId) +{ + if (NS_FAILED(aRv)) { + ReleaseManager(aRequestId); + if (!SendOpenResponse(aRequestId, aRv, nullptr)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Open response."); + } + return; + } + + MOZ_ASSERT(mManager); + CacheParent* actor = new CacheParent(mManager, aCacheId); + + ReleaseManager(aRequestId); + + PCacheParent* base = Manager()->SendPCacheConstructor(actor); + actor = static_cast(base); + if (!SendOpenResponse(aRequestId, aRv, actor)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Open response."); + } +} + +void +CacheStorageParent::OnStorageDelete(RequestId aRequestId, nsresult aRv, + bool aCacheDeleted) +{ + ReleaseManager(aRequestId); + if (!SendDeleteResponse(aRequestId, aRv, aCacheDeleted)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Delete response."); + } +} + +void +CacheStorageParent::OnStorageKeys(RequestId aRequestId, nsresult aRv, + const nsTArray& aKeys) +{ + ReleaseManager(aRequestId); + if (!SendKeysResponse(aRequestId, aRv, aKeys)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("CacheStorage failed to send Keys response."); + } +} + +void +CacheStorageParent::RetryPendingRequests() +{ + MOZ_ASSERT(mManagerId || NS_FAILED(mVerifiedStatus)); + for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) { + const Entry& entry = mPendingRequests[i]; + switch(entry.mOp) { + case OP_MATCH: + RecvMatch(entry.mRequestId, entry.mRequest, entry.mParams); + break; + case OP_HAS: + RecvHas(entry.mRequestId, entry.mKey); + break; + case OP_OPEN: + RecvOpen(entry.mRequestId, entry.mKey); + break; + case OP_DELETE: + RecvDelete(entry.mRequestId, entry.mKey); + break; + case OP_KEYS: + RecvKeys(entry.mRequestId); + break; + default: + MOZ_ASSERT_UNREACHABLE("Pending request within unknown op"); + } + } + mPendingRequests.Clear(); + mPendingRequests.Compact(); +} + +nsresult +CacheStorageParent::RequestManager(RequestId aRequestId, + cache::Manager** aManagerOut) +{ + MOZ_ASSERT(!mActiveRequests.Contains(aRequestId)); + nsRefPtr ref = mManager; + if (!ref) { + MOZ_ASSERT(mActiveRequests.IsEmpty()); + nsresult rv = cache::Manager::GetOrCreate(mManagerId, getter_AddRefs(ref)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + mManager = ref; + } + mActiveRequests.AppendElement(aRequestId); + ref.forget(aManagerOut); + return NS_OK; +} + +void +CacheStorageParent::ReleaseManager(RequestId aRequestId) +{ + // Note that if the child process dies we also clean up the mManager in + // ActorDestroy(). There is no race with this method, however, because + // ActorDestroy removes this object from the Manager's listener list. + // Therefore ReleaseManager() should never be called after ActorDestroy() + // runs. + MOZ_ASSERT(mManager); + MOZ_ASSERT(!mActiveRequests.IsEmpty()); + + MOZ_ALWAYS_TRUE(mActiveRequests.RemoveElement(aRequestId)); + + if (mActiveRequests.IsEmpty()) { + mManager->RemoveListener(this); + mManager = nullptr; + } +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/CacheStorageParent.h b/dom/cache/CacheStorageParent.h new file mode 100644 index 0000000000..fde040a199 --- /dev/null +++ b/dom/cache/CacheStorageParent.h @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheStorageParent_h +#define mozilla_dom_cache_CacheStorageParent_h + +#include "mozilla/dom/cache/CacheInitData.h" +#include "mozilla/dom/cache/PCacheStorageParent.h" +#include "mozilla/dom/cache/Manager.h" +#include "mozilla/dom/cache/PrincipalVerifier.h" +#include "mozilla/dom/cache/Types.h" + +template class nsRefPtr; + +namespace mozilla { +namespace dom { +namespace cache { + +class CacheStreamControlParent; +class ManagerId; + +class CacheStorageParent MOZ_FINAL : public PCacheStorageParent + , public PrincipalVerifier::Listener + , public Manager::Listener +{ +public: + CacheStorageParent(PBackgroundParent* aManagingActor, Namespace aNamespace, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo); + virtual ~CacheStorageParent(); + +private: + // PCacheStorageParent methods + virtual void ActorDestroy(ActorDestroyReason aReason) MOZ_OVERRIDE; + virtual bool RecvTeardown() MOZ_OVERRIDE; + virtual bool RecvMatch(const RequestId& aRequestId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) MOZ_OVERRIDE; + virtual bool RecvHas(const RequestId& aRequestId, + const nsString& aKey) MOZ_OVERRIDE; + virtual bool RecvOpen(const RequestId& aRequestId, + const nsString& aKey) MOZ_OVERRIDE; + virtual bool RecvDelete(const RequestId& aRequestId, + const nsString& aKey) MOZ_OVERRIDE; + virtual bool RecvKeys(const RequestId& aRequestId) MOZ_OVERRIDE; + + // PrincipalVerifier::Listener methods + virtual void OnPrincipalVerified(nsresult aRv, + ManagerId* aManagerId) MOZ_OVERRIDE; + + // Manager::Listener methods + virtual void OnStorageMatch(RequestId aRequestId, nsresult aRv, + const SavedResponse* aResponse, + StreamList* aStreamList) MOZ_OVERRIDE; + virtual void OnStorageHas(RequestId aRequestId, nsresult aRv, + bool aCacheFound) MOZ_OVERRIDE; + virtual void OnStorageOpen(RequestId aRequestId, nsresult aRv, + CacheId aCacheId) MOZ_OVERRIDE; + virtual void OnStorageDelete(RequestId aRequestId, nsresult aRv, + bool aCacheDeleted) MOZ_OVERRIDE; + virtual void OnStorageKeys(RequestId aRequestId, nsresult aRv, + const nsTArray& aKeys) MOZ_OVERRIDE; + + CacheStreamControlParent* + SerializeReadStream(CacheStreamControlParent *aStreamControl, const nsID& aId, + StreamList* aStreamList, + PCacheReadStream* aReadStreamOut); + + void RetryPendingRequests(); + + nsresult RequestManager(RequestId aRequestId, cache::Manager** aManagerOut); + void ReleaseManager(RequestId aRequestId); + + const Namespace mNamespace; + nsRefPtr mVerifier; + nsresult mVerifiedStatus; + nsRefPtr mManagerId; + nsRefPtr mManager; + + enum Op + { + OP_MATCH, + OP_HAS, + OP_OPEN, + OP_DELETE, + OP_KEYS + }; + + struct Entry + { + Op mOp; + RequestId mRequestId; + nsString mKey; + PCacheRequest mRequest; + PCacheQueryParams mParams; + }; + + nsTArray mPendingRequests; + nsTArray mActiveRequests; +}; + +} // namesapce cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheStorageParent_h diff --git a/dom/cache/CacheStreamControlChild.cpp b/dom/cache/CacheStreamControlChild.cpp new file mode 100644 index 0000000000..c0cd043378 --- /dev/null +++ b/dom/cache/CacheStreamControlChild.cpp @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheStreamControlChild.h" + +#include "mozilla/DebugOnly.h" +#include "mozilla/unused.h" +#include "mozilla/dom/cache/ActorUtils.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "nsISupportsImpl.h" + +namespace mozilla { +namespace dom { +namespace cache { + +// declared in ActorUtils.h +PCacheStreamControlChild* +AllocPCacheStreamControlChild() +{ + return new CacheStreamControlChild(); +} + +// declared in ActorUtils.h +void +DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor) +{ + delete aActor; +} + +CacheStreamControlChild::CacheStreamControlChild() + : mDestroyStarted(false) +{ + MOZ_COUNT_CTOR(cache::CacheStreamControlChild); +} + +CacheStreamControlChild::~CacheStreamControlChild() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + MOZ_COUNT_DTOR(cache::CacheStreamControlChild); +} + +void +CacheStreamControlChild::AddListener(ReadStream* aListener) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + MOZ_ASSERT(aListener); + MOZ_ASSERT(!mListeners.Contains(aListener)); + mListeners.AppendElement(aListener); +} + +void +CacheStreamControlChild::RemoveListener(ReadStream* aListener) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + MOZ_ASSERT(aListener); + MOZ_ALWAYS_TRUE(mListeners.RemoveElement(aListener)); +} + +void +CacheStreamControlChild::NoteClosed(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + unused << SendNoteClosed(aId); +} + +void +CacheStreamControlChild::StartDestroy() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + // This can get called twice under some circumstances. For example, if the + // actor is added to a Feature that has already been notified and the Cache + // actor has no mListener. + if (mDestroyStarted) { + return; + } + mDestroyStarted = true; + + // Begin shutting down all streams. This is the same as if the parent had + // asked us to shutdown. So simulate the CloseAll IPC message. + RecvCloseAll(); +} + +void +CacheStreamControlChild::ActorDestroy(ActorDestroyReason aReason) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + // Note, we cannot trigger IPC traffic here. So use + // CloseStreamWithoutReporting(). + ReadStreamList::ForwardIterator iter(mListeners); + while (iter.HasMore()) { + nsRefPtr stream = iter.GetNext(); + stream->CloseStreamWithoutReporting(); + } + mListeners.Clear(); + + RemoveFeature(); +} + +bool +CacheStreamControlChild::RecvClose(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + DebugOnly closedCount = 0; + + ReadStreamList::ForwardIterator iter(mListeners); + while (iter.HasMore()) { + nsRefPtr stream = iter.GetNext(); + // note, multiple streams may exist for same ID + if (stream->MatchId(aId)) { + stream->CloseStream(); + closedCount += 1; + } + } + + MOZ_ASSERT(closedCount > 0); + + return true; +} + +bool +CacheStreamControlChild::RecvCloseAll() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); + ReadStreamList::ForwardIterator iter(mListeners); + while (iter.HasMore()) { + nsRefPtr stream = iter.GetNext(); + stream->CloseStream(); + } + return true; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/CacheStreamControlChild.h b/dom/cache/CacheStreamControlChild.h new file mode 100644 index 0000000000..63efdc1b79 --- /dev/null +++ b/dom/cache/CacheStreamControlChild.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheStreamControlChild_h +#define mozilla_dom_cache_CacheStreamControlChild_h + +#include "mozilla/dom/cache/ActorChild.h" +#include "mozilla/dom/cache/PCacheStreamControlChild.h" +#include "nsTObserverArray.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class ReadStream; + +class CacheStreamControlChild MOZ_FINAL : public PCacheStreamControlChild + , public ActorChild +{ +public: + CacheStreamControlChild(); + ~CacheStreamControlChild(); + + void AddListener(ReadStream* aListener); + void RemoveListener(ReadStream* aListener); + + void NoteClosed(const nsID& aId); + + // ActorChild methods + virtual void StartDestroy() MOZ_OVERRIDE; + +private: + // PCacheStreamControlChild methods + virtual void ActorDestroy(ActorDestroyReason aReason) MOZ_OVERRIDE; + virtual bool RecvClose(const nsID& aId) MOZ_OVERRIDE; + virtual bool RecvCloseAll() MOZ_OVERRIDE; + + typedef nsTObserverArray ReadStreamList; + ReadStreamList mListeners; + + bool mDestroyStarted; + + NS_DECL_OWNINGTHREAD +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheStreamControlChild_h diff --git a/dom/cache/CacheStreamControlParent.cpp b/dom/cache/CacheStreamControlParent.cpp new file mode 100644 index 0000000000..e39790e43c --- /dev/null +++ b/dom/cache/CacheStreamControlParent.cpp @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/CacheStreamControlParent.h" + +#include "mozilla/DebugOnly.h" +#include "mozilla/unused.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/dom/cache/StreamList.h" +#include "nsISupportsImpl.h" + +namespace mozilla { +namespace dom { +namespace cache { + +// declared in ActorUtils.h +void +DeallocPCacheStreamControlParent(PCacheStreamControlParent* aActor) +{ + delete aActor; +} + +CacheStreamControlParent::CacheStreamControlParent() +{ + MOZ_COUNT_CTOR(cache::CacheStreamControlParent); +} + +CacheStreamControlParent::~CacheStreamControlParent() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + MOZ_ASSERT(!mStreamList); + MOZ_COUNT_DTOR(cache::CacheStreamControlParent); +} + +void +CacheStreamControlParent::AddListener(ReadStream* aListener) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + MOZ_ASSERT(aListener); + MOZ_ASSERT(!mListeners.Contains(aListener)); + mListeners.AppendElement(aListener); +} + +void +CacheStreamControlParent::RemoveListener(ReadStream* aListener) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + MOZ_ASSERT(aListener); + DebugOnly removed = mListeners.RemoveElement(aListener); + MOZ_ASSERT(removed); +} + +void +CacheStreamControlParent::ActorDestroy(ActorDestroyReason aReason) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + MOZ_ASSERT(mStreamList); + ReadStreamList::ForwardIterator iter(mListeners); + while (iter.HasMore()) { + nsRefPtr stream = iter.GetNext(); + stream->CloseStreamWithoutReporting(); + } + mStreamList->RemoveStreamControl(this); + mStreamList->NoteClosedAll(); + mStreamList = nullptr; +} + +bool +CacheStreamControlParent::RecvNoteClosed(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + MOZ_ASSERT(mStreamList); + mStreamList->NoteClosed(aId); + return true; +} + +void +CacheStreamControlParent::SetStreamList(StreamList* aStreamList) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + MOZ_ASSERT(!mStreamList); + mStreamList = aStreamList; +} + +void +CacheStreamControlParent::Close(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + NotifyClose(aId); + unused << SendClose(aId); +} + +void +CacheStreamControlParent::CloseAll() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + NotifyCloseAll(); + unused << SendCloseAll(); +} + +void +CacheStreamControlParent::Shutdown() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + if (!Send__delete__(this)) { + // child process is gone, allow actor to be destroyed normally + NS_WARNING("Cache failed to delete stream actor."); + return; + } +} + +void +CacheStreamControlParent::NotifyClose(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + DebugOnly closedCount = 0; + + ReadStreamList::ForwardIterator iter(mListeners); + while (iter.HasMore()) { + nsRefPtr stream = iter.GetNext(); + // note, multiple streams may exist for same ID + if (stream->MatchId(aId)) { + stream->CloseStream(); + closedCount += 1; + } + } + + MOZ_ASSERT(closedCount > 0); +} + +void +CacheStreamControlParent::NotifyCloseAll() +{ + NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); + ReadStreamList::ForwardIterator iter(mListeners); + while (iter.HasMore()) { + nsRefPtr stream = iter.GetNext(); + stream->CloseStream(); + } +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/CacheStreamControlParent.h b/dom/cache/CacheStreamControlParent.h new file mode 100644 index 0000000000..b45992b86c --- /dev/null +++ b/dom/cache/CacheStreamControlParent.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_CacheStreamControlParent_h +#define mozilla_dom_cache_CacheStreamControlParent_h + +#include "mozilla/dom/cache/PCacheStreamControlParent.h" +#include "nsTObserverArray.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class ReadStream; +class StreamList; + +class CacheStreamControlParent : public PCacheStreamControlParent +{ +public: + CacheStreamControlParent(); + ~CacheStreamControlParent(); + + void AddListener(ReadStream* aListener); + void RemoveListener(ReadStream* aListener); + + void SetStreamList(StreamList* aStreamList); + void Close(const nsID& aId); + void CloseAll(); + void Shutdown(); + + // PCacheStreamControlParent methods + virtual void ActorDestroy(ActorDestroyReason aReason) MOZ_OVERRIDE; + virtual bool RecvNoteClosed(const nsID& aId) MOZ_OVERRIDE; + +private: + void NotifyClose(const nsID& aId); + void NotifyCloseAll(); + + // Cycle with StreamList via a weak-ref to us. Cleanup occurs when the actor + // is deleted by the PBackground manager. ActorDestroy() then calls + // StreamList::RemoveStreamControl() to clear the weak ref. + nsRefPtr mStreamList; + + typedef nsTObserverArray ReadStreamList; + ReadStreamList mListeners; + + NS_DECL_OWNINGTHREAD +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_CacheStreamControlParent_h diff --git a/dom/cache/Context.cpp b/dom/cache/Context.cpp new file mode 100644 index 0000000000..6d50582d0e --- /dev/null +++ b/dom/cache/Context.cpp @@ -0,0 +1,630 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/Context.h" + +#include "mozilla/DebugOnly.h" +#include "mozilla/dom/cache/Action.h" +#include "mozilla/dom/cache/Manager.h" +#include "mozilla/dom/cache/ManagerId.h" +#include "mozilla/dom/quota/OriginOrPatternString.h" +#include "mozilla/dom/quota/QuotaManager.h" +#include "nsIFile.h" +#include "nsIPrincipal.h" +#include "nsIRunnable.h" +#include "nsThreadUtils.h" + +namespace { + +using mozilla::dom::Nullable; +using mozilla::dom::cache::QuotaInfo; +using mozilla::dom::quota::OriginOrPatternString; +using mozilla::dom::quota::QuotaManager; +using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT; +using mozilla::dom::quota::PersistenceType; + +// Executed when the context is destroyed to release our lock on the +// QuotaManager. +class QuotaReleaseRunnable MOZ_FINAL : public nsRunnable +{ +public: + QuotaReleaseRunnable(const QuotaInfo& aQuotaInfo, const nsACString& aQuotaId) + : mQuotaInfo(aQuotaInfo) + , mQuotaId(aQuotaId) + { } + + NS_IMETHOD Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + QuotaManager* qm = QuotaManager::Get(); + MOZ_ASSERT(qm); + qm->AllowNextSynchronizedOp(OriginOrPatternString::FromOrigin(mQuotaInfo.mOrigin), + Nullable(PERSISTENCE_TYPE_DEFAULT), + mQuotaId); + return NS_OK; + } + +private: + ~QuotaReleaseRunnable() { } + + const QuotaInfo mQuotaInfo; + const nsCString mQuotaId; +}; + +} // anonymous namespace + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::DebugOnly; +using mozilla::dom::quota::OriginOrPatternString; +using mozilla::dom::quota::QuotaManager; +using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT; +using mozilla::dom::quota::PersistenceType; + +// Executed to perform the complicated dance of steps necessary to initialize +// the QuotaManager. This must be performed for each origin before any disk +// IO occurrs. +class Context::QuotaInitRunnable MOZ_FINAL : public nsIRunnable + , public Action::Resolver +{ +public: + QuotaInitRunnable(Context* aContext, + Manager* aManager, + const nsACString& aQuotaId, + Action* aQuotaIOThreadAction) + : mContext(aContext) + , mManager(aManager) + , mQuotaId(aQuotaId) + , mQuotaIOThreadAction(aQuotaIOThreadAction) + , mInitiatingThread(NS_GetCurrentThread()) + , mState(STATE_INIT) + , mResult(NS_OK) + { + MOZ_ASSERT(mContext); + MOZ_ASSERT(mManager); + MOZ_ASSERT(mInitiatingThread); + } + + nsresult Dispatch() + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + MOZ_ASSERT(mState == STATE_INIT); + + mState = STATE_CALL_WAIT_FOR_OPEN_ALLOWED; + nsresult rv = NS_DispatchToMainThread(this, nsIThread::DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + mState = STATE_COMPLETE; + Clear(); + } + return rv; + } + + virtual void Resolve(nsresult aRv) MOZ_OVERRIDE + { + // Depending on the error or success path, this can run on either the + // main thread or the QuotaManager IO thread. The IO thread is an + // idle thread which may be destroyed and recreated, so its hard to + // assert on. + MOZ_ASSERT(mState == STATE_RUNNING || NS_FAILED(aRv)); + + mResult = aRv; + mState = STATE_COMPLETING; + + nsresult rv = mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + // Shutdown must be delayed until all Contexts are destroyed. Crash for + // this invariant violation. + MOZ_CRASH("Failed to dispatch QuotaInitRunnable to initiating thread."); + } + } + +private: + ~QuotaInitRunnable() + { + MOZ_ASSERT(mState == STATE_COMPLETE); + MOZ_ASSERT(!mContext); + MOZ_ASSERT(!mQuotaIOThreadAction); + } + + enum State + { + STATE_INIT, + STATE_CALL_WAIT_FOR_OPEN_ALLOWED, + STATE_WAIT_FOR_OPEN_ALLOWED, + STATE_ENSURE_ORIGIN_INITIALIZED, + STATE_RUNNING, + STATE_COMPLETING, + STATE_COMPLETE + }; + + void Clear() + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + MOZ_ASSERT(mContext); + mContext = nullptr; + mManager = nullptr; + mQuotaIOThreadAction = nullptr; + } + + nsRefPtr mContext; + nsRefPtr mManager; + const nsCString mQuotaId; + nsRefPtr mQuotaIOThreadAction; + nsCOMPtr mInitiatingThread; + State mState; + nsresult mResult; + QuotaInfo mQuotaInfo; + +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIRUNNABLE +}; + +NS_IMPL_ISUPPORTS_INHERITED(mozilla::dom::cache::Context::QuotaInitRunnable, + Action::Resolver, nsIRunnable); + +// The QuotaManager init state machine is represented in the following diagram: +// +// +---------------+ +// | Start | Resolve(error) +// | (Orig Thread) +---------------------+ +// +-------+-------+ | +// | | +// +----------v-----------+ | +// |CallWaitForOpenAllowed| Resolve(error) | +// | (Main Thread) +-----------------+ +// +----------+-----------+ | +// | | +// +--------v---------+ | +// |WaitForOpenAllowed| Resolve(error) | +// | (Main Thread) +-------------------+ +// +--------+---------+ | +// | | +// +----------v------------+ | +// |EnsureOriginInitialized| Resolve(error) | +// | (Quota IO Thread) +----------------+ +// +----------+------------+ | +// | | +// +---------v---------+ +------v------+ +// | Running | Resolve() | Completing | +// | (Quota IO Thread) +------------>(Orig Thread)| +// +-------------------+ +------+------+ +// | +// +-----v----+ +// | Complete | +// +----------+ +// +// The initialization process proceeds through the main states. If an error +// occurs, then we transition back to Completing state back on the original +// thread. +NS_IMETHODIMP +Context::QuotaInitRunnable::Run() +{ + // May run on different threads depending on the state. See individual + // state cases for thread assertions. + + switch(mState) { + // ----------------------------------- + case STATE_CALL_WAIT_FOR_OPEN_ALLOWED: + { + MOZ_ASSERT(NS_IsMainThread()); + QuotaManager* qm = QuotaManager::GetOrCreate(); + if (!qm) { + Resolve(NS_ERROR_FAILURE); + return NS_OK; + } + + nsRefPtr managerId = mManager->GetManagerId(); + nsCOMPtr principal = managerId->Principal(); + nsresult rv = qm->GetInfoFromPrincipal(principal, + &mQuotaInfo.mGroup, + &mQuotaInfo.mOrigin, + &mQuotaInfo.mIsApp); + if (NS_WARN_IF(NS_FAILED(rv))) { + Resolve(rv); + return NS_OK; + } + + // QuotaManager::WaitForOpenAllowed() will hold a reference to us as + // a callback. We will then get executed again on the main thread when + // it is safe to open the quota directory. + mState = STATE_WAIT_FOR_OPEN_ALLOWED; + rv = qm->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mQuotaInfo.mOrigin), + Nullable(PERSISTENCE_TYPE_DEFAULT), + mQuotaId, this); + if (NS_FAILED(rv)) { + Resolve(rv); + return NS_OK; + } + break; + } + // ------------------------------ + case STATE_WAIT_FOR_OPEN_ALLOWED: + { + MOZ_ASSERT(NS_IsMainThread()); + QuotaManager* qm = QuotaManager::Get(); + MOZ_ASSERT(qm); + mState = STATE_ENSURE_ORIGIN_INITIALIZED; + nsresult rv = qm->IOThread()->Dispatch(this, nsIThread::DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + Resolve(rv); + return NS_OK; + } + break; + } + // ---------------------------------- + case STATE_ENSURE_ORIGIN_INITIALIZED: + { + // Can't assert quota IO thread because its an idle thread that can get + // recreated. At least assert we're not on main thread or owning thread. + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(_mOwningThread.GetThread() != PR_GetCurrentThread()); + + QuotaManager* qm = QuotaManager::Get(); + MOZ_ASSERT(qm); + nsresult rv = qm->EnsureOriginIsInitialized(PERSISTENCE_TYPE_DEFAULT, + mQuotaInfo.mGroup, + mQuotaInfo.mOrigin, + mQuotaInfo.mIsApp, + getter_AddRefs(mQuotaInfo.mDir)); + if (NS_FAILED(rv)) { + Resolve(rv); + return NS_OK; + } + + mState = STATE_RUNNING; + + if (!mQuotaIOThreadAction) { + Resolve(NS_OK); + return NS_OK; + } + + // Execute the provided initialization Action. We pass ourselves as the + // Resolver. The Action must either call Resolve() immediately or hold + // a ref to us and call Resolve() later. + mQuotaIOThreadAction->RunOnTarget(this, mQuotaInfo); + + break; + } + // ------------------- + case STATE_COMPLETING: + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + if (mQuotaIOThreadAction) { + mQuotaIOThreadAction->CompleteOnInitiatingThread(mResult); + } + mContext->OnQuotaInit(mResult, mQuotaInfo); + mState = STATE_COMPLETE; + // Explicitly cleanup here as the destructor could fire on any of + // the threads we have bounced through. + Clear(); + break; + } + // ----- + default: + { + MOZ_CRASH("unexpected state in QuotaInitRunnable"); + break; + } + } + + return NS_OK; +} + +// Runnable wrapper around Action objects dispatched on the Context. This +// runnable executes the Action on the appropriate threads while the Context +// is initialized. +class Context::ActionRunnable MOZ_FINAL : public nsIRunnable + , public Action::Resolver +{ +public: + ActionRunnable(Context* aContext, nsIEventTarget* aTarget, Action* aAction, + const QuotaInfo& aQuotaInfo) + : mContext(aContext) + , mTarget(aTarget) + , mAction(aAction) + , mQuotaInfo(aQuotaInfo) + , mInitiatingThread(NS_GetCurrentThread()) + , mState(STATE_INIT) + , mResult(NS_OK) + { + MOZ_ASSERT(mContext); + MOZ_ASSERT(mTarget); + MOZ_ASSERT(mAction); + MOZ_ASSERT(mQuotaInfo.mDir); + MOZ_ASSERT(mInitiatingThread); + } + + nsresult Dispatch() + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + MOZ_ASSERT(mState == STATE_INIT); + + mState = STATE_RUN_ON_TARGET; + nsresult rv = mTarget->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + mState = STATE_COMPLETE; + Clear(); + } + return rv; + } + + bool MatchesCacheId(CacheId aCacheId) { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + return mAction->MatchesCacheId(aCacheId); + } + + void Cancel() + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + mAction->CancelOnInitiatingThread(); + } + + virtual void Resolve(nsresult aRv) MOZ_OVERRIDE + { + MOZ_ASSERT(mTarget == NS_GetCurrentThread()); + MOZ_ASSERT(mState == STATE_RUNNING); + mResult = aRv; + mState = STATE_COMPLETING; + nsresult rv = mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + // Shutdown must be delayed until all Contexts are destroyed. Crash + // for this invariant violation. + MOZ_CRASH("Failed to dispatch ActionRunnable to initiating thread."); + } + } + +private: + ~ActionRunnable() + { + MOZ_ASSERT(mState == STATE_COMPLETE); + MOZ_ASSERT(!mContext); + MOZ_ASSERT(!mAction); + } + + void Clear() + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + MOZ_ASSERT(mContext); + MOZ_ASSERT(mAction); + mContext->OnActionRunnableComplete(this); + mContext = nullptr; + mAction = nullptr; + } + + enum State + { + STATE_INIT, + STATE_RUN_ON_TARGET, + STATE_RUNNING, + STATE_COMPLETING, + STATE_COMPLETE + }; + + nsRefPtr mContext; + nsCOMPtr mTarget; + nsRefPtr mAction; + const QuotaInfo mQuotaInfo; + nsCOMPtr mInitiatingThread; + State mState; + nsresult mResult; + +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIRUNNABLE +}; + +NS_IMPL_ISUPPORTS_INHERITED(mozilla::dom::cache::Context::ActionRunnable, + Action::Resolver, nsIRunnable); + +// The ActionRunnable has a simpler state machine. It basically needs to run +// the action on the target thread and then complete on the original thread. +// +// +-------------+ +// | Start | +// |(Orig Thread)| +// +-----+-------+ +// | +// +-------v---------+ +// | RunOnTarget | +// |Target IO Thread)+-------------------------------+ +// +-------+---------+ | +// | | +// +-------v----------+ Resolve() +-------v-----+ +// | Running | | Completing | +// |(Target IO Thread)+---------------------->(Orig Thread)| +// +------------------+ +-------+-----+ +// | +// | +// +----v---+ +// |Complete| +// +--------+ +// +// Its important to note that synchronous actions will effectively Resolve() +// out of the Running state immediately. Asynchronous Actions may remain +// in the Running state for some time, but normally the ActionRunnable itself +// does not see any execution there. Its all handled internal to the Action. +NS_IMETHODIMP +Context::ActionRunnable::Run() +{ + switch(mState) { + // ---------------------- + case STATE_RUN_ON_TARGET: + { + MOZ_ASSERT(NS_GetCurrentThread() == mTarget); + mState = STATE_RUNNING; + mAction->RunOnTarget(this, mQuotaInfo); + break; + } + // ------------------- + case STATE_COMPLETING: + { + NS_ASSERT_OWNINGTHREAD(Action::Resolver); + mAction->CompleteOnInitiatingThread(mResult); + mState = STATE_COMPLETE; + // Explicitly cleanup here as the destructor could fire on any of + // the threads we have bounced through. + Clear(); + break; + } + // ----------------- + default: + { + MOZ_CRASH("unexpected state in ActionRunnable"); + break; + } + } + return NS_OK; +} + +// static +already_AddRefed +Context::Create(Manager* aManager, Action* aQuotaIOThreadAction) +{ + nsRefPtr context = new Context(aManager); + + nsRefPtr runnable = + new QuotaInitRunnable(context, aManager, NS_LITERAL_CSTRING("Cache"), + aQuotaIOThreadAction); + nsresult rv = runnable->Dispatch(); + if (NS_FAILED(rv)) { + // Shutdown must be delayed until all Contexts are destroyed. Shutdown + // must also prevent any new Contexts from being constructed. Crash + // for this invariant violation. + MOZ_CRASH("Failed to dispatch QuotaInitRunnable."); + } + + return context.forget(); +} + +Context::Context(Manager* aManager) + : mManager(aManager) + , mState(STATE_CONTEXT_INIT) +{ + MOZ_ASSERT(mManager); +} + +void +Context::Dispatch(nsIEventTarget* aTarget, Action* aAction) +{ + NS_ASSERT_OWNINGTHREAD(Context); + MOZ_ASSERT(aTarget); + MOZ_ASSERT(aAction); + + if (mState == STATE_CONTEXT_CANCELED) { + return; + } else if (mState == STATE_CONTEXT_INIT) { + PendingAction* pending = mPendingActions.AppendElement(); + pending->mTarget = aTarget; + pending->mAction = aAction; + return; + } + + MOZ_ASSERT(STATE_CONTEXT_READY); + DispatchAction(aTarget, aAction); +} + +void +Context::CancelAll() +{ + NS_ASSERT_OWNINGTHREAD(Context); + mState = STATE_CONTEXT_CANCELED; + mPendingActions.Clear(); + for (uint32_t i = 0; i < mActionRunnables.Length(); ++i) { + nsRefPtr runnable = mActionRunnables[i]; + runnable->Cancel(); + } +} + +void +Context::CancelForCacheId(CacheId aCacheId) +{ + NS_ASSERT_OWNINGTHREAD(Context); + for (uint32_t i = 0; i < mPendingActions.Length(); ++i) { + if (mPendingActions[i].mAction->MatchesCacheId(aCacheId)) { + mPendingActions.RemoveElementAt(i); + } + } + for (uint32_t i = 0; i < mActionRunnables.Length(); ++i) { + nsRefPtr runnable = mActionRunnables[i]; + if (runnable->MatchesCacheId(aCacheId)) { + runnable->Cancel(); + } + } +} + +Context::~Context() +{ + NS_ASSERT_OWNINGTHREAD(Context); + MOZ_ASSERT(mManager); + + // Unlock the quota dir as we go out of scope. + nsCOMPtr runnable = + new QuotaReleaseRunnable(mQuotaInfo, NS_LITERAL_CSTRING("Cache")); + nsresult rv = NS_DispatchToMainThread(runnable, nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + // Shutdown must be delayed until all Contexts are destroyed. Crash + // for this invariant violation. + MOZ_CRASH("Failed to dispatch QuotaReleaseRunnable to main thread."); + } + + mManager->RemoveContext(this); +} + +void +Context::DispatchAction(nsIEventTarget* aTarget, Action* aAction) +{ + NS_ASSERT_OWNINGTHREAD(Context); + + nsRefPtr runnable = + new ActionRunnable(this, aTarget, aAction, mQuotaInfo); + nsresult rv = runnable->Dispatch(); + if (NS_FAILED(rv)) { + // Shutdown must be delayed until all Contexts are destroyed. Crash + // for this invariant violation. + MOZ_CRASH("Failed to dispatch ActionRunnable to target thread."); + } + mActionRunnables.AppendElement(runnable); +} + +void +Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo) +{ + NS_ASSERT_OWNINGTHREAD(Context); + + mQuotaInfo = aQuotaInfo; + + if (mState == STATE_CONTEXT_CANCELED || NS_FAILED(aRv)) { + for (uint32_t i = 0; i < mPendingActions.Length(); ++i) { + mPendingActions[i].mAction->CompleteOnInitiatingThread(aRv); + } + mPendingActions.Clear(); + // Context will destruct after return here and last ref is released. + return; + } + + MOZ_ASSERT(mState == STATE_CONTEXT_INIT); + mState = STATE_CONTEXT_READY; + + for (uint32_t i = 0; i < mPendingActions.Length(); ++i) { + DispatchAction(mPendingActions[i].mTarget, mPendingActions[i].mAction); + } + mPendingActions.Clear(); +} + +void +Context::OnActionRunnableComplete(ActionRunnable* aActionRunnable) +{ + NS_ASSERT_OWNINGTHREAD(Context); + MOZ_ASSERT(aActionRunnable); + MOZ_ALWAYS_TRUE(mActionRunnables.RemoveElement(aActionRunnable)); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/Context.h b/dom/cache/Context.h new file mode 100644 index 0000000000..e53b957e38 --- /dev/null +++ b/dom/cache/Context.h @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_Context_h +#define mozilla_dom_cache_Context_h + +#include "mozilla/dom/cache/Types.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "nsISupportsImpl.h" +#include "nsString.h" +#include "nsTArray.h" + +class nsIEventTarget; +class nsIFile; + +namespace mozilla { +namespace dom { +namespace cache { + +class Action; +class Manager; + +// The Context class is RAII-style class for managing IO operations within the +// Cache. +// +// When a Context is created it performs the complicated steps necessary to +// initialize the QuotaManager. Action objects dispatched on the Context are +// delayed until this initialization is complete. They are then allow to +// execute on any specified thread. Once all references to the Context are +// gone, then the steps necessary to release the QuotaManager are performed. +// Since pending Action objects reference the Context, this allows overlapping +// IO to opportunistically run without re-initializing the QuotaManager again. +// +// While the Context performs operations asynchronously on threads, all of +// methods in its public interface must be called on the same thread +// originally used to create the Context. +// +// As an invariant, all Context objects must be destroyed before permitting +// the "profile-before-change" shutdown event to complete. This is ensured +// via the code in ShutdownObserver.cpp. +class Context MOZ_FINAL +{ +public: + static already_AddRefed + Create(Manager* aManager, Action* aQuotaIOThreadAction); + + // Execute given action on the target once the quota manager has been + // initialized. + // + // Only callable from the thread that created the Context. + void Dispatch(nsIEventTarget* aTarget, Action* aAction); + + // Cancel any Actions running or waiting to run. This should allow the + // Context to be released and Listener::RemoveContext() will be called + // when complete. + // + // Only callable from the thread that created the Context. + void CancelAll(); + + // Cancel any Actions running or waiting to run that operate on the given + // cache ID. + // + // Only callable from the thread that created the Context. + void CancelForCacheId(CacheId aCacheId); + +private: + class QuotaInitRunnable; + class ActionRunnable; + + enum State + { + STATE_CONTEXT_INIT, + STATE_CONTEXT_READY, + STATE_CONTEXT_CANCELED + }; + + struct PendingAction + { + nsCOMPtr mTarget; + nsRefPtr mAction; + }; + + explicit Context(Manager* aManager); + ~Context(); + void DispatchAction(nsIEventTarget* aTarget, Action* aAction); + void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo); + void OnActionRunnableComplete(ActionRunnable* const aAction); + + nsRefPtr mManager; + State mState; + QuotaInfo mQuotaInfo; + nsTArray mPendingActions; + + // weak refs since ~ActionRunnable() removes itself from this list + nsTArray mActionRunnables; + +public: + NS_INLINE_DECL_REFCOUNTING(cache::Context) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_Context_h diff --git a/dom/cache/DBAction.cpp b/dom/cache/DBAction.cpp new file mode 100644 index 0000000000..b8a2d136d9 --- /dev/null +++ b/dom/cache/DBAction.cpp @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/DBAction.h" + +#include "mozilla/dom/quota/PersistenceType.h" +#include "mozilla/net/nsFileProtocolHandler.h" +#include "mozIStorageConnection.h" +#include "mozIStorageService.h" +#include "mozStorageCID.h" +#include "nsIFile.h" +#include "nsIURI.h" +#include "nsNetUtil.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT; +using mozilla::dom::quota::PersistenceType; + +DBAction::DBAction(Mode aMode) + : mMode(aMode) +{ +} + +DBAction::~DBAction() +{ +} + +void +DBAction::RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aResolver); + MOZ_ASSERT(aQuotaInfo.mDir); + + if (IsCanceled()) { + aResolver->Resolve(NS_ERROR_ABORT); + return; + } + + nsCOMPtr dbDir; + nsresult rv = aQuotaInfo.mDir->Clone(getter_AddRefs(dbDir)); + if (NS_WARN_IF(NS_FAILED(rv))) { + aResolver->Resolve(rv); + return; + } + + rv = dbDir->Append(NS_LITERAL_STRING("cache")); + if (NS_WARN_IF(NS_FAILED(rv))) { + aResolver->Resolve(rv); + return; + } + + nsCOMPtr conn; + rv = OpenConnection(aQuotaInfo, dbDir, getter_AddRefs(conn)); + if (NS_WARN_IF(NS_FAILED(rv))) { + aResolver->Resolve(rv); + return; + } + MOZ_ASSERT(conn); + + RunWithDBOnTarget(aResolver, aQuotaInfo, dbDir, conn); +} + +nsresult +DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection** aConnOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aDBDir); + MOZ_ASSERT(aConnOut); + + bool exists; + nsresult rv = aDBDir->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!exists) { + if (NS_WARN_IF(mMode != Create)) { return NS_ERROR_FILE_NOT_FOUND; } + rv = aDBDir->Create(nsIFile::DIRECTORY_TYPE, 0755); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + nsCOMPtr dbFile; + rv = aDBDir->Clone(getter_AddRefs(dbFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = dbFile->Append(NS_LITERAL_STRING("caches.sqlite")); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = dbFile->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // Use our default file:// protocol handler directly to construct the database + // URL. This avoids any problems if a plugin registers a custom file:// + // handler. If such a custom handler used javascript, then we would have a + // bad time running off the main thread here. + nsRefPtr handler = new nsFileProtocolHandler(); + rv = handler->Init(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr uri; + rv = handler->NewFileURI(dbFile, getter_AddRefs(uri)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr dbFileUrl = do_QueryInterface(uri); + if (NS_WARN_IF(!dbFileUrl)) { return NS_ERROR_UNEXPECTED; } + + nsAutoCString type; + PersistenceTypeToText(PERSISTENCE_TYPE_DEFAULT, type); + + rv = dbFileUrl->SetQuery( + NS_LITERAL_CSTRING("persistenceType=") + type + + NS_LITERAL_CSTRING("&group=") + aQuotaInfo.mGroup + + NS_LITERAL_CSTRING("&origin=") + aQuotaInfo.mOrigin); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr ss = + do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID); + if (NS_WARN_IF(!ss)) { return NS_ERROR_UNEXPECTED; } + + rv = ss->OpenDatabaseWithFileURL(dbFileUrl, aConnOut); + if (rv == NS_ERROR_FILE_CORRUPTED) { + NS_WARNING("Cache database corrupted. Recreating empty database."); + + // There is nothing else we can do to recover. Also, this data can + // be deleted by QuotaManager at any time anyways. + rv = dbFile->Remove(false); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // TODO: clean up any orphaned body files (bug 1110446) + + rv = ss->OpenDatabaseWithFileURL(dbFileUrl, aConnOut); + } + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(*aConnOut); + return rv; +} + +SyncDBAction::SyncDBAction(Mode aMode) + : DBAction(aMode) +{ +} + +SyncDBAction::~SyncDBAction() +{ +} + +void +SyncDBAction::RunWithDBOnTarget(Resolver* aResolver, + const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aResolver); + MOZ_ASSERT(aDBDir); + MOZ_ASSERT(aConn); + + nsresult rv = RunSyncWithDBOnTarget(aQuotaInfo, aDBDir, aConn); + aResolver->Resolve(rv); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/DBAction.h b/dom/cache/DBAction.h new file mode 100644 index 0000000000..497b7695a1 --- /dev/null +++ b/dom/cache/DBAction.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_DBAction_h +#define mozilla_dom_cache_DBAction_h + +#include "mozilla/dom/cache/Action.h" +#include "mozilla/dom/cache/CacheInitData.h" +#include "mozilla/nsRefPtr.h" +#include "nsString.h" + +class mozIStorageConnection; +class nsIFile; + +namespace mozilla { +namespace dom { +namespace cache { + +class DBAction : public Action +{ +protected: + // The mode specifies whether the database should already exist or if its + // ok to create a new database. + enum Mode + { + Existing, + Create + }; + + explicit DBAction(Mode aMode); + + // Action objects are deleted through their base pointer + virtual ~DBAction(); + + // Just as the resolver must be ref'd until resolve, you may also + // ref the DB connection. The connection can only be referenced from the + // target thread and must be released upon resolve. + virtual void + RunWithDBOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo, + nsIFile* aDBDir, mozIStorageConnection* aConn) = 0; + +private: + virtual void + RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo) MOZ_OVERRIDE; + + nsresult OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aQuotaDir, + mozIStorageConnection** aConnOut); + + const Mode mMode; +}; + +class SyncDBAction : public DBAction +{ +protected: + explicit SyncDBAction(Mode aMode); + + // Action objects are deleted through their base pointer + virtual ~SyncDBAction(); + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) = 0; + +private: + virtual void + RunWithDBOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo, + nsIFile* aDBDir, mozIStorageConnection* aConn) MOZ_OVERRIDE; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_DBAction_h diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp new file mode 100644 index 0000000000..03da25a384 --- /dev/null +++ b/dom/cache/DBSchema.cpp @@ -0,0 +1,1322 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/DBSchema.h" + +#include "ipc/IPCMessageUtils.h" +#include "mozilla/dom/InternalHeaders.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/dom/cache/SavedTypes.h" +#include "mozIStorageConnection.h" +#include "mozIStorageStatement.h" +#include "nsCOMPtr.h" +#include "nsTArray.h" + +namespace mozilla { +namespace dom { +namespace cache { + + +const int32_t DBSchema::kLatestSchemaVersion = 1; +const int32_t DBSchema::kMaxEntriesPerStatement = 255; + +using mozilla::void_t; + +// static +nsresult +DBSchema::CreateSchema(mozIStorageConnection* aConn) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + nsAutoCString pragmas( +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) + // Switch the journaling mode to TRUNCATE to avoid changing the directory + // structure at the conclusion of every transaction for devices with slower + // file systems. + "PRAGMA journal_mode = TRUNCATE; " +#endif + "PRAGMA foreign_keys = ON; " + + // Note, the default encoding of UTF-8 is preferred. mozStorage does all + // the work necessary to convert UTF-16 nsString values for us. We don't + // need ordering and the binary equality operations are correct. So, do + // NOT set PRAGMA encoding to UTF-16. + ); + + nsresult rv = aConn->ExecuteSimpleSQL(pragmas); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t schemaVersion; + rv = aConn->GetSchemaVersion(&schemaVersion); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (schemaVersion == kLatestSchemaVersion) { + return rv; + } + + if (!schemaVersion) { + // The caches table is the single source of truth about what Cache + // objects exist for the origin. The contents of the Cache are stored + // in the entries table that references back to caches. + // + // The caches table is also referenced from storage. Rows in storage + // represent named Cache objects. There are cases, however, where + // a Cache can still exist, but not be in a named Storage. For example, + // when content is still using the Cache after CacheStorage::Delete() + // has been run. + // + // For now, the caches table mainly exists for data integrity with + // foreign keys, but could be expanded to contain additional cache object + // information. + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE caches (" + "id INTEGER NOT NULL PRIMARY KEY " + ");" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE entries (" + "id INTEGER NOT NULL PRIMARY KEY, " + "request_method TEXT NOT NULL, " + "request_url TEXT NOT NULL, " + "request_url_no_query TEXT NOT NULL, " + "request_referrer TEXT NOT NULL, " + "request_headers_guard INTEGER NOT NULL, " + "request_mode INTEGER NOT NULL, " + "request_credentials INTEGER NOT NULL, " + "request_body_id TEXT NULL, " + "response_type INTEGER NOT NULL, " + "response_url TEXT NOT NULL, " + "response_status INTEGER NOT NULL, " + "response_status_text TEXT NOT NULL, " + "response_headers_guard INTEGER NOT NULL, " + "response_body_id TEXT NULL, " + "cache_id INTEGER NOT NULL REFERENCES caches(id) ON DELETE CASCADE" + ");" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // TODO: see if we can remove these indices on TEXT columns (bug 1110458) + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX entries_request_url_index " + "ON entries (request_url);" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX entries_request_url_no_query_index " + "ON entries (request_url_no_query);" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE request_headers (" + "name TEXT NOT NULL, " + "value TEXT NOT NULL, " + "entry_id INTEGER NOT NULL REFERENCES entries(id) ON DELETE CASCADE" + ");" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE response_headers (" + "name TEXT NOT NULL, " + "value TEXT NOT NULL, " + "entry_id INTEGER NOT NULL REFERENCES entries(id) ON DELETE CASCADE" + ");" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // We need an index on response_headers, but not on request_headers, + // because we quickly need to determine if a VARY header is present. + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX response_headers_name_index " + "ON response_headers (name);" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE storage (" + "namespace INTEGER NOT NULL, " + "key TEXT NOT NULL, " + "cache_id INTEGER NOT NULL REFERENCES caches(id), " + "PRIMARY KEY(namespace, key) " + ");" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->SetSchemaVersion(kLatestSchemaVersion); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->GetSchemaVersion(&schemaVersion); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + if (schemaVersion != kLatestSchemaVersion) { + return NS_ERROR_FAILURE; + } + + return rv; +} + +// static +nsresult +DBSchema::CreateCache(mozIStorageConnection* aConn, CacheId* aCacheIdOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aCacheIdOut); + + nsresult rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "INSERT INTO caches DEFAULT VALUES;" + )); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr state; + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT last_insert_rowid()" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + rv = state->ExecuteStep(&hasMoreData); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(!hasMoreData)) { return NS_ERROR_UNEXPECTED; } + + rv = state->GetInt32(0, aCacheIdOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::DeleteCache(mozIStorageConnection* aConn, CacheId aCacheId, + nsTArray& aDeletedBodyIdListOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + // Delete the bodies explicitly as we need to read out the body IDs + // anyway. These body IDs must be deleted one-by-one as content may + // still be referencing them invidivually. + nsAutoTArray matches; + nsresult rv = QueryAll(aConn, aCacheId, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // Delete the remainder of the cache using cascade semantics. + nsCOMPtr state; + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "DELETE FROM caches WHERE id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::IsCacheOrphaned(mozIStorageConnection* aConn, + CacheId aCacheId, bool* aOrphanedOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aOrphanedOut); + + // err on the side of not deleting user data + *aOrphanedOut = false; + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT COUNT(*) FROM storage WHERE cache_id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + rv = state->ExecuteStep(&hasMoreData); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(hasMoreData); + + int32_t refCount; + rv = state->GetInt32(0, &refCount); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + *aOrphanedOut = refCount == 0; + + return rv; +} + +// static +nsresult +DBSchema::CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + bool* aFoundResponseOut, + SavedResponse* aSavedResponseOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aFoundResponseOut); + MOZ_ASSERT(aSavedResponseOut); + + *aFoundResponseOut = false; + + nsAutoTArray matches; + nsresult rv = QueryCache(aConn, aCacheId, aRequest, aParams, matches, 1); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (matches.IsEmpty()) { + return rv; + } + + rv = ReadResponse(aConn, matches[0], aSavedResponseOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + aSavedResponseOut->mCacheId = aCacheId; + *aFoundResponseOut = true; + + return rv; +} + +// static +nsresult +DBSchema::CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams, + nsTArray& aSavedResponsesOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + nsresult rv; + + nsAutoTArray matches; + if (aRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t) { + rv = QueryAll(aConn, aCacheId, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } else { + rv = QueryCache(aConn, aCacheId, aRequestOrVoid, aParams, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + // TODO: replace this with a bulk load using SQL IN clause (bug 1110458) + for (uint32_t i = 0; i < matches.Length(); ++i) { + SavedResponse savedResponse; + rv = ReadResponse(aConn, matches[i], &savedResponse); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + savedResponse.mCacheId = aCacheId; + aSavedResponsesOut.AppendElement(savedResponse); + } + + return rv; +} + +// static +nsresult +DBSchema::CachePut(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const nsID* aRequestBodyId, + const PCacheResponse& aResponse, + const nsID* aResponseBodyId, + nsTArray& aDeletedBodyIdListOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + PCacheQueryParams params(false, false, false, false, false, + NS_LITERAL_STRING("")); + nsAutoTArray matches; + nsresult rv = QueryCache(aConn, aCacheId, aRequest, params, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = InsertEntry(aConn, aCacheId, aRequest, aRequestBodyId, aResponse, + aResponseBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + nsTArray& aDeletedBodyIdListOut, bool* aSuccessOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aSuccessOut); + + *aSuccessOut = false; + + nsAutoTArray matches; + nsresult rv = QueryCache(aConn, aCacheId, aRequest, aParams, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (matches.IsEmpty()) { + return rv; + } + + rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + *aSuccessOut = true; + + return rv; +} + +// static +nsresult +DBSchema::CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams, + nsTArray& aSavedRequestsOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + nsresult rv; + + nsAutoTArray matches; + if (aRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t) { + rv = QueryAll(aConn, aCacheId, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } else { + rv = QueryCache(aConn, aCacheId, aRequestOrVoid, aParams, matches); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + // TODO: replace this with a bulk load using SQL IN clause (bug 1110458) + for (uint32_t i = 0; i < matches.Length(); ++i) { + SavedRequest savedRequest; + rv = ReadRequest(aConn, matches[i], &savedRequest); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + savedRequest.mCacheId = aCacheId; + aSavedRequestsOut.AppendElement(savedRequest); + } + + return rv; +} + +// static +nsresult +DBSchema::StorageMatch(mozIStorageConnection* aConn, + Namespace aNamespace, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + bool* aFoundResponseOut, + SavedResponse* aSavedResponseOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aFoundResponseOut); + MOZ_ASSERT(aSavedResponseOut); + + *aFoundResponseOut = false; + + nsresult rv; + + // If we are given a cache to check, then simply find its cache ID + // and perform the match. + if (!aParams.cacheName().EqualsLiteral("")) { + bool foundCache = false; + // no invalid CacheId, init to least likely real value + CacheId cacheId = INT32_MAX; + rv = StorageGetCacheId(aConn, aNamespace, aParams.cacheName(), &foundCache, + &cacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (!foundCache) { return NS_ERROR_DOM_NOT_FOUND_ERR; } + + rv = CacheMatch(aConn, cacheId, aRequest, aParams, aFoundResponseOut, + aSavedResponseOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; + } + + // Otherwise we need to get a list of all the cache IDs in this namespace. + + nsCOMPtr state; + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT cache_id FROM storage WHERE namespace=?1 ORDER BY rowid;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aNamespace); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsAutoTArray cacheIdList; + + bool hasMoreData = false; + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + CacheId cacheId = INT32_MAX; + rv = state->GetInt32(0, &cacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + cacheIdList.AppendElement(cacheId); + } + + // Now try to find a match in each cache in order + for (uint32_t i = 0; i < cacheIdList.Length(); ++i) { + rv = CacheMatch(aConn, cacheIdList[i], aRequest, aParams, aFoundResponseOut, + aSavedResponseOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (*aFoundResponseOut) { + aSavedResponseOut->mCacheId = cacheIdList[i]; + return rv; + } + } + + return NS_OK; +} + +// static +nsresult +DBSchema::StorageGetCacheId(mozIStorageConnection* aConn, Namespace aNamespace, + const nsAString& aKey, bool* aFoundCacheOut, + CacheId* aCacheIdOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aFoundCacheOut); + MOZ_ASSERT(aCacheIdOut); + + *aFoundCacheOut = false; + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT cache_id FROM storage WHERE namespace=?1 AND key=?2 ORDER BY rowid;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aNamespace); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(1, aKey); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + rv = state->ExecuteStep(&hasMoreData); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!hasMoreData) { + return rv; + } + + rv = state->GetInt32(0, aCacheIdOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + *aFoundCacheOut = true; + return rv; +} + +// static +nsresult +DBSchema::StoragePutCache(mozIStorageConnection* aConn, Namespace aNamespace, + const nsAString& aKey, CacheId aCacheId) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO storage (namespace, key, cache_id) VALUES(?1, ?2, ?3);" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aNamespace); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(1, aKey); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(2, aCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::StorageForgetCache(mozIStorageConnection* aConn, Namespace aNamespace, + const nsAString& aKey) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "DELETE FROM storage WHERE namespace=?1 AND key=?2;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aNamespace); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(1, aKey); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace, + nsTArray& aKeysOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT key FROM storage WHERE namespace=?1 ORDER BY rowid;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aNamespace); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + nsAutoString key; + rv = state->GetString(0, key); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aKeysOut.AppendElement(key); + } + + return rv; +} + +// static +nsresult +DBSchema::QueryAll(mozIStorageConnection* aConn, CacheId aCacheId, + nsTArray& aEntryIdListOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT id FROM entries WHERE cache_id=?1 ORDER BY id;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + EntryId entryId = INT32_MAX; + rv = state->GetInt32(0, &entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aEntryIdListOut.AppendElement(entryId); + } + + return rv; +} + +// static +nsresult +DBSchema::QueryCache(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + nsTArray& aEntryIdListOut, + uint32_t aMaxResults) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aMaxResults > 0); + + if (!aParams.ignoreMethod() && !aRequest.method().LowerCaseEqualsLiteral("get") + && !aRequest.method().LowerCaseEqualsLiteral("head")) + { + return NS_OK; + } + + nsAutoCString query( + "SELECT id, COUNT(response_headers.name) AS vary_count " + "FROM entries " + "LEFT OUTER JOIN response_headers ON entries.id=response_headers.entry_id " + "AND response_headers.name='vary' " + "WHERE entries.cache_id=?1 " + "AND entries." + ); + + nsAutoString urlToMatch; + if (aParams.ignoreSearch()) { + urlToMatch = aRequest.urlWithoutQuery(); + query.AppendLiteral("request_url_no_query"); + } else { + urlToMatch = aRequest.url(); + query.AppendLiteral("request_url"); + } + + if (aParams.prefixMatch()) { + query.AppendLiteral(" LIKE ?2 ESCAPE '\\'"); + } else { + query.AppendLiteral("=?2"); + } + + query.AppendLiteral(" GROUP BY entries.id ORDER BY entries.id;"); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(query, getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (aParams.prefixMatch()) { + nsAutoString escapedUrlToMatch; + rv = state->EscapeStringForLIKE(urlToMatch, '\\', escapedUrlToMatch); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + urlToMatch = escapedUrlToMatch; + urlToMatch.AppendLiteral("%"); + } + + rv = state->BindStringParameter(1, urlToMatch); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + // no invalid EntryId, init to least likely real value + EntryId entryId = INT32_MAX; + rv = state->GetInt32(0, &entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t varyCount; + rv = state->GetInt32(1, &varyCount); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!aParams.ignoreVary() && varyCount > 0) { + bool matchedByVary = false; + rv = MatchByVaryHeader(aConn, aRequest, entryId, &matchedByVary); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (!matchedByVary) { + continue; + } + } + + aEntryIdListOut.AppendElement(entryId); + + if (aEntryIdListOut.Length() == aMaxResults) { + return NS_OK; + } + } + + return rv; +} + +// static +nsresult +DBSchema::MatchByVaryHeader(mozIStorageConnection* aConn, + const PCacheRequest& aRequest, + EntryId entryId, bool* aSuccessOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + *aSuccessOut = false; + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT value FROM response_headers " + "WHERE name='vary' AND entry_id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsAutoTArray varyValues; + + bool hasMoreData = false; + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + nsAutoCString value; + rv = state->GetUTF8String(0, value); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + varyValues.AppendElement(value); + } + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // Should not have called this function if this was not the case + MOZ_ASSERT(!varyValues.IsEmpty()); + + state->Reset(); + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT name, value FROM request_headers " + "WHERE entry_id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsRefPtr cachedHeaders = new InternalHeaders(HeadersGuardEnum::None); + + ErrorResult errorResult; + + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + nsAutoCString name; + nsAutoCString value; + rv = state->GetUTF8String(0, name); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + rv = state->GetUTF8String(1, value); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + cachedHeaders->Append(name, value, errorResult); + if (errorResult.Failed()) { return errorResult.ErrorCode(); }; + } + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsRefPtr queryHeaders = new InternalHeaders(aRequest.headers()); + + // Assume the vary headers match until we find a conflict + bool varyHeadersMatch = true; + + for (uint32_t i = 0; i < varyValues.Length(); ++i) { + if (varyValues[i].EqualsLiteral("*")) { + continue; + } + + nsAutoCString queryValue; + queryHeaders->Get(varyValues[i], queryValue, errorResult); + if (errorResult.Failed()) { return errorResult.ErrorCode(); }; + + nsAutoCString cachedValue; + cachedHeaders->Get(varyValues[i], cachedValue, errorResult); + if (errorResult.Failed()) { return errorResult.ErrorCode(); }; + + if (queryValue != cachedValue) { + varyHeadersMatch = false; + break; + } + } + + *aSuccessOut = varyHeadersMatch; + return rv; +} + +// static +nsresult +DBSchema::DeleteEntries(mozIStorageConnection* aConn, + const nsTArray& aEntryIdList, + nsTArray& aDeletedBodyIdListOut, + uint32_t aPos, int32_t aLen) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + if (aEntryIdList.IsEmpty()) { + return NS_OK; + } + + MOZ_ASSERT(aPos < aEntryIdList.Length()); + + if (aLen < 0) { + aLen = aEntryIdList.Length() - aPos; + } + + // Sqlite limits the number of entries allowed for an IN clause, + // so split up larger operations. + if (aLen > kMaxEntriesPerStatement) { + uint32_t curPos = aPos; + int32_t remaining = aLen; + while (remaining > 0) { + int32_t max = kMaxEntriesPerStatement; + int32_t curLen = std::min(max, remaining); + nsresult rv = DeleteEntries(aConn, aEntryIdList, aDeletedBodyIdListOut, + curPos, curLen); + if (NS_FAILED(rv)) { return rv; } + + curPos += curLen; + remaining -= curLen; + } + return NS_OK; + } + + nsCOMPtr state; + nsAutoCString query( + "SELECT request_body_id, response_body_id FROM entries WHERE id IN (" + ); + AppendListParamsToQuery(query, aEntryIdList, aPos, aLen); + query.AppendLiteral(")"); + + nsresult rv = aConn->CreateStatement(query, getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = BindListParamsToQuery(state, aEntryIdList, aPos, aLen); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + // extract 0 to 2 nsID structs per row + for (uint32_t i = 0; i < 2; ++i) { + bool isNull = false; + + rv = state->GetIsNull(i, &isNull); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!isNull) { + nsID id; + rv = ExtractId(state, i, &id); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aDeletedBodyIdListOut.AppendElement(id); + } + } + } + + // Dependent records removed via ON DELETE CASCADE + + query = NS_LITERAL_CSTRING( + "DELETE FROM entries WHERE id IN (" + ); + AppendListParamsToQuery(query, aEntryIdList, aPos, aLen); + query.AppendLiteral(")"); + + rv = aConn->CreateStatement(query, getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = BindListParamsToQuery(state, aEntryIdList, aPos, aLen); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const nsID* aRequestBodyId, + const PCacheResponse& aResponse, + const nsID* aResponseBodyId) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO entries (" + "request_method, " + "request_url, " + "request_url_no_query, " + "request_referrer, " + "request_headers_guard, " + "request_mode, " + "request_credentials, " + "request_body_id, " + "response_type, " + "response_url, " + "response_status, " + "response_status_text, " + "response_headers_guard, " + "response_body_id, " + "cache_id " + ") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindUTF8StringParameter(0, aRequest.method()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(1, aRequest.url()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(2, aRequest.urlWithoutQuery()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(3, aRequest.referrer()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(4, + static_cast(aRequest.headersGuard())); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(5, static_cast(aRequest.mode())); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(6, + static_cast(aRequest.credentials())); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = BindId(state, 7, aRequestBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(8, static_cast(aResponse.type())); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindStringParameter(9, aResponse.url()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(10, aResponse.status()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindUTF8StringParameter(11, aResponse.statusText()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(12, + static_cast(aResponse.headersGuard())); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = BindId(state, 13, aResponseBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(14, aCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT last_insert_rowid()" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + rv = state->ExecuteStep(&hasMoreData); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t entryId; + rv = state->GetInt32(0, &entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO request_headers (" + "name, " + "value, " + "entry_id " + ") VALUES (?1, ?2, ?3)" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + const nsTArray& requestHeaders = aRequest.headers(); + for (uint32_t i = 0; i < requestHeaders.Length(); ++i) { + rv = state->BindUTF8StringParameter(0, requestHeaders[i].name()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindUTF8StringParameter(1, requestHeaders[i].value()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(2, entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO response_headers (" + "name, " + "value, " + "entry_id " + ") VALUES (?1, ?2, ?3)" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + const nsTArray& responseHeaders = aResponse.headers(); + for (uint32_t i = 0; i < responseHeaders.Length(); ++i) { + rv = state->BindUTF8StringParameter(0, responseHeaders[i].name()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindUTF8StringParameter(1, responseHeaders[i].value()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(2, entryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->Execute(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + return rv; +} + +// static +nsresult +DBSchema::ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId, + SavedResponse* aSavedResponseOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aSavedResponseOut); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT " + "response_type, " + "response_url, " + "response_status, " + "response_status_text, " + "response_headers_guard, " + "response_body_id " + "FROM entries " + "WHERE id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aEntryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + rv = state->ExecuteStep(&hasMoreData); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t type; + rv = state->GetInt32(0, &type); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedResponseOut->mValue.type() = static_cast(type); + + rv = state->GetString(1, aSavedResponseOut->mValue.url()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t status; + rv = state->GetInt32(2, &status); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedResponseOut->mValue.status() = status; + + rv = state->GetUTF8String(3, aSavedResponseOut->mValue.statusText()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t guard; + rv = state->GetInt32(4, &guard); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedResponseOut->mValue.headersGuard() = + static_cast(guard); + + bool nullBody = false; + rv = state->GetIsNull(5, &nullBody); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedResponseOut->mHasBodyId = !nullBody; + + if (aSavedResponseOut->mHasBodyId) { + rv = ExtractId(state, 5, &aSavedResponseOut->mBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT " + "name, " + "value " + "FROM response_headers " + "WHERE entry_id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aEntryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + PHeadersEntry header; + + rv = state->GetUTF8String(0, header.name()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->GetUTF8String(1, header.value()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + aSavedResponseOut->mValue.headers().AppendElement(header); + } + + return rv; +} + +// static +nsresult +DBSchema::ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId, + SavedRequest* aSavedRequestOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aConn); + MOZ_ASSERT(aSavedRequestOut); + + nsCOMPtr state; + nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT " + "request_method, " + "request_url, " + "request_url_no_query, " + "request_referrer, " + "request_headers_guard, " + "request_mode, " + "request_credentials, " + "request_body_id " + "FROM entries " + "WHERE id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aEntryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMoreData = false; + rv = state->ExecuteStep(&hasMoreData); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->GetUTF8String(0, aSavedRequestOut->mValue.method()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->GetString(1, aSavedRequestOut->mValue.url()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->GetString(2, aSavedRequestOut->mValue.urlWithoutQuery()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->GetString(3, aSavedRequestOut->mValue.referrer()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + int32_t guard; + rv = state->GetInt32(4, &guard); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedRequestOut->mValue.headersGuard() = + static_cast(guard); + + int32_t mode; + rv = state->GetInt32(5, &mode); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedRequestOut->mValue.mode() = static_cast(mode); + + int32_t credentials; + rv = state->GetInt32(6, &credentials); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedRequestOut->mValue.credentials() = + static_cast(credentials); + + bool nullBody = false; + rv = state->GetIsNull(7, &nullBody); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + aSavedRequestOut->mHasBodyId = !nullBody; + + if (aSavedRequestOut->mHasBodyId) { + rv = ExtractId(state, 7, &aSavedRequestOut->mBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + } + + rv = aConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT " + "name, " + "value " + "FROM request_headers " + "WHERE entry_id=?1;" + ), getter_AddRefs(state)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->BindInt32Parameter(0, aEntryId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) { + PHeadersEntry header; + + rv = state->GetUTF8String(0, header.name()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = state->GetUTF8String(1, header.value()); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + aSavedRequestOut->mValue.headers().AppendElement(header); + } + + return rv; +} + +// static +void +DBSchema::AppendListParamsToQuery(nsACString& aQuery, + const nsTArray& aEntryIdList, + uint32_t aPos, int32_t aLen) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT((aPos + aLen) <= aEntryIdList.Length()); + for (int32_t i = aPos; i < aLen; ++i) { + if (i == 0) { + aQuery.AppendLiteral("?"); + } else { + aQuery.AppendLiteral(",?"); + } + } +} + +// static +nsresult +DBSchema::BindListParamsToQuery(mozIStorageStatement* aState, + const nsTArray& aEntryIdList, + uint32_t aPos, int32_t aLen) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT((aPos + aLen) <= aEntryIdList.Length()); + for (int32_t i = aPos; i < aLen; ++i) { + nsresult rv = aState->BindInt32Parameter(i, aEntryIdList[i]); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +// static +nsresult +DBSchema::BindId(mozIStorageStatement* aState, uint32_t aPos, const nsID* aId) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aState); + nsresult rv; + + if (!aId) { + rv = aState->BindNullParameter(aPos); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + return rv; + } + + char idBuf[NSID_LENGTH]; + aId->ToProvidedString(idBuf); + rv = aState->BindUTF8StringParameter(aPos, nsAutoCString(idBuf)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +DBSchema::ExtractId(mozIStorageStatement* aState, uint32_t aPos, nsID* aIdOut) +{ + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aState); + MOZ_ASSERT(aIdOut); + + nsAutoCString idString; + nsresult rv = aState->GetUTF8String(aPos, idString); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool success = aIdOut->Parse(idString.get()); + if (NS_WARN_IF(!success)) { return NS_ERROR_UNEXPECTED; } + + return rv; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/DBSchema.h b/dom/cache/DBSchema.h new file mode 100644 index 0000000000..a592c96b9f --- /dev/null +++ b/dom/cache/DBSchema.h @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_DBSchema_h +#define mozilla_dom_cache_DBSchema_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/cache/Types.h" +#include "nsError.h" +#include "nsString.h" +#include "nsTArrayForwardDeclare.h" + +class mozIStorageConnection; +class mozIStorageStatement; +struct nsID; + +namespace mozilla { +namespace dom { +namespace cache { + +class PCacheQueryParams; +class PCacheRequest; +class PCacheRequestOrVoid; +class PCacheResponse; +class PCacheResponseOrVoid; +struct SavedRequest; +struct SavedResponse; + +// TODO: remove static class and use functions in cache namespace (bug 1110485) +class DBSchema MOZ_FINAL +{ +public: + static nsresult CreateSchema(mozIStorageConnection* aConn); + + static nsresult CreateCache(mozIStorageConnection* aConn, + CacheId* aCacheIdOut); + // TODO: improve naming (confusing with CacheDelete) (bug 1110485) + static nsresult DeleteCache(mozIStorageConnection* aConn, CacheId aCacheId, + nsTArray& aDeletedBodyIdListOut); + + // TODO: Consider removing unused IsCacheOrphaned after writing cleanup code. (bug 1110446) + static nsresult IsCacheOrphaned(mozIStorageConnection* aConn, + CacheId aCacheId, bool* aOrphanedOut); + + static nsresult CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + bool* aFoundResponseOut, + SavedResponse* aSavedResponseOut); + static nsresult CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams, + nsTArray& aSavedResponsesOut); + static nsresult CachePut(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const nsID* aRequestBodyId, + const PCacheResponse& aResponse, + const nsID* aResponseBodyId, + nsTArray& aDeletedBodyIdListOut); + static nsresult CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + nsTArray& aDeletedBodyIdListOut, + bool* aSuccessOut); + static nsresult CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams, + nsTArray& aSavedRequestsOut); + + static nsresult StorageMatch(mozIStorageConnection* aConn, + Namespace aNamespace, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + bool* aFoundResponseOut, + SavedResponse* aSavedResponseOut); + static nsresult StorageGetCacheId(mozIStorageConnection* aConn, + Namespace aNamespace, const nsAString& aKey, + bool* aFoundCacheOut, CacheId* aCacheIdOut); + static nsresult StoragePutCache(mozIStorageConnection* aConn, + Namespace aNamespace, const nsAString& aKey, + CacheId aCacheId); + static nsresult StorageForgetCache(mozIStorageConnection* aConn, + Namespace aNamespace, + const nsAString& aKey); + static nsresult StorageGetKeys(mozIStorageConnection* aConn, + Namespace aNamespace, + nsTArray& aKeysOut); + +private: + typedef int32_t EntryId; + + static nsresult QueryAll(mozIStorageConnection* aConn, CacheId aCacheId, + nsTArray& aEntryIdListOut); + static nsresult QueryCache(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + nsTArray& aEntryIdListOut, + uint32_t aMaxResults = UINT32_MAX); + static nsresult MatchByVaryHeader(mozIStorageConnection* aConn, + const PCacheRequest& aRequest, + EntryId entryId, bool* aSuccessOut); + static nsresult DeleteEntries(mozIStorageConnection* aConn, + const nsTArray& aEntryIdList, + nsTArray& aDeletedBodyIdListOut, + uint32_t aPos=0, int32_t aLen=-1); + static nsresult InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId, + const PCacheRequest& aRequest, + const nsID* aRequestBodyId, + const PCacheResponse& aResponse, + const nsID* aResponseBodyId); + static nsresult ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId, + SavedResponse* aSavedResponseOut); + static nsresult ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId, + SavedRequest* aSavedRequestOut); + + static void AppendListParamsToQuery(nsACString& aQuery, + const nsTArray& aEntryIdList, + uint32_t aPos, int32_t aLen); + static nsresult BindListParamsToQuery(mozIStorageStatement* aState, + const nsTArray& aEntryIdList, + uint32_t aPos, int32_t aLen); + static nsresult BindId(mozIStorageStatement* aState, uint32_t aPos, + const nsID* aId); + static nsresult ExtractId(mozIStorageStatement* aState, uint32_t aPos, + nsID* aIdOut); + + DBSchema() = delete; + ~DBSchema() = delete; + + static const int32_t kLatestSchemaVersion; + static const int32_t kMaxEntriesPerStatement; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_DBSchema_h diff --git a/dom/cache/Feature.cpp b/dom/cache/Feature.cpp new file mode 100644 index 0000000000..1e24e51ad6 --- /dev/null +++ b/dom/cache/Feature.cpp @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/Feature.h" + +#include "mozilla/dom/cache/ActorChild.h" +#include "WorkerPrivate.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::dom::workers::Running; +using mozilla::dom::workers::Status; +using mozilla::dom::workers::WorkerPrivate; + +// static +already_AddRefed +Feature::Create(WorkerPrivate* aWorkerPrivate) +{ + MOZ_ASSERT(aWorkerPrivate); + + nsRefPtr feature = new Feature(aWorkerPrivate); + + if (!aWorkerPrivate->AddFeature(aWorkerPrivate->GetJSContext(), feature)) { + return nullptr; + } + + return feature.forget(); +} + +void +Feature::AddActor(ActorChild* aActor) +{ + NS_ASSERT_OWNINGTHREAD(Feature); + MOZ_ASSERT(aActor); + MOZ_ASSERT(!mActorList.Contains(aActor)); + + mActorList.AppendElement(aActor); + + // Allow an actor to be added after we've entered the Notifying case. We + // can't stop the actor creation from racing with out destruction of the + // other actors and we need to wait for this extra one to close as well. + // Signal it should destroy itself right away. + if (mNotified) { + aActor->StartDestroy(); + } +} + +void +Feature::RemoveActor(ActorChild* aActor) +{ + NS_ASSERT_OWNINGTHREAD(Feature); + MOZ_ASSERT(aActor); + + DebugOnly removed = mActorList.RemoveElement(aActor); + + MOZ_ASSERT(removed); + MOZ_ASSERT(!mActorList.Contains(aActor)); +} + +bool +Feature::Notified() const +{ + return mNotified; +} + +bool +Feature::Notify(JSContext* aCx, Status aStatus) +{ + NS_ASSERT_OWNINGTHREAD(Feature); + + if (aStatus <= Running || mNotified) { + return true; + } + + mNotified = true; + + // Start the asynchronous destruction of our actors. These will call back + // into RemoveActor() once the actor is destroyed. + for (uint32_t i = 0; i < mActorList.Length(); ++i) { + mActorList[i]->StartDestroy(); + } + + return true; +} + +Feature::Feature(WorkerPrivate* aWorkerPrivate) + : mWorkerPrivate(aWorkerPrivate) + , mNotified(false) +{ + MOZ_ASSERT(mWorkerPrivate); +} + +Feature::~Feature() +{ + NS_ASSERT_OWNINGTHREAD(Feature); + MOZ_ASSERT(mActorList.IsEmpty()); + + mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/Feature.h b/dom/cache/Feature.h new file mode 100644 index 0000000000..697e53ec08 --- /dev/null +++ b/dom/cache/Feature.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_Feature_h +#define mozilla_dom_cache_Feature_h + +#include "nsISupportsImpl.h" +#include "nsTArray.h" +#include "WorkerFeature.h" + +namespace mozilla { + +namespace workers { +class WorkerPrivate; +} + +namespace dom { +namespace cache { + +class ActorChild; + +class Feature MOZ_FINAL : public workers::WorkerFeature +{ +public: + static already_AddRefed Create(workers::WorkerPrivate* aWorkerPrivate); + + void AddActor(ActorChild* aActor); + void RemoveActor(ActorChild* aActor); + + bool Notified() const; + + // WorkerFeature methods + virtual bool Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE; + +private: + explicit Feature(workers::WorkerPrivate *aWorkerPrivate); + ~Feature(); + + workers::WorkerPrivate* mWorkerPrivate; + nsTArray mActorList; + bool mNotified; + +public: + NS_INLINE_DECL_REFCOUNTING(mozilla::dom::cache::Feature) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_Feature_h diff --git a/dom/cache/FetchPut.cpp b/dom/cache/FetchPut.cpp new file mode 100644 index 0000000000..aea24423ae --- /dev/null +++ b/dom/cache/FetchPut.cpp @@ -0,0 +1,451 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/FetchPut.h" + +#include "mozilla/dom/Fetch.h" +#include "mozilla/dom/FetchDriver.h" +#include "mozilla/dom/Headers.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/PromiseNativeHandler.h" +#include "mozilla/dom/Request.h" +#include "mozilla/dom/Response.h" +#include "mozilla/dom/ResponseBinding.h" +#include "mozilla/dom/UnionTypes.h" +#include "mozilla/dom/cache/ManagerId.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "nsContentUtils.h" +#include "nsNetUtil.h" +#include "nsThreadUtils.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class FetchPut::Runnable MOZ_FINAL : public nsRunnable +{ +public: + explicit Runnable(FetchPut* aFetchPut) + : mFetchPut(aFetchPut) + { + MOZ_ASSERT(mFetchPut); + } + + NS_IMETHOD Run() MOZ_OVERRIDE + { + if (NS_IsMainThread()) + { + mFetchPut->DoFetchOnMainThread(); + return NS_OK; + } + + MOZ_ASSERT(mFetchPut->mInitiatingThread == NS_GetCurrentThread()); + + mFetchPut->DoPutOnWorkerThread(); + + // The FetchPut object must ultimately be freed on the worker thread, + // so make sure we release our reference here. The runnable may end + // up getting deleted on the main thread. + mFetchPut = nullptr; + + return NS_OK; + } + +private: + nsRefPtr mFetchPut; +}; + +class FetchPut::FetchObserver MOZ_FINAL : public FetchDriverObserver +{ +public: + explicit FetchObserver(FetchPut* aFetchPut) + : mFetchPut(aFetchPut) + { + } + + virtual void OnResponseAvailable(InternalResponse* aResponse) MOZ_OVERRIDE + { + MOZ_ASSERT(!mInternalResponse); + mInternalResponse = aResponse; + } + + virtual void OnResponseEnd() MOZ_OVERRIDE + { + mFetchPut->FetchComplete(this, mInternalResponse); + mFetchPut = nullptr; + } + +protected: + virtual ~FetchObserver() { } + +private: + nsRefPtr mFetchPut; + nsRefPtr mInternalResponse; +}; + +// static +nsresult +FetchPut::Create(Listener* aListener, Manager* aManager, + RequestId aRequestId, CacheId aCacheId, + const nsTArray& aRequests, + const nsTArray>& aRequestStreams, + FetchPut** aFetchPutOut) +{ + MOZ_ASSERT(aRequests.Length() == aRequestStreams.Length()); + + // The FetchDriver requires that all requests have a referrer already set. +#ifdef DEBUG + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + if (aRequests[i].referrer() == EmptyString()) { + return NS_ERROR_UNEXPECTED; + } + } +#endif + + nsRefPtr ref = new FetchPut(aListener, aManager, aRequestId, aCacheId, + aRequests, aRequestStreams); + + nsresult rv = ref->DispatchToMainThread(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + ref.forget(aFetchPutOut); + + return NS_OK; +} + +void +FetchPut::ClearListener() +{ + MOZ_ASSERT(mListener); + mListener = nullptr; +} + +FetchPut::FetchPut(Listener* aListener, Manager* aManager, + RequestId aRequestId, CacheId aCacheId, + const nsTArray& aRequests, + const nsTArray>& aRequestStreams) + : mListener(aListener) + , mManager(aManager) + , mRequestId(aRequestId) + , mCacheId(aCacheId) + , mInitiatingThread(NS_GetCurrentThread()) + , mStateList(aRequests.Length()) + , mPendingCount(0) + , mResult(NS_OK) +{ + MOZ_ASSERT(mListener); + MOZ_ASSERT(mManager); + MOZ_ASSERT(aRequests.Length() == aRequestStreams.Length()); + + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + State* s = mStateList.AppendElement(); + s->mPCacheRequest = aRequests[i]; + s->mRequestStream = aRequestStreams[i]; + } + + mManager->AddRefCacheId(mCacheId); +} + +FetchPut::~FetchPut() +{ + MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread()); + MOZ_ASSERT(!mListener); + mManager->RemoveListener(this); + mManager->ReleaseCacheId(mCacheId); +} + +nsresult +FetchPut::DispatchToMainThread() +{ + MOZ_ASSERT(!mRunnable); + + nsRefPtr runnable = new Runnable(this); + + nsresult rv = NS_DispatchToMainThread(runnable, nsIThread::DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + MOZ_ASSERT(!mRunnable); + mRunnable = runnable.forget(); + + return NS_OK; +} + +void +FetchPut::DispatchToInitiatingThread() +{ + MOZ_ASSERT(mRunnable); + + nsresult rv = mInitiatingThread->Dispatch(mRunnable, + nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + MOZ_CRASH("Failed to dispatch to worker thread after fetch completion."); + } + + mRunnable = nullptr; +} + +void +FetchPut::DoFetchOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsRefPtr managerId = mManager->GetManagerId(); + nsCOMPtr principal = managerId->Principal(); + mPendingCount = mStateList.Length(); + + nsCOMPtr loadGroup; + nsresult rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal); + if (NS_WARN_IF(NS_FAILED(rv))) { + MaybeSetError(rv); + MaybeCompleteOnMainThread(); + return; + } + + for (uint32_t i = 0; i < mStateList.Length(); ++i) { + nsRefPtr internalRequest = + ToInternalRequest(mStateList[i].mPCacheRequest); + + // If there is a stream we must clone it so that its still available + // to store in the cache later; + if (mStateList[i].mRequestStream) { + internalRequest->SetBody(mStateList[i].mRequestStream); + nsRefPtr clone = internalRequest->Clone(); + + // The copy construction clone above can change the source stream, + // so get it back out to use when we put this in the cache. + internalRequest->GetBody(getter_AddRefs(mStateList[i].mRequestStream)); + + internalRequest = clone; + } + + nsRefPtr fetchDriver = new FetchDriver(internalRequest, + principal, + loadGroup); + + mStateList[i].mFetchObserver = new FetchObserver(this); + rv = fetchDriver->Fetch(mStateList[i].mFetchObserver); + if (NS_WARN_IF(NS_FAILED(rv))) { + MaybeSetError(rv); + mStateList[i].mFetchObserver = nullptr; + mPendingCount -= 1; + continue; + } + } + + // If they all failed, then we might need to complete main thread immediately + MaybeCompleteOnMainThread(); +} + +void +FetchPut::FetchComplete(FetchObserver* aObserver, + InternalResponse* aInternalResponse) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (aInternalResponse->IsError() && NS_SUCCEEDED(mResult)) { + MaybeSetError(NS_ERROR_FAILURE); + } + + for (uint32_t i = 0; i < mStateList.Length(); ++i) { + if (mStateList[i].mFetchObserver == aObserver) { + ErrorResult rv; + ToPCacheResponseWithoutBody(mStateList[i].mPCacheResponse, + *aInternalResponse, rv); + if (rv.Failed()) { + MaybeSetError(rv.ErrorCode()); + return; + } + aInternalResponse->GetBody(getter_AddRefs(mStateList[i].mResponseStream)); + mStateList[i].mFetchObserver = nullptr; + MOZ_ASSERT(mPendingCount > 0); + mPendingCount -= 1; + MaybeCompleteOnMainThread(); + return; + } + } + + MOZ_ASSERT_UNREACHABLE("Should never get called by unknown fetch observer."); +} + +void +FetchPut::MaybeCompleteOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (mPendingCount > 0) { + return; + } + + DispatchToInitiatingThread(); +} + +void +FetchPut::DoPutOnWorkerThread() +{ + MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread()); + + if (NS_FAILED(mResult)) { + MaybeNotifyListener(); + return; + } + + // These allocate ~4.5k combined on the stack + nsAutoTArray putList; + nsAutoTArray, 16> requestStreamList; + nsAutoTArray, 16> responseStreamList; + + putList.SetCapacity(mStateList.Length()); + requestStreamList.SetCapacity(mStateList.Length()); + responseStreamList.SetCapacity(mStateList.Length()); + + for (uint32_t i = 0; i < mStateList.Length(); ++i) { + // The spec requires us to catch if content tries to insert a set of + // requests that would overwrite each other. + if (MatchInPutList(mStateList[i].mPCacheRequest, putList)) { + MaybeSetError(NS_ERROR_DOM_INVALID_STATE_ERR); + MaybeNotifyListener(); + return; + } + + CacheRequestResponse* entry = putList.AppendElement(); + entry->request() = mStateList[i].mPCacheRequest; + entry->response() = mStateList[i].mPCacheResponse; + requestStreamList.AppendElement(mStateList[i].mRequestStream.forget()); + responseStreamList.AppendElement(mStateList[i].mResponseStream.forget()); + } + mStateList.Clear(); + + mManager->CachePutAll(this, mRequestId, mCacheId, putList, requestStreamList, + responseStreamList); +} + +// static +bool +FetchPut::MatchInPutList(const PCacheRequest& aRequest, + const nsTArray& aPutList) +{ + // This method implements the SW spec QueryCache algorithm against an + // in memory array of Request/Response objects. This essentially the + // same algorithm that is implemented in DBSchema.cpp. Unfortunately + // we cannot unify them because when operating against the real database + // we don't want to load all request/response objects into memory. + + if (!aRequest.method().LowerCaseEqualsLiteral("get") && + !aRequest.method().LowerCaseEqualsLiteral("head")) { + return false; + } + + nsRefPtr requestHeaders = + new InternalHeaders(aRequest.headers()); + + for (uint32_t i = 0; i < aPutList.Length(); ++i) { + const PCacheRequest& cachedRequest = aPutList[i].request(); + const PCacheResponse& cachedResponse = aPutList[i].response(); + + // If the URLs don't match, then just skip to the next entry. + if (aRequest.url() != cachedRequest.url()) { + continue; + } + + nsRefPtr cachedRequestHeaders = + new InternalHeaders(cachedRequest.headers()); + + nsRefPtr cachedResponseHeaders = + new InternalHeaders(cachedResponse.headers()); + + nsAutoTArray varyHeaders; + ErrorResult rv; + cachedResponseHeaders->GetAll(NS_LITERAL_CSTRING("vary"), varyHeaders, rv); + MOZ_ALWAYS_TRUE(!rv.Failed()); + + // Assume the vary headers match until we find a conflict + bool varyHeadersMatch = true; + + for (uint32_t j = 0; j < varyHeaders.Length(); ++j) { + if (varyHeaders[i].EqualsLiteral("*")) { + continue; + } + + // The VARY header could in theory contain an illegal header name. So + // we need to detect the error in the Get() calls below. Treat these + // as not matching. + ErrorResult headerRv; + + nsAutoCString value; + requestHeaders->Get(varyHeaders[j], value, rv); + if (NS_WARN_IF(rv.Failed())) { + varyHeadersMatch = false; + break; + } + + nsAutoCString cachedValue; + cachedRequestHeaders->Get(varyHeaders[j], value, rv); + if (NS_WARN_IF(rv.Failed())) { + varyHeadersMatch = false; + break; + } + + if (value != cachedValue) { + varyHeadersMatch = false; + break; + } + } + + // URL was equal and all vary headers match! + if (varyHeadersMatch) { + return true; + } + } + + return false; +} + +void +FetchPut::OnCachePutAll(RequestId aRequestId, nsresult aRv) +{ + MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread()); + MaybeSetError(aRv); + MaybeNotifyListener(); +} + +void +FetchPut::MaybeSetError(nsresult aRv) +{ + if (NS_FAILED(mResult) || NS_SUCCEEDED(aRv)) { + return; + } + mResult = aRv; +} + +void +FetchPut::MaybeNotifyListener() +{ + MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread()); + if (!mListener) { + return; + } + mListener->OnFetchPut(this, mRequestId, mResult); +} + +nsIGlobalObject* +FetchPut::GetGlobalObject() const +{ + MOZ_CRASH("No global object in parent-size FetchPut operation!"); +} + +#ifdef DEBUG +void +FetchPut::AssertOwningThread() const +{ + MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread()); +} +#endif + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/FetchPut.h b/dom/cache/FetchPut.h new file mode 100644 index 0000000000..21a87bf029 --- /dev/null +++ b/dom/cache/FetchPut.h @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_FetchPut_h +#define mozilla_dom_cache_FetchPut_h + +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/cache/Manager.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/dom/cache/Types.h" +#include "mozilla/dom/cache/TypeUtils.h" +#include "mozilla/nsRefPtr.h" +#include "nsTArray.h" +#include + +class nsIInputStream; +class nsIRunnable; +class nsIThread; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class OwningRequestOrScalarValueString; +class Promise; +class Request; +class RequestOrScalarValueString; +class Response; +template class Sequence; + +namespace cache { + +class FetchPut MOZ_FINAL : public Manager::Listener + , public TypeUtils +{ +public: + typedef std::pair, nsRefPtr> PutPair; + + class Listener + { + public: + virtual void + OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, nsresult aRv) = 0; + }; + + static nsresult + Create(Listener* aListener, Manager* aManager, + RequestId aRequestId, CacheId aCacheId, + const nsTArray& aRequests, + const nsTArray>& aRequestStreams, + FetchPut** aFetchPutOut); + + void ClearListener(); + +private: + class Runnable; + class FetchObserver; + struct State + { + PCacheRequest mPCacheRequest; + nsCOMPtr mRequestStream; + nsRefPtr mFetchObserver; + PCacheResponse mPCacheResponse; + nsCOMPtr mResponseStream; + + nsRefPtr mRequest; + nsRefPtr mResponse; + }; + + FetchPut(Listener* aListener, Manager* aManager, + RequestId aRequestId, CacheId aCacheId, + const nsTArray& aRequests, + const nsTArray>& aRequestStreams); + ~FetchPut(); + + nsresult DispatchToMainThread(); + void DispatchToInitiatingThread(); + + void DoFetchOnMainThread(); + void FetchComplete(FetchObserver* aObserver, + InternalResponse* aInternalResponse); + void MaybeCompleteOnMainThread(); + + void DoPutOnWorkerThread(); + static bool MatchInPutList(const PCacheRequest& aRequest, + const nsTArray& aPutList); + virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) MOZ_OVERRIDE; + + void MaybeSetError(nsresult aRv); + void MaybeNotifyListener(); + + // TypeUtils methods + virtual nsIGlobalObject* GetGlobalObject() const MOZ_OVERRIDE; +#ifdef DEBUG + virtual void AssertOwningThread() const MOZ_OVERRIDE; +#endif + + Listener* mListener; + nsRefPtr mManager; + const RequestId mRequestId; + const CacheId mCacheId; + nsCOMPtr mInitiatingThread; + nsTArray mStateList; + uint32_t mPendingCount; + nsresult mResult; + nsCOMPtr mRunnable; + +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::cache::FetchPut) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_FetchPut_h diff --git a/dom/cache/FileUtils.cpp b/dom/cache/FileUtils.cpp new file mode 100644 index 0000000000..1bfda8b8f0 --- /dev/null +++ b/dom/cache/FileUtils.cpp @@ -0,0 +1,286 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/FileUtils.h" + +#include "mozilla/dom/quota/FileStreams.h" +#include "mozilla/SnappyCompressOutputStream.h" +#include "mozilla/unused.h" +#include "nsIFile.h" +#include "nsIUUIDGenerator.h" +#include "nsNetUtil.h" +#include "nsServiceManagerUtils.h" +#include "nsString.h" +#include "nsThreadUtils.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::dom::quota::FileInputStream; +using mozilla::dom::quota::FileOutputStream; +using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT; +using mozilla::unused; + +// static +nsresult +FileUtils::BodyCreateDir(nsIFile* aBaseDir) +{ + MOZ_ASSERT(aBaseDir); + + nsCOMPtr aBodyDir; + nsresult rv = aBaseDir->Clone(getter_AddRefs(aBodyDir)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aBodyDir->Append(NS_LITERAL_STRING("morgue")); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = aBodyDir->Create(nsIFile::DIRECTORY_TYPE, 0755); + if (rv == NS_ERROR_FILE_ALREADY_EXISTS) { + return NS_OK; + } + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +FileUtils::BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId, + nsIFile** aCacheDirOut) +{ + MOZ_ASSERT(aBaseDir); + MOZ_ASSERT(aCacheDirOut); + + *aCacheDirOut = nullptr; + + nsresult rv = aBaseDir->Clone(aCacheDirOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(*aCacheDirOut); + + rv = (*aCacheDirOut)->Append(NS_LITERAL_STRING("morgue")); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + // Some file systems have poor performance when there are too many files + // in a single directory. Mitigate this issue by spreading the body + // files out into sub-directories. We use the last byte of the ID for + // the name of the sub-directory. + nsAutoString subDirName; + subDirName.AppendInt(aId.m3[7]); + rv = (*aCacheDirOut)->Append(subDirName); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = (*aCacheDirOut)->Create(nsIFile::DIRECTORY_TYPE, 0755); + if (rv == NS_ERROR_FILE_ALREADY_EXISTS) { + return NS_OK; + } + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +FileUtils::BodyStartWriteStream(const QuotaInfo& aQuotaInfo, + nsIFile* aBaseDir, nsIInputStream* aSource, + void* aClosure, + nsAsyncCopyCallbackFun aCallback, nsID* aIdOut, + nsISupports** aCopyContextOut) +{ + MOZ_ASSERT(aBaseDir); + MOZ_ASSERT(aSource); + MOZ_ASSERT(aClosure); + MOZ_ASSERT(aCallback); + MOZ_ASSERT(aIdOut); + MOZ_ASSERT(aCopyContextOut); + + nsresult rv; + nsCOMPtr idGen = + do_GetService("@mozilla.org/uuid-generator;1", &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = idGen->GenerateUUIDInPlace(aIdOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr finalFile; + rv = BodyIdToFile(aBaseDir, *aIdOut, BODY_FILE_FINAL, + getter_AddRefs(finalFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool exists; + rv = finalFile->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(exists)) { return NS_ERROR_FILE_ALREADY_EXISTS; } + + nsCOMPtr tmpFile; + rv = BodyIdToFile(aBaseDir, *aIdOut, BODY_FILE_TMP, getter_AddRefs(tmpFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = tmpFile->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(exists)) { return NS_ERROR_FILE_ALREADY_EXISTS; } + + nsCOMPtr fileStream = + FileOutputStream::Create(PERSISTENCE_TYPE_DEFAULT, aQuotaInfo.mGroup, + aQuotaInfo.mOrigin, tmpFile); + if (NS_WARN_IF(!fileStream)) { return NS_ERROR_UNEXPECTED; } + + nsRefPtr compressed = + new SnappyCompressOutputStream(fileStream); + + nsCOMPtr target = + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); + + rv = NS_AsyncCopy(aSource, compressed, target, NS_ASYNCCOPY_VIA_WRITESEGMENTS, + compressed->BlockSize(), aCallback, aClosure, + true, true, // close streams + aCopyContextOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +void +FileUtils::BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext) +{ + MOZ_ASSERT(aBaseDir); + MOZ_ASSERT(aCopyContext); + + nsresult rv = NS_CancelAsyncCopy(aCopyContext, NS_ERROR_ABORT); + unused << NS_WARN_IF(NS_FAILED(rv)); + + // The partially written file must be cleaned up after the async copy + // makes its callback. +} + +// static +nsresult +FileUtils::BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId) +{ + MOZ_ASSERT(aBaseDir); + + nsCOMPtr tmpFile; + nsresult rv = BodyIdToFile(aBaseDir, aId, BODY_FILE_TMP, getter_AddRefs(tmpFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr finalFile; + rv = BodyIdToFile(aBaseDir, aId, BODY_FILE_FINAL, getter_AddRefs(finalFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsAutoString finalFileName; + rv = finalFile->GetLeafName(finalFileName); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = tmpFile->RenameTo(nullptr, finalFileName); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +// static +nsresult +FileUtils::BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, + const nsID& aId, nsIInputStream** aStreamOut) +{ + MOZ_ASSERT(aBaseDir); + MOZ_ASSERT(aStreamOut); + + nsCOMPtr finalFile; + nsresult rv = BodyIdToFile(aBaseDir, aId, BODY_FILE_FINAL, + getter_AddRefs(finalFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool exists; + rv = finalFile->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(!exists)) { return NS_ERROR_FILE_NOT_FOUND; } + + nsCOMPtr fileStream = + FileInputStream::Create(PERSISTENCE_TYPE_DEFAULT, aQuotaInfo.mGroup, + aQuotaInfo.mOrigin, finalFile); + if (NS_WARN_IF(!fileStream)) { return NS_ERROR_UNEXPECTED; } + + fileStream.forget(aStreamOut); + + return rv; +} + +// static +nsresult +FileUtils::BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray& aIdList) +{ + nsresult rv = NS_OK; + + for (uint32_t i = 0; i < aIdList.Length(); ++i) { + nsCOMPtr tmpFile; + rv = BodyIdToFile(aBaseDir, aIdList[i], BODY_FILE_TMP, + getter_AddRefs(tmpFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = tmpFile->Remove(false /* recursive */); + if (rv == NS_ERROR_FILE_NOT_FOUND || + rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) { + rv = NS_OK; + } + + // Only treat file deletion as a hard failure in DEBUG builds. Users + // can unfortunately hit this on windows if anti-virus is scanning files, + // etc. + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + nsCOMPtr finalFile; + rv = BodyIdToFile(aBaseDir, aIdList[i], BODY_FILE_FINAL, + getter_AddRefs(finalFile)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = finalFile->Remove(false /* recursive */); + if (rv == NS_ERROR_FILE_NOT_FOUND || + rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) { + rv = NS_OK; + } + + // Again, only treat removal as hard failure in debug build. + MOZ_ASSERT(NS_SUCCEEDED(rv)); + } + + return NS_OK; +} + +// static +nsresult +FileUtils::BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, + BodyFileType aType, nsIFile** aBodyFileOut) +{ + MOZ_ASSERT(aBaseDir); + MOZ_ASSERT(aBodyFileOut); + + *aBodyFileOut = nullptr; + + nsresult rv = BodyGetCacheDir(aBaseDir, aId, aBodyFileOut); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(*aBodyFileOut); + + char idString[NSID_LENGTH]; + aId.ToProvidedString(idString); + + NS_ConvertASCIItoUTF16 fileName(idString); + + if (aType == BODY_FILE_FINAL) { + fileName.AppendLiteral(".final"); + } else { + fileName.AppendLiteral(".tmp"); + } + + rv = (*aBodyFileOut)->Append(fileName); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/FileUtils.h b/dom/cache/FileUtils.h new file mode 100644 index 0000000000..8f9cf16fe1 --- /dev/null +++ b/dom/cache/FileUtils.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_FileUtils_h +#define mozilla_dom_cache_FileUtils_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/cache/Types.h" +#include "nsStreamUtils.h" +#include "nsTArrayForwardDeclare.h" + +struct nsID; +class nsIFile; + +namespace mozilla { +namespace dom { +namespace cache { + +// TODO: remove static class and use functions in cache namespace (bug 1110485) +class FileUtils MOZ_FINAL +{ +public: + enum BodyFileType + { + BODY_FILE_FINAL, + BODY_FILE_TMP + }; + + static nsresult BodyCreateDir(nsIFile* aBaseDir); + static nsresult BodyGetCacheDir(nsIFile* aBaseDir, const nsID& aId, + nsIFile** aCacheDirOut); + + static nsresult + BodyStartWriteStream(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, + nsIInputStream* aSource, void* aClosure, + nsAsyncCopyCallbackFun aCallback, nsID* aIdOut, + nsISupports** aCopyContextOut); + + static void + BodyCancelWrite(nsIFile* aBaseDir, nsISupports* aCopyContext); + + static nsresult + BodyFinalizeWrite(nsIFile* aBaseDir, const nsID& aId); + + static nsresult + BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId, + nsIInputStream** aStreamOut); + + static nsresult + BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray& aIdList); + +private: + static nsresult + BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType, + nsIFile** aBodyFileOut); + + FileUtils() = delete; + ~FileUtils() = delete; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_FileUtils_h diff --git a/dom/cache/IPCUtils.h b/dom/cache/IPCUtils.h new file mode 100644 index 0000000000..48498e0f43 --- /dev/null +++ b/dom/cache/IPCUtils.h @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_IPCUtils_h +#define mozilla_dom_cache_IPCUtils_h + +#include "ipc/IPCMessageUtils.h" +#include "mozilla/dom/cache/Types.h" + +namespace IPC { + template<> + struct ParamTraits : + public ContiguousEnumSerializer + {}; +} + +#endif // mozilla_dom_cache_IPCUtils_h diff --git a/dom/cache/Manager.cpp b/dom/cache/Manager.cpp new file mode 100644 index 0000000000..66c09487f9 --- /dev/null +++ b/dom/cache/Manager.cpp @@ -0,0 +1,1869 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/Manager.h" + +#include "mozilla/Mutex.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/unused.h" +#include "mozilla/dom/cache/Context.h" +#include "mozilla/dom/cache/DBAction.h" +#include "mozilla/dom/cache/DBSchema.h" +#include "mozilla/dom/cache/FileUtils.h" +#include "mozilla/dom/cache/ManagerId.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/dom/cache/SavedTypes.h" +#include "mozilla/dom/cache/StreamList.h" +#include "mozilla/dom/cache/Types.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "mozStorageHelper.h" +#include "nsAutoPtr.h" +#include "nsIInputStream.h" +#include "nsID.h" +#include "nsIFile.h" +#include "nsIThread.h" +#include "nsThreadUtils.h" +#include "nsTObserverArray.h" + +namespace { + +using mozilla::unused; +using mozilla::dom::cache::Action; +using mozilla::dom::cache::DBSchema; +using mozilla::dom::cache::FileUtils; +using mozilla::dom::cache::QuotaInfo; +using mozilla::dom::cache::SyncDBAction; + +// An Action that is executed when a Context is first created. It ensures that +// the directory and database are setup properly. This lets other actions +// not worry about these details. +class SetupAction MOZ_FINAL : public SyncDBAction +{ +public: + SetupAction() + : SyncDBAction(DBAction::Create) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + // TODO: init maintainance marker (bug 1110446) + // TODO: perform maintainance if necessary (bug 1110446) + // TODO: find orphaned caches in database (bug 1110446) + // TODO: have Context create/delete marker files in constructor/destructor + // and only do expensive maintenance if that marker is present (bug 1110446) + + nsresult rv = FileUtils::BodyCreateDir(aDBDir); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + mozStorageTransaction trans(aConn, false, + mozIStorageConnection::TRANSACTION_IMMEDIATE); + + rv = DBSchema::CreateSchema(aConn); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = trans.Commit(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; + } +}; + +// ---------------------------------------------------------------------------- + +// Action that is executed when we determine that content has stopped using +// a body file that has been orphaned. +class DeleteOrphanedBodyAction MOZ_FINAL : public Action +{ +public: + explicit DeleteOrphanedBodyAction(const nsTArray& aDeletedBodyIdList) + : mDeletedBodyIdList(aDeletedBodyIdList) + { } + + explicit DeleteOrphanedBodyAction(const nsID& aBodyId) + { + mDeletedBodyIdList.AppendElement(aBodyId); + } + + virtual void + RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo) MOZ_OVERRIDE + { + MOZ_ASSERT(aResolver); + MOZ_ASSERT(aQuotaInfo.mDir); + + if (IsCanceled()) { + // TODO: handle orphaned files (bug 1110446) + aResolver->Resolve(NS_ERROR_ABORT); + return; + } + + nsCOMPtr dbDir; + nsresult rv = aQuotaInfo.mDir->Clone(getter_AddRefs(dbDir)); + if (NS_WARN_IF(NS_FAILED(rv))) { + aResolver->Resolve(rv); + return; + } + + rv = dbDir->Append(NS_LITERAL_STRING("cache")); + if (NS_WARN_IF(NS_FAILED(rv))) { + aResolver->Resolve(rv); + return; + } + + rv = FileUtils::BodyDeleteFiles(dbDir, mDeletedBodyIdList); + unused << NS_WARN_IF(NS_FAILED(rv)); + + aResolver->Resolve(rv); + } + +private: + nsTArray mDeletedBodyIdList; +}; + +} // anonymous namespace + +namespace mozilla { +namespace dom { +namespace cache { + +// ---------------------------------------------------------------------------- + +// Singleton class to track Manager instances and ensure there is only +// one for each unique ManagerId. +class Manager::Factory +{ +public: + friend class StaticAutoPtr; + + static nsresult + GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut) + { + mozilla::ipc::AssertIsOnBackgroundThread(); + + // Ensure there is a factory instance. This forces the Get() call + // below to use the same factory. + nsresult rv = MaybeCreateInstance(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsRefPtr ref = Get(aManagerId); + if (!ref) { + // TODO: replace this with a thread pool (bug 1119864) + nsCOMPtr ioThread; + rv = NS_NewNamedThread("DOMCacheThread", getter_AddRefs(ioThread)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + ref = new Manager(aManagerId, ioThread); + + MOZ_ASSERT(!sFactory->mManagerList.Contains(ref)); + sFactory->mManagerList.AppendElement(ref); + } + + ref.forget(aManagerOut); + + return NS_OK; + } + + static already_AddRefed + Get(ManagerId* aManagerId) + { + mozilla::ipc::AssertIsOnBackgroundThread(); + + nsresult rv = MaybeCreateInstance(); + if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } + + ManagerList::ForwardIterator iter(sFactory->mManagerList); + while (iter.HasMore()) { + nsRefPtr manager = iter.GetNext(); + if (*manager->mManagerId == *aManagerId) { + return manager.forget(); + } + } + + return nullptr; + } + + static void + Remove(Manager* aManager) + { + mozilla::ipc::AssertIsOnBackgroundThread(); + MOZ_ASSERT(aManager); + MOZ_ASSERT(sFactory); + + MOZ_ALWAYS_TRUE(sFactory->mManagerList.RemoveElement(aManager)); + + // clean up the factory singleton if there are no more managers + if (sFactory->mManagerList.IsEmpty()) { + DestroyInstance(); + } + } + + static void + StartShutdownAllOnMainThread() + { + MOZ_ASSERT(NS_IsMainThread()); + + // Lock for sFactoryShutdown and sBackgroundThread. + StaticMutexAutoLock lock(sMutex); + + sFactoryShutdown = true; + + if (!sBackgroundThread) { + return; + } + + // Guaranteed to succeed because we should be shutdown before the + // background thread is destroyed. + nsCOMPtr runnable = new ShutdownAllRunnable(); + nsresult rv = sBackgroundThread->Dispatch(runnable, + nsIThread::DISPATCH_NORMAL); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv)); + } + + static bool + IsShutdownAllCompleteOnMainThread() + { + MOZ_ASSERT(NS_IsMainThread()); + StaticMutexAutoLock lock(sMutex); + // Infer whether we have shutdown using the sBackgroundThread value. We + // guarantee this is nullptr when sFactory is destroyed. + return sFactoryShutdown && !sBackgroundThread; + } + +private: + Factory() + { + MOZ_COUNT_CTOR(cache::Manager::Factory); + } + + ~Factory() + { + MOZ_COUNT_DTOR(cache::Manager::Factory); + MOZ_ASSERT(mManagerList.IsEmpty()); + } + + static nsresult + MaybeCreateInstance() + { + mozilla::ipc::AssertIsOnBackgroundThread(); + + if (!sFactory) { + // Be clear about what we are locking. sFactory is bg thread only, so + // we don't need to lock it here. Just protect sFactoryShutdown and + // sBackgroundThread. + { + StaticMutexAutoLock lock(sMutex); + + if (sFactoryShutdown) { + return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; + } + + // Cannot use ClearOnShutdown() because we're on the background thread. + // This is automatically cleared when Factory::Remove() calls + // DestroyInstance(). + MOZ_ASSERT(!sBackgroundThread); + sBackgroundThread = NS_GetCurrentThread(); + } + + // We cannot use ClearOnShutdown() here because we're not on the main + // thread. Instead, we delete sFactory in Factory::Remove() after the + // last manager is removed. ShutdownObserver ensures this happens + // before shutdown. + sFactory = new Factory(); + } + + // Never return sFactory to code outside Factory. We need to delete it + // out from under ourselves just before we return from Remove(). This + // would be (even more) dangerous if other code had a pointer to the + // factory itself. + + return NS_OK; + } + + static void + DestroyInstance() + { + mozilla::ipc::AssertIsOnBackgroundThread(); + MOZ_ASSERT(sFactory); + + // Be clear about what we are locking. sFactory is bg thread only, so + // we don't need to lock it here. Just protect sBackgroundThread. + { + StaticMutexAutoLock lock(sMutex); + MOZ_ASSERT(sBackgroundThread); + sBackgroundThread = nullptr; + } + + sFactory = nullptr; + } + + static void + ShutdownAllOnBackgroundThread() + { + mozilla::ipc::AssertIsOnBackgroundThread(); + + // The factory shutdown between when shutdown started on main thread and + // when we could start shutdown on the worker thread. Just declare + // shutdown complete. The sFactoryShutdown flag prevents the factory + // from racing to restart here. + if (!sFactory) { +#ifdef DEBUG + StaticMutexAutoLock lock(sMutex); + MOZ_ASSERT(!sBackgroundThread); +#endif + return; + } + + MOZ_ASSERT(!sFactory->mManagerList.IsEmpty()); + + ManagerList::ForwardIterator iter(sFactory->mManagerList); + while (iter.HasMore()) { + nsRefPtr manager = iter.GetNext(); + manager->Shutdown(); + } + } + + class ShutdownAllRunnable MOZ_FINAL : public nsRunnable + { + public: + NS_IMETHOD + Run() MOZ_OVERRIDE + { + mozilla::ipc::AssertIsOnBackgroundThread(); + ShutdownAllOnBackgroundThread(); + return NS_OK; + } + private: + ~ShutdownAllRunnable() { } + }; + + // Singleton created on demand and deleted when last Manager is cleared + // in Remove(). + // PBackground thread only. + static StaticAutoPtr sFactory; + + // protects following static attributes + static StaticMutex sMutex; + + // Indicate if shutdown has occurred to block re-creation of sFactory. + // Must hold sMutex to access. + static bool sFactoryShutdown; + + // Background thread owning all Manager objects. Only set while sFactory is + // set. + // Must hold sMutex to access. + static StaticRefPtr sBackgroundThread; + + // Weak references as we don't want to keep Manager objects alive forever. + // When a Manager is destroyed it calls Factory::Remove() to clear itself. + // PBackground thread only. + typedef nsTObserverArray ManagerList; + ManagerList mManagerList; +}; + +// static +StaticAutoPtr Manager::Factory::sFactory; + +// static +StaticMutex Manager::Factory::sMutex; + +// static +bool Manager::Factory::sFactoryShutdown = false; + +// static +StaticRefPtr Manager::Factory::sBackgroundThread; + +// ---------------------------------------------------------------------------- + +// Abstract class to help implement the various Actions. The vast majority +// of Actions are synchronous and need to report back to a Listener on the +// Manager. +class Manager::BaseAction : public SyncDBAction +{ +protected: + BaseAction(Manager* aManager, ListenerId aListenerId, RequestId aRequestId) + : SyncDBAction(DBAction::Existing) + , mManager(aManager) + , mListenerId(aListenerId) + , mRequestId (aRequestId) + { + } + + virtual void + Complete(Listener* aListener, nsresult aRv) = 0; + + virtual void + CompleteOnInitiatingThread(nsresult aRv) MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(Manager::BaseAction); + Listener* listener = mManager->GetListener(mListenerId); + if (listener) { + Complete(listener, aRv); + } + + // ensure we release the manager on the initiating thread + mManager = nullptr; + } + + nsRefPtr mManager; + const ListenerId mListenerId; + const RequestId mRequestId; +}; + +// ---------------------------------------------------------------------------- + +// Action that is executed when we determine that content has stopped using +// a Cache object that has been orphaned. +class Manager::DeleteOrphanedCacheAction MOZ_FINAL : public SyncDBAction +{ +public: + DeleteOrphanedCacheAction(Manager* aManager, CacheId aCacheId) + : SyncDBAction(DBAction::Existing) + , mManager(aManager) + , mCacheId(aCacheId) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + mozStorageTransaction trans(aConn, false, + mozIStorageConnection::TRANSACTION_IMMEDIATE); + + nsresult rv = DBSchema::DeleteCache(aConn, mCacheId, mDeletedBodyIdList); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = trans.Commit(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; + } + + virtual void + CompleteOnInitiatingThread(nsresult aRv) MOZ_OVERRIDE + { + mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList); + + // ensure we release the manager on the initiating thread + mManager = nullptr; + } + +private: + nsRefPtr mManager; + const CacheId mCacheId; + nsTArray mDeletedBodyIdList; +}; + +// ---------------------------------------------------------------------------- + +class Manager::CacheMatchAction MOZ_FINAL : public Manager::BaseAction +{ +public: + CacheMatchAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + StreamList* aStreamList) + : BaseAction(aManager, aListenerId, aRequestId) + , mCacheId(aCacheId) + , mRequest(aRequest) + , mParams(aParams) + , mStreamList(aStreamList) + , mFoundResponse(false) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + nsresult rv = DBSchema::CacheMatch(aConn, mCacheId, mRequest, mParams, + &mFoundResponse, &mResponse); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!mFoundResponse || !mResponse.mHasBodyId) { + return rv; + } + + nsCOMPtr stream; + rv = FileUtils::BodyOpen(aQuotaInfo, aDBDir, mResponse.mBodyId, + getter_AddRefs(stream)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(!stream)) { return NS_ERROR_FILE_NOT_FOUND; } + + mStreamList->Add(mResponse.mBodyId, stream); + + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + if (!mFoundResponse) { + aListener->OnCacheMatch(mRequestId, aRv, nullptr, nullptr); + } else { + mStreamList->Activate(mCacheId); + aListener->OnCacheMatch(mRequestId, aRv, &mResponse, mStreamList); + } + mStreamList = nullptr; + } + + virtual bool MatchesCacheId(CacheId aCacheId) const MOZ_OVERRIDE + { + return aCacheId == mCacheId; + } + +private: + const CacheId mCacheId; + const PCacheRequest mRequest; + const PCacheQueryParams mParams; + nsRefPtr mStreamList; + bool mFoundResponse; + SavedResponse mResponse; +}; + +// ---------------------------------------------------------------------------- + +class Manager::CacheMatchAllAction MOZ_FINAL : public Manager::BaseAction +{ +public: + CacheMatchAllAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, CacheId aCacheId, + const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams, + StreamList* aStreamList) + : BaseAction(aManager, aListenerId, aRequestId) + , mCacheId(aCacheId) + , mRequestOrVoid(aRequestOrVoid) + , mParams(aParams) + , mStreamList(aStreamList) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + nsresult rv = DBSchema::CacheMatchAll(aConn, mCacheId, mRequestOrVoid, + mParams, mSavedResponses); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + for (uint32_t i = 0; i < mSavedResponses.Length(); ++i) { + if (!mSavedResponses[i].mHasBodyId) { + continue; + } + + nsCOMPtr stream; + rv = FileUtils::BodyOpen(aQuotaInfo, aDBDir, + mSavedResponses[i].mBodyId, + getter_AddRefs(stream)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(!stream)) { return NS_ERROR_FILE_NOT_FOUND; } + + mStreamList->Add(mSavedResponses[i].mBodyId, stream); + } + + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + mStreamList->Activate(mCacheId); + aListener->OnCacheMatchAll(mRequestId, aRv, mSavedResponses, mStreamList); + mStreamList = nullptr; + } + + virtual bool MatchesCacheId(CacheId aCacheId) const MOZ_OVERRIDE + { + return aCacheId == mCacheId; + } + +private: + const CacheId mCacheId; + const PCacheRequestOrVoid mRequestOrVoid; + const PCacheQueryParams mParams; + nsRefPtr mStreamList; + nsTArray mSavedResponses; +}; + +// ---------------------------------------------------------------------------- + +// This is the most complex Action. It puts a request/response pair into the +// Cache. It does not complete until all of the body data has been saved to +// disk. This means its an asynchronous Action. +class Manager::CachePutAllAction MOZ_FINAL : public DBAction +{ +public: + CachePutAllAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, CacheId aCacheId, + const nsTArray& aPutList, + const nsTArray>& aRequestStreamList, + const nsTArray>& aResponseStreamList) + : DBAction(DBAction::Existing) + , mManager(aManager) + , mListenerId(aListenerId) + , mRequestId(aRequestId) + , mCacheId(aCacheId) + , mList(aPutList.Length()) + , mExpectedAsyncCopyCompletions(1) + , mAsyncResult(NS_OK) + , mMutex("cache::Manager::CachePutAllAction") + { + MOZ_ASSERT(!aPutList.IsEmpty()); + MOZ_ASSERT(aPutList.Length() == aRequestStreamList.Length()); + MOZ_ASSERT(aPutList.Length() == aResponseStreamList.Length()); + + for (uint32_t i = 0; i < aPutList.Length(); ++i) { + Entry* entry = mList.AppendElement(); + entry->mRequest = aPutList[i].request(); + entry->mRequestStream = aRequestStreamList[i]; + entry->mResponse = aPutList[i].response(); + entry->mResponseStream = aResponseStreamList[i]; + } + } + +private: + ~CachePutAllAction() { } + + virtual void + RunWithDBOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo, + nsIFile* aDBDir, mozIStorageConnection* aConn) MOZ_OVERRIDE + { + MOZ_ASSERT(aResolver); + MOZ_ASSERT(aDBDir); + MOZ_ASSERT(aConn); + MOZ_ASSERT(!mResolver); + MOZ_ASSERT(!mDBDir); + MOZ_ASSERT(!mConn); + + MOZ_ASSERT(!mTargetThread); + mTargetThread = NS_GetCurrentThread(); + MOZ_ASSERT(mTargetThread); + + // We should be pre-initialized to expect one async completion. This is + // the "manual" completion we call at the end of this method in all + // cases. + MOZ_ASSERT(mExpectedAsyncCopyCompletions == 1); + + mResolver = aResolver; + mDBDir = aDBDir; + mConn = aConn; + + // File bodies are streamed to disk via asynchronous copying. Start + // this copying now. Each copy will eventually result in a call + // to OnAsyncCopyComplete(). + nsresult rv = NS_OK; + for (uint32_t i = 0; i < mList.Length(); ++i) { + rv = StartStreamCopy(aQuotaInfo, mList[i], RequestStream, + &mExpectedAsyncCopyCompletions); + if (NS_WARN_IF(NS_FAILED(rv))) { + break; + } + + rv = StartStreamCopy(aQuotaInfo, mList[i], ResponseStream, + &mExpectedAsyncCopyCompletions); + if (NS_WARN_IF(NS_FAILED(rv))) { + break; + } + } + + + // Always call OnAsyncCopyComplete() manually here. This covers the + // case where there is no async copying and also reports any startup + // errors correctly. If we hit an error, then OnAsyncCopyComplete() + // will cancel any async copying. + OnAsyncCopyComplete(rv); + } + + // Called once for each asynchronous file copy whether it succeeds or + // fails. If a file copy is canceled, it still calls this method with + // an error code. + void + OnAsyncCopyComplete(nsresult aRv) + { + MOZ_ASSERT(mTargetThread == NS_GetCurrentThread()); + MOZ_ASSERT(mConn); + MOZ_ASSERT(mResolver); + MOZ_ASSERT(mExpectedAsyncCopyCompletions > 0); + + // Explicitly check for cancellation here to catch a race condition. + // Consider: + // + // 1) NS_AsyncCopy() executes on IO thread, but has not saved its + // copy context yet. + // 2) CancelAllStreamCopying() occurs on PBackground thread + // 3) Copy context from (1) is saved on IO thread. + // + // Checking for cancellation here catches this condition when we + // first call OnAsyncCopyComplete() manually from RunWithDBOnTarget(). + // + // This explicit cancellation check also handles the case where we + // are canceled just after all stream copying completes. We should + // abort the synchronous DB operations in this case if we have not + // started them yet. + if (NS_SUCCEEDED(aRv) && IsCanceled()) { + aRv = NS_ERROR_ABORT; + } + + // If any of the async copies fail, we need to still wait for them all to + // complete. Cancel any other streams still working and remember the + // error. All canceled streams will call OnAsyncCopyComplete(). + if (NS_FAILED(aRv) && NS_SUCCEEDED(mAsyncResult)) { + CancelAllStreamCopying(); + mAsyncResult = aRv; + } + + // Check to see if async copying is still on-going. If so, then simply + // return for now. We must wait for a later OnAsyncCopyComplete() call. + mExpectedAsyncCopyCompletions -= 1; + if (mExpectedAsyncCopyCompletions > 0) { + return; + } + + // We have finished with all async copying. Indicate this by clearing all + // our copy contexts. + { + MutexAutoLock lock(mMutex); + mCopyContextList.Clear(); + } + + // An error occurred while async copying. Terminate the Action. + // DoResolve() will clean up any files we may have written. + if (NS_FAILED(mAsyncResult)) { + DoResolve(mAsyncResult); + return; + } + + mozStorageTransaction trans(mConn, false, + mozIStorageConnection::TRANSACTION_IMMEDIATE); + + nsresult rv = NS_OK; + for (uint32_t i = 0; i < mList.Length(); ++i) { + Entry& e = mList[i]; + if (e.mRequestStream) { + rv = FileUtils::BodyFinalizeWrite(mDBDir, e.mRequestBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { + DoResolve(rv); + return; + } + } + if (e.mResponseStream) { + rv = FileUtils::BodyFinalizeWrite(mDBDir, e.mResponseBodyId); + if (NS_WARN_IF(NS_FAILED(rv))) { + DoResolve(rv); + return; + } + } + + rv = DBSchema::CachePut(mConn, mCacheId, e.mRequest, + e.mRequestStream ? &e.mRequestBodyId : nullptr, + e.mResponse, + e.mResponseStream ? &e.mResponseBodyId : nullptr, + mDeletedBodyIdList); + if (NS_WARN_IF(NS_FAILED(rv))) { + DoResolve(rv); + return; + } + } + + rv = trans.Commit(); + unused << NS_WARN_IF(NS_FAILED(rv)); + + DoResolve(rv); + } + + virtual void + CompleteOnInitiatingThread(nsresult aRv) MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(Action); + + for (uint32_t i = 0; i < mList.Length(); ++i) { + mList[i].mRequestStream = nullptr; + mList[i].mResponseStream = nullptr; + } + + mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList); + + Listener* listener = mManager->GetListener(mListenerId); + mManager = nullptr; + if (listener) { + listener->OnCachePutAll(mRequestId, aRv); + } + } + + virtual void + CancelOnInitiatingThread() MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(Action); + Action::CancelOnInitiatingThread(); + CancelAllStreamCopying(); + } + + virtual bool MatchesCacheId(CacheId aCacheId) const MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(Action); + return aCacheId == mCacheId; + } + + struct Entry + { + PCacheRequest mRequest; + nsCOMPtr mRequestStream; + nsID mRequestBodyId; + nsCOMPtr mRequestCopyContext; + + PCacheResponse mResponse; + nsCOMPtr mResponseStream; + nsID mResponseBodyId; + nsCOMPtr mResponseCopyContext; + }; + + enum StreamId + { + RequestStream, + ResponseStream + }; + + nsresult + StartStreamCopy(const QuotaInfo& aQuotaInfo, Entry& aEntry, + StreamId aStreamId, uint32_t* aCopyCountOut) + { + MOZ_ASSERT(mTargetThread == NS_GetCurrentThread()); + MOZ_ASSERT(aCopyCountOut); + + if (IsCanceled()) { + return NS_ERROR_ABORT; + } + + nsCOMPtr source; + nsID* bodyId; + + if (aStreamId == RequestStream) { + source = aEntry.mRequestStream; + bodyId = &aEntry.mRequestBodyId; + } else { + MOZ_ASSERT(aStreamId == ResponseStream); + source = aEntry.mResponseStream; + bodyId = &aEntry.mResponseBodyId; + } + + if (!source) { + return NS_OK; + } + + nsCOMPtr copyContext; + + nsresult rv = FileUtils::BodyStartWriteStream(aQuotaInfo, mDBDir, source, + this, AsyncCopyCompleteFunc, + bodyId, + getter_AddRefs(copyContext)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + mBodyIdWrittenList.AppendElement(*bodyId); + + if (copyContext) { + MutexAutoLock lock(mMutex); + mCopyContextList.AppendElement(copyContext); + } + + *aCopyCountOut += 1; + + return rv; + } + + void + CancelAllStreamCopying() + { + // May occur on either owning thread or target thread + MutexAutoLock lock(mMutex); + for (uint32_t i = 0; i < mCopyContextList.Length(); ++i) { + FileUtils::BodyCancelWrite(mDBDir, mCopyContextList[i]); + } + mCopyContextList.Clear(); + } + + static void + AsyncCopyCompleteFunc(void* aClosure, nsresult aRv) + { + // May be on any thread, including STS event target. + MOZ_ASSERT(aClosure); + nsRefPtr action = static_cast(aClosure); + action->CallOnAsyncCopyCompleteOnTargetThread(aRv); + } + + void + CallOnAsyncCopyCompleteOnTargetThread(nsresult aRv) + { + // May be on any thread, including STS event target. + nsCOMPtr runnable = NS_NewRunnableMethodWithArg( + this, &CachePutAllAction::OnAsyncCopyComplete, aRv); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED( + mTargetThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL))); + } + + void + DoResolve(nsresult aRv) + { + MOZ_ASSERT(mTargetThread == NS_GetCurrentThread()); + + // DoResolve() must not be called until all async copying has completed. +#ifdef DEBUG + { + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mCopyContextList.IsEmpty()); + } +#endif + + // Clean up any files we might have written before hitting the error. + if (NS_FAILED(aRv)) { + FileUtils::BodyDeleteFiles(mDBDir, mBodyIdWrittenList); + } + + // Must be released on the target thread where it was opened. + mConn = nullptr; + + // Drop our ref to the target thread as we are done with this thread. + // Also makes our thread assertions catch any incorrect method calls + // after resolve. + mTargetThread = nullptr; + + // Make sure to de-ref the resolver per the Action API contract. + nsRefPtr resolver; + mResolver.swap(resolver); + resolver->Resolve(aRv); + } + + // initiating thread only + nsRefPtr mManager; + const ListenerId mListenerId; + const RequestId mRequestId; + + // Set on initiating thread, read on target thread. State machine guarantees + // these are not modified while being read by the target thread. + const CacheId mCacheId; + nsTArray mList; + uint32_t mExpectedAsyncCopyCompletions; + + // target thread only + nsRefPtr mResolver; + nsCOMPtr mDBDir; + nsCOMPtr mConn; + nsCOMPtr mTargetThread; + nsresult mAsyncResult; + nsTArray mBodyIdWrittenList; + + // Written to on target thread, accessed on initiating thread after target + // thread activity is guaranteed complete + nsTArray mDeletedBodyIdList; + + // accessed from any thread while mMutex locked + Mutex mMutex; + nsTArray> mCopyContextList; +}; + +// ---------------------------------------------------------------------------- + +class Manager::CacheDeleteAction MOZ_FINAL : public Manager::BaseAction +{ +public: + CacheDeleteAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) + : BaseAction(aManager, aListenerId, aRequestId) + , mCacheId(aCacheId) + , mRequest(aRequest) + , mParams(aParams) + , mSuccess(false) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + mozStorageTransaction trans(aConn, false, + mozIStorageConnection::TRANSACTION_IMMEDIATE); + + nsresult rv = DBSchema::CacheDelete(aConn, mCacheId, mRequest, mParams, + mDeletedBodyIdList, &mSuccess); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = trans.Commit(); + if (NS_WARN_IF(NS_FAILED(rv))) { + mSuccess = false; + return rv; + } + + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList); + aListener->OnCacheDelete(mRequestId, aRv, mSuccess); + } + + virtual bool MatchesCacheId(CacheId aCacheId) const MOZ_OVERRIDE + { + return aCacheId == mCacheId; + } + +private: + const CacheId mCacheId; + const PCacheRequest mRequest; + const PCacheQueryParams mParams; + bool mSuccess; + nsTArray mDeletedBodyIdList; +}; + +// ---------------------------------------------------------------------------- + +class Manager::CacheKeysAction MOZ_FINAL : public Manager::BaseAction +{ +public: + CacheKeysAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, CacheId aCacheId, + const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams, + StreamList* aStreamList) + : BaseAction(aManager, aListenerId, aRequestId) + , mCacheId(aCacheId) + , mRequestOrVoid(aRequestOrVoid) + , mParams(aParams) + , mStreamList(aStreamList) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + nsresult rv = DBSchema::CacheKeys(aConn, mCacheId, mRequestOrVoid, mParams, + mSavedRequests); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + for (uint32_t i = 0; i < mSavedRequests.Length(); ++i) { + if (!mSavedRequests[i].mHasBodyId) { + continue; + } + + nsCOMPtr stream; + rv = FileUtils::BodyOpen(aQuotaInfo, aDBDir, + mSavedRequests[i].mBodyId, + getter_AddRefs(stream)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(!stream)) { return NS_ERROR_FILE_NOT_FOUND; } + + mStreamList->Add(mSavedRequests[i].mBodyId, stream); + } + + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + mStreamList->Activate(mCacheId); + aListener->OnCacheKeys(mRequestId, aRv, mSavedRequests, mStreamList); + mStreamList = nullptr; + } + + virtual bool MatchesCacheId(CacheId aCacheId) const MOZ_OVERRIDE + { + return aCacheId == mCacheId; + } + +private: + const CacheId mCacheId; + const PCacheRequestOrVoid mRequestOrVoid; + const PCacheQueryParams mParams; + nsRefPtr mStreamList; + nsTArray mSavedRequests; +}; + +// ---------------------------------------------------------------------------- + +class Manager::StorageMatchAction MOZ_FINAL : public Manager::BaseAction +{ +public: + StorageMatchAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, Namespace aNamespace, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams, + StreamList* aStreamList) + : BaseAction(aManager, aListenerId, aRequestId) + , mNamespace(aNamespace) + , mRequest(aRequest) + , mParams(aParams) + , mStreamList(aStreamList) + , mFoundResponse(false) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + nsresult rv = DBSchema::StorageMatch(aConn, mNamespace, mRequest, mParams, + &mFoundResponse, &mSavedResponse); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!mFoundResponse || !mSavedResponse.mHasBodyId) { + return rv; + } + + nsCOMPtr stream; + rv = FileUtils::BodyOpen(aQuotaInfo, aDBDir, mSavedResponse.mBodyId, + getter_AddRefs(stream)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (NS_WARN_IF(!stream)) { return NS_ERROR_FILE_NOT_FOUND; } + + mStreamList->Add(mSavedResponse.mBodyId, stream); + + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + if (!mFoundResponse) { + aListener->OnStorageMatch(mRequestId, aRv, nullptr, nullptr); + } else { + mStreamList->Activate(mSavedResponse.mCacheId); + aListener->OnStorageMatch(mRequestId, aRv, &mSavedResponse, mStreamList); + } + mStreamList = nullptr; + } + +private: + const Namespace mNamespace; + const PCacheRequest mRequest; + const PCacheQueryParams mParams; + nsRefPtr mStreamList; + bool mFoundResponse; + SavedResponse mSavedResponse; +}; + +// ---------------------------------------------------------------------------- + +class Manager::StorageHasAction MOZ_FINAL : public Manager::BaseAction +{ +public: + StorageHasAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, Namespace aNamespace, + const nsAString& aKey) + : BaseAction(aManager, aListenerId, aRequestId) + , mNamespace(aNamespace) + , mKey(aKey) + , mCacheFound(false) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + CacheId cacheId; + return DBSchema::StorageGetCacheId(aConn, mNamespace, mKey, + &mCacheFound, &cacheId); + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + aListener->OnStorageHas(mRequestId, aRv, mCacheFound); + } + +private: + const Namespace mNamespace; + const nsString mKey; + bool mCacheFound; +}; + +// ---------------------------------------------------------------------------- + +class Manager::StorageOpenAction MOZ_FINAL : public Manager::BaseAction +{ +public: + StorageOpenAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, Namespace aNamespace, + const nsAString& aKey) + : BaseAction(aManager, aListenerId, aRequestId) + , mNamespace(aNamespace) + , mKey(aKey) + , mCacheId(0) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + // Cache does not exist, create it instead + mozStorageTransaction trans(aConn, false, + mozIStorageConnection::TRANSACTION_IMMEDIATE); + + // Look for existing cache + bool cacheFound; + nsresult rv = DBSchema::StorageGetCacheId(aConn, mNamespace, mKey, + &cacheFound, &mCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + if (cacheFound) { + return rv; + } + + rv = DBSchema::CreateCache(aConn, &mCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = DBSchema::StoragePutCache(aConn, mNamespace, mKey, mCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = trans.Commit(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + aListener->OnStorageOpen(mRequestId, aRv, mCacheId); + } + +private: + const Namespace mNamespace; + const nsString mKey; + CacheId mCacheId; +}; + +// ---------------------------------------------------------------------------- + +class Manager::StorageDeleteAction MOZ_FINAL : public Manager::BaseAction +{ +public: + StorageDeleteAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, Namespace aNamespace, + const nsAString& aKey) + : BaseAction(aManager, aListenerId, aRequestId) + , mNamespace(aNamespace) + , mKey(aKey) + , mCacheDeleted(false) + , mCacheId(0) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + mozStorageTransaction trans(aConn, false, + mozIStorageConnection::TRANSACTION_IMMEDIATE); + + bool exists; + nsresult rv = DBSchema::StorageGetCacheId(aConn, mNamespace, mKey, &exists, + &mCacheId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (!exists) { + mCacheDeleted = false; + return NS_OK; + } + + rv = DBSchema::StorageForgetCache(aConn, mNamespace, mKey); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = trans.Commit(); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + mCacheDeleted = true; + return rv; + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + if (mCacheDeleted) { + // If content is referencing this cache, mark it orphaned to be + // deleted later. + if (!mManager->SetCacheIdOrphanedIfRefed(mCacheId)) { + + // no outstanding references, delete immediately + nsRefPtr context = mManager->CurrentContext(); + context->CancelForCacheId(mCacheId); + nsRefPtr action = + new DeleteOrphanedCacheAction(mManager, mCacheId); + context->Dispatch(mManager->mIOThread, action); + } + } + + aListener->OnStorageDelete(mRequestId, aRv, mCacheDeleted); + } + +private: + const Namespace mNamespace; + const nsString mKey; + bool mCacheDeleted; + CacheId mCacheId; +}; + +// ---------------------------------------------------------------------------- + +class Manager::StorageKeysAction MOZ_FINAL : public Manager::BaseAction +{ +public: + StorageKeysAction(Manager* aManager, ListenerId aListenerId, + RequestId aRequestId, Namespace aNamespace) + : BaseAction(aManager, aListenerId, aRequestId) + , mNamespace(aNamespace) + { } + + virtual nsresult + RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir, + mozIStorageConnection* aConn) MOZ_OVERRIDE + { + return DBSchema::StorageGetKeys(aConn, mNamespace, mKeys); + } + + virtual void + Complete(Listener* aListener, nsresult aRv) MOZ_OVERRIDE + { + if (NS_FAILED(aRv)) { + mKeys.Clear(); + } + aListener->OnStorageKeys(mRequestId, aRv, mKeys); + } + +private: + const Namespace mNamespace; + nsTArray mKeys; +}; + +// ---------------------------------------------------------------------------- + +//static +Manager::ListenerId Manager::sNextListenerId = 0; + +// static +nsresult +Manager::GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut) +{ + mozilla::ipc::AssertIsOnBackgroundThread(); + return Factory::GetOrCreate(aManagerId, aManagerOut); +} + +// static +already_AddRefed +Manager::Get(ManagerId* aManagerId) +{ + mozilla::ipc::AssertIsOnBackgroundThread(); + return Factory::Get(aManagerId); +} + +// static +void +Manager::ShutdownAllOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + + Factory::StartShutdownAllOnMainThread(); + + while (!Factory::IsShutdownAllCompleteOnMainThread()) { + if (!NS_ProcessNextEvent()) { + NS_WARNING("Something bad happened!"); + break; + } + } +} + +void +Manager::RemoveListener(Listener* aListener) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + // There may not be a listener here in the case where an actor is killed + // before it can perform any actual async requests on Manager. + mListeners.RemoveElement(aListener, ListenerEntryListenerComparator()); + MOZ_ASSERT(!mListeners.Contains(aListener, + ListenerEntryListenerComparator())); +} + +void +Manager::RemoveContext(Context* aContext) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(mContext); + MOZ_ASSERT(mContext == aContext); + mContext = nullptr; + + // If we're trying to shutdown, then note that we're done. This is the + // delayed case from Manager::Shutdown(). + if (mShuttingDown) { + Factory::Remove(this); + } +} + +void +Manager::AddRefCacheId(CacheId aCacheId) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + for (uint32_t i = 0; i < mCacheIdRefs.Length(); ++i) { + if (mCacheIdRefs[i].mCacheId == aCacheId) { + mCacheIdRefs[i].mCount += 1; + return; + } + } + CacheIdRefCounter* entry = mCacheIdRefs.AppendElement(); + entry->mCacheId = aCacheId; + entry->mCount = 1; + entry->mOrphaned = false; +} + +void +Manager::ReleaseCacheId(CacheId aCacheId) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + for (uint32_t i = 0; i < mCacheIdRefs.Length(); ++i) { + if (mCacheIdRefs[i].mCacheId == aCacheId) { + DebugOnly oldRef = mCacheIdRefs[i].mCount; + mCacheIdRefs[i].mCount -= 1; + MOZ_ASSERT(mCacheIdRefs[i].mCount < oldRef); + if (mCacheIdRefs[i].mCount == 0) { + bool orphaned = mCacheIdRefs[i].mOrphaned; + mCacheIdRefs.RemoveElementAt(i); + // TODO: note that we need to check this cache for staleness on startup (bug 1110446) + if (orphaned && !mShuttingDown) { + nsRefPtr context = CurrentContext(); + context->CancelForCacheId(aCacheId); + nsRefPtr action = new DeleteOrphanedCacheAction(this, + aCacheId); + context->Dispatch(mIOThread, action); + } + } + return; + } + } + MOZ_ASSERT_UNREACHABLE("Attempt to release CacheId that is not referenced!"); +} + +void +Manager::AddRefBodyId(const nsID& aBodyId) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + for (uint32_t i = 0; i < mBodyIdRefs.Length(); ++i) { + if (mBodyIdRefs[i].mBodyId == aBodyId) { + mBodyIdRefs[i].mCount += 1; + return; + } + } + BodyIdRefCounter* entry = mBodyIdRefs.AppendElement(); + entry->mBodyId = aBodyId; + entry->mCount = 1; + entry->mOrphaned = false; +} + +void +Manager::ReleaseBodyId(const nsID& aBodyId) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + for (uint32_t i = 0; i < mBodyIdRefs.Length(); ++i) { + if (mBodyIdRefs[i].mBodyId == aBodyId) { + DebugOnly oldRef = mBodyIdRefs[i].mCount; + mBodyIdRefs[i].mCount -= 1; + MOZ_ASSERT(mBodyIdRefs[i].mCount < oldRef); + if (mBodyIdRefs[i].mCount < 1) { + bool orphaned = mBodyIdRefs[i].mOrphaned; + mBodyIdRefs.RemoveElementAt(i); + // TODO: note that we need to check this body for staleness on startup (bug 1110446) + if (orphaned && !mShuttingDown) { + nsRefPtr action = new DeleteOrphanedBodyAction(aBodyId); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); + } + } + return; + } + } + MOZ_ASSERT_UNREACHABLE("Attempt to release BodyId that is not referenced!"); +} + +already_AddRefed +Manager::GetManagerId() const +{ + nsRefPtr ref = mManagerId; + return ref.forget(); +} + +void +Manager::AddStreamList(StreamList* aStreamList) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aStreamList); + mStreamLists.AppendElement(aStreamList); +} + +void +Manager::RemoveStreamList(StreamList* aStreamList) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aStreamList); + mStreamLists.RemoveElement(aStreamList); +} + +void +Manager::CacheMatch(Listener* aListener, RequestId aRequestId, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnCacheMatch(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + nullptr, nullptr); + return; + } + nsRefPtr context = CurrentContext(); + nsRefPtr streamList = new StreamList(this, context); + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new CacheMatchAction(this, listenerId, aRequestId, + aCacheId, aRequest, aParams, + streamList); + context->Dispatch(mIOThread, action); +} + +void +Manager::CacheMatchAll(Listener* aListener, RequestId aRequestId, + CacheId aCacheId, const PCacheRequestOrVoid& aRequest, + const PCacheQueryParams& aParams) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnCacheMatchAll(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + nsTArray(), nullptr); + return; + } + nsRefPtr context = CurrentContext(); + nsRefPtr streamList = new StreamList(this, context); + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new CacheMatchAllAction(this, listenerId, aRequestId, + aCacheId, aRequest, aParams, + streamList); + context->Dispatch(mIOThread, action); +} + +void +Manager::CachePutAll(Listener* aListener, RequestId aRequestId, CacheId aCacheId, + const nsTArray& aPutList, + const nsTArray>& aRequestStreamList, + const nsTArray>& aResponseStreamList) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnCachePutAll(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new CachePutAllAction(this, listenerId, aRequestId, + aCacheId, aPutList, + aRequestStreamList, + aResponseStreamList); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); +} + +void +Manager::CacheDelete(Listener* aListener, RequestId aRequestId, + CacheId aCacheId, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnCacheDelete(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, false); + return; + } + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new CacheDeleteAction(this, listenerId, aRequestId, + aCacheId, aRequest, aParams); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); +} + +void +Manager::CacheKeys(Listener* aListener, RequestId aRequestId, + CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnCacheKeys(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + nsTArray(), nullptr); + return; + } + nsRefPtr context = CurrentContext(); + nsRefPtr streamList = new StreamList(this, context); + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new CacheKeysAction(this, listenerId, aRequestId, + aCacheId, aRequestOrVoid, + aParams, streamList); + context->Dispatch(mIOThread, action); +} + +void +Manager::StorageMatch(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnStorageMatch(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + nullptr, nullptr); + return; + } + nsRefPtr context = CurrentContext(); + nsRefPtr streamList = new StreamList(this, context); + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new StorageMatchAction(this, listenerId, aRequestId, + aNamespace, aRequest, + aParams, streamList); + context->Dispatch(mIOThread, action); +} + +void +Manager::StorageHas(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const nsAString& aKey) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnStorageHas(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + false); + return; + } + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new StorageHasAction(this, listenerId, aRequestId, + aNamespace, aKey); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); +} + +void +Manager::StorageOpen(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const nsAString& aKey) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnStorageOpen(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, 0); + return; + } + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new StorageOpenAction(this, listenerId, aRequestId, + aNamespace, aKey); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); +} + +void +Manager::StorageDelete(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const nsAString& aKey) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnStorageDelete(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + false); + return; + } + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new StorageDeleteAction(this, listenerId, aRequestId, + aNamespace, aKey); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); +} + +void +Manager::StorageKeys(Listener* aListener, RequestId aRequestId, + Namespace aNamespace) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(aListener); + if (mShuttingDown) { + aListener->OnStorageKeys(aRequestId, NS_ERROR_ILLEGAL_DURING_SHUTDOWN, + nsTArray()); + return; + } + ListenerId listenerId = SaveListener(aListener); + nsRefPtr action = new StorageKeysAction(this, listenerId, aRequestId, + aNamespace); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); +} + +Manager::Manager(ManagerId* aManagerId, nsIThread* aIOThread) + : mManagerId(aManagerId) + , mIOThread(aIOThread) + , mContext(nullptr) + , mShuttingDown(false) +{ + MOZ_ASSERT(mManagerId); + MOZ_ASSERT(mIOThread); +} + +Manager::~Manager() +{ + NS_ASSERT_OWNINGTHREAD(Manager); + MOZ_ASSERT(!mContext); + Shutdown(); + + nsCOMPtr ioThread; + mIOThread.swap(ioThread); + + // Don't spin the event loop in the destructor waiting for the thread to + // shutdown. Defer this to the main thread, instead. + nsCOMPtr runnable = + NS_NewRunnableMethod(ioThread, &nsIThread::Shutdown); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable))); +} + +void +Manager::Shutdown() +{ + NS_ASSERT_OWNINGTHREAD(Manager); + + // Ignore duplicate attempts to shutdown. This can occur when we start + // a browser initiated shutdown and then run ~Manager() which also + // calls Shutdown(). + if (mShuttingDown) { + return; + } + + // Set a flag to prevent any new requests from coming in and creating + // a new Context. We must ensure all Contexts and IO operations are + // complete before shutdown proceeds. + mShuttingDown = true; + + for (uint32_t i = 0; i < mStreamLists.Length(); ++i) { + nsRefPtr streamList = mStreamLists[i]; + streamList->CloseAll(); + } + + // If there is a context, then we must wait for it to complete. Cancel and + // only note that we are done after its cleaned up. + if (mContext) { + nsRefPtr context = mContext; + context->CancelAll(); + return; + } + + // Otherwise, note that we are complete immediately + Factory::Remove(this); +} + +already_AddRefed +Manager::CurrentContext() +{ + NS_ASSERT_OWNINGTHREAD(Manager); + nsRefPtr ref = mContext; + if (!ref) { + MOZ_ASSERT(!mShuttingDown); + nsRefPtr setupAction = new SetupAction(); + ref = Context::Create(this, setupAction); + mContext = ref; + } + return ref.forget(); +} + +Manager::ListenerId +Manager::SaveListener(Listener* aListener) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + + // Once a Listener is added, we keep a reference to it until its + // removed. Since the same Listener might make multiple requests, + // ensure we only have a single reference in our list. + ListenerList::index_type index = + mListeners.IndexOf(aListener, 0, ListenerEntryListenerComparator()); + if (index != ListenerList::NoIndex) { + return mListeners[index].mId; + } + + ListenerId id = sNextListenerId; + sNextListenerId += 1; + + mListeners.AppendElement(ListenerEntry(id, aListener)); + return id; +} + +Manager::Listener* +Manager::GetListener(ListenerId aListenerId) const +{ + NS_ASSERT_OWNINGTHREAD(Manager); + ListenerList::index_type index = + mListeners.IndexOf(aListenerId, 0, ListenerEntryIdComparator()); + if (index != ListenerList::NoIndex) { + return mListeners[index].mListener; + } + + // This can legitimately happen if the actor is deleted while a request is + // in process. For example, the child process OOMs. + return nullptr; +} + +bool +Manager::SetCacheIdOrphanedIfRefed(CacheId aCacheId) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + for (uint32_t i = 0; i < mCacheIdRefs.Length(); ++i) { + if (mCacheIdRefs[i].mCacheId == aCacheId) { + MOZ_ASSERT(mCacheIdRefs[i].mCount > 0); + MOZ_ASSERT(!mCacheIdRefs[i].mOrphaned); + mCacheIdRefs[i].mOrphaned = true; + return true; + } + } + return false; +} + +// TODO: provide way to set body non-orphaned if its added back to a cache (bug 1110479) + +bool +Manager::SetBodyIdOrphanedIfRefed(const nsID& aBodyId) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + for (uint32_t i = 0; i < mBodyIdRefs.Length(); ++i) { + if (mBodyIdRefs[i].mBodyId == aBodyId) { + MOZ_ASSERT(mBodyIdRefs[i].mCount > 0); + MOZ_ASSERT(!mBodyIdRefs[i].mOrphaned); + mBodyIdRefs[i].mOrphaned = true; + return true; + } + } + return false; +} + +void +Manager::NoteOrphanedBodyIdList(const nsTArray& aDeletedBodyIdList) +{ + NS_ASSERT_OWNINGTHREAD(Manager); + + nsAutoTArray deleteNowList; + deleteNowList.SetCapacity(aDeletedBodyIdList.Length()); + + for (uint32_t i = 0; i < aDeletedBodyIdList.Length(); ++i) { + if (!SetBodyIdOrphanedIfRefed(aDeletedBodyIdList[i])) { + deleteNowList.AppendElement(aDeletedBodyIdList[i]); + } + } + + if (!deleteNowList.IsEmpty()) { + nsRefPtr action = new DeleteOrphanedBodyAction(deleteNowList); + nsRefPtr context = CurrentContext(); + context->Dispatch(mIOThread, action); + } +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/Manager.h b/dom/cache/Manager.h new file mode 100644 index 0000000000..967e84445d --- /dev/null +++ b/dom/cache/Manager.h @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_Manager_h +#define mozilla_dom_cache_Manager_h + +#include "mozilla/dom/cache/CacheInitData.h" +#include "mozilla/dom/cache/PCacheStreamControlParent.h" +#include "mozilla/dom/cache/Types.h" +#include "nsCOMPtr.h" +#include "nsISupportsImpl.h" +#include "nsString.h" +#include "nsTArray.h" + +class nsIInputStream; +class nsIOutputStream; +class nsIThread; + +namespace mozilla { +namespace dom { +namespace cache { + +class CacheRequestResponse; +class Context; +class ManagerId; +class PCacheQueryParams; +class PCacheRequest; +class PCacheRequestOrVoid; +class PCacheResponse; +struct SavedRequest; +struct SavedResponse; +class StreamList; + +// The Manager is class is responsible for performing all of the underlying +// work for a Cache or CacheStorage operation. The DOM objects and IPC actors +// are basically just plumbing to get the request to the right Manager object +// running in the parent process. +// +// There should be exactly one Manager object for each origin or app using the +// Cache API. This uniqueness is defined by the ManagerId equality operator. +// The uniqueness is enforced by the Manager GetOrCreate() factory method. +// +// The Manager object can out live the IPC actors in the case where the child +// process is killed; e.g a child process OOM. The Manager object can +// The Manager object can potentially use non-trivial resources. Long lived +// DOM objects and their actors should not maintain a reference to the Manager +// while idle. Transient DOM objects that may keep a reference for their +// lifetimes. +// +// For example, once a CacheStorage DOM object is access it will live until its +// global is released. Therefore, CacheStorage should release its Manager +// reference after operations complete and it becomes idle. Cache objects, +// however, can be GC'd once content are done using them and can therefore keep +// their Manager reference alive. Its expected that more operations are +// performed on a Cache object, so keeping the Manager reference will help +// minimize overhead for each reference. +// +// As an invariant, all Manager objects must cease all IO before shutdown. This +// is enforced by the ShutdownObserver. If content still holds references to +// Cache DOM objects during shutdown, then all operations will begin rejecting. +class Manager MOZ_FINAL +{ +public: + // Callback interface implemented by clients of Manager, such as CacheParent + // and CacheStorageParent. In general, if you call a Manager method you + // should expect to receive exactly one On*() callback. For example, if + // you call Manager::CacheMatch(), then you should expect to receive + // OnCacheMatch() back in response. + // + // Listener objects are set on a per-operation basis. So you pass the + // Listener to a call like Manager::CacheMatch(). Once set in this way, + // the Manager will continue to reference the Listener until RemoveListener() + // is called. This is done to allow the same listener to be used for + // multiple operations simultaneously without having to maintain an exact + // count of operations-in-flight. + // + // Note, the Manager only holds weak references to Listener objects. + // Listeners must call Manager::RemoveListener() before they are destroyed + // to clear these weak references. + // + // All public methods should be invoked on the same thread used to create + // the Manager. + class Listener + { + public: + virtual void OnCacheMatch(RequestId aRequestId, nsresult aRv, + const SavedResponse* aResponse, + StreamList* aStreamList) { } + virtual void OnCacheMatchAll(RequestId aRequestId, nsresult aRv, + const nsTArray& aSavedResponses, + StreamList* aStreamList) { } + virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) { } + virtual void OnCacheDelete(RequestId aRequestId, nsresult aRv, + bool aSuccess) { } + virtual void OnCacheKeys(RequestId aRequestId, nsresult aRv, + const nsTArray& aSavedRequests, + StreamList* aStreamList) { } + + virtual void OnStorageMatch(RequestId aRequestId, nsresult aRv, + const SavedResponse* aResponse, + StreamList* aStreamList) { } + virtual void OnStorageHas(RequestId aRequestId, nsresult aRv, + bool aCacheFound) { } + virtual void OnStorageOpen(RequestId aRequestId, nsresult aRv, + CacheId aCacheId) { } + virtual void OnStorageDelete(RequestId aRequestId, nsresult aRv, + bool aCacheDeleted) { } + virtual void OnStorageKeys(RequestId aRequestId, nsresult aRv, + const nsTArray& aKeys) { } + + protected: + ~Listener() { } + }; + + static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut); + static already_AddRefed Get(ManagerId* aManagerId); + + // Synchronously shutdown from main thread. This spins the event loop. + static void ShutdownAllOnMainThread(); + + // Must be called by Listener objects before they are destroyed. + void RemoveListener(Listener* aListener); + + // Must be called by Context objects before they are destroyed. + void RemoveContext(Context* aContext); + + // If an actor represents a long term reference to a cache or body stream, + // then they must call AddRefCacheId() or AddRefBodyId(). This will + // cause the Manager to keep the backing data store alive for the given + // object. The actor must then call ReleaseCacheId() or ReleaseBodyId() + // exactly once for every AddRef*() call it made. Any delayed deletion + // will then be performed. + void AddRefCacheId(CacheId aCacheId); + void ReleaseCacheId(CacheId aCacheId); + void AddRefBodyId(const nsID& aBodyId); + void ReleaseBodyId(const nsID& aBodyId); + + already_AddRefed GetManagerId() const; + + // Methods to allow a StreamList to register themselves with the Manager. + // StreamList objects must call RemoveStreamList() before they are destroyed. + void AddStreamList(StreamList* aStreamList); + void RemoveStreamList(StreamList* aStreamList); + + // TODO: consider moving CacheId up in the argument lists below (bug 1110485) + void CacheMatch(Listener* aListener, RequestId aRequestId, CacheId aCacheId, + const PCacheRequest& aRequest, + const PCacheQueryParams& aParams); + void CacheMatchAll(Listener* aListener, RequestId aRequestId, + CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams); + void CachePutAll(Listener* aListener, RequestId aRequestId, CacheId aCacheId, + const nsTArray& aPutList, + const nsTArray>& aRequestStreamList, + const nsTArray>& aResponseStreamList); + void CacheDelete(Listener* aListener, RequestId aRequestId, + CacheId aCacheId, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams); + void CacheKeys(Listener* aListener, RequestId aRequestId, + CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid, + const PCacheQueryParams& aParams); + + void StorageMatch(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const PCacheRequest& aRequest, + const PCacheQueryParams& aParams); + void StorageHas(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const nsAString& aKey); + void StorageOpen(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const nsAString& aKey); + void StorageDelete(Listener* aListener, RequestId aRequestId, + Namespace aNamespace, const nsAString& aKey); + void StorageKeys(Listener* aListener, RequestId aRequestId, + Namespace aNamespace); + +private: + class Factory; + class BaseAction; + class DeleteOrphanedCacheAction; + + class CacheMatchAction; + class CacheMatchAllAction; + class CachePutAllAction; + class CacheDeleteAction; + class CacheKeysAction; + + class StorageMatchAction; + class StorageHasAction; + class StorageOpenAction; + class StorageDeleteAction; + class StorageKeysAction; + + typedef uint64_t ListenerId; + + Manager(ManagerId* aManagerId, nsIThread* aIOThread); + ~Manager(); + void Shutdown(); + already_AddRefed CurrentContext(); + + ListenerId SaveListener(Listener* aListener); + Listener* GetListener(ListenerId aListenerId) const; + + bool SetCacheIdOrphanedIfRefed(CacheId aCacheId); + bool SetBodyIdOrphanedIfRefed(const nsID& aBodyId); + void NoteOrphanedBodyIdList(const nsTArray& aDeletedBodyIdList); + + nsRefPtr mManagerId; + nsCOMPtr mIOThread; + + // Weak reference cleared by RemoveContext() in Context destructor. + Context* MOZ_NON_OWNING_REF mContext; + + // Weak references cleared by RemoveListener() in Listener destructors. + struct ListenerEntry + { + ListenerEntry() + : mId(UINT64_MAX), + mListener(nullptr) + { + } + + ListenerEntry(ListenerId aId, Listener* aListener) + : mId(aId) + , mListener(aListener) + { + } + + ListenerId mId; + Listener* mListener; + }; + + class ListenerEntryIdComparator + { + public: + bool Equals(const ListenerEntry& aA, const ListenerId& aB) const + { + return aA.mId == aB; + } + }; + + class ListenerEntryListenerComparator + { + public: + bool Equals(const ListenerEntry& aA, const Listener* aB) const + { + return aA.mListener == aB; + } + }; + + typedef nsTArray ListenerList; + ListenerList mListeners; + static ListenerId sNextListenerId; + + // Weak references cleared by RemoveStreamList() in StreamList destructors. + nsTArray mStreamLists; + + bool mShuttingDown; + + struct CacheIdRefCounter + { + CacheId mCacheId; + MozRefCountType mCount; + bool mOrphaned; + }; + nsTArray mCacheIdRefs; + + struct BodyIdRefCounter + { + nsID mBodyId; + MozRefCountType mCount; + bool mOrphaned; + }; + nsTArray mBodyIdRefs; + +public: + NS_INLINE_DECL_REFCOUNTING(cache::Manager) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_Manager_h diff --git a/dom/cache/ManagerId.cpp b/dom/cache/ManagerId.cpp new file mode 100644 index 0000000000..891605f955 --- /dev/null +++ b/dom/cache/ManagerId.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/ManagerId.h" +#include "nsIPrincipal.h" +#include "nsProxyRelease.h" +#include "mozilla/nsRefPtr.h" +#include "nsThreadUtils.h" + +namespace mozilla { +namespace dom { +namespace cache { + +// static +nsresult +ManagerId::Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // The QuotaManager::GetInfoFromPrincipal() has special logic for system + // and about: principals. We currently don't need the system principal logic + // because ManagerId only uses the origin for in memory comparisons. We + // also don't do any special logic to host the same Cache for different about: + // pages, so we don't need those checks either. + // + // But, if we get the same QuotaManager directory for different about: + // origins, we probably only want one Manager instance. So, we might + // want to start using the QM's concept of origin uniqueness here. + // + // TODO: consider using QuotaManager's modified origin here (bug 1112071) + + nsAutoCString origin; + nsresult rv = aPrincipal->GetOrigin(getter_Copies(origin)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + uint32_t appId; + rv = aPrincipal->GetAppId(&appId); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool inBrowserElement; + rv = aPrincipal->GetIsInBrowserElement(&inBrowserElement); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsRefPtr ref = new ManagerId(aPrincipal, origin, appId, + inBrowserElement); + ref.forget(aManagerIdOut); + + return NS_OK; +} + +already_AddRefed +ManagerId::Principal() const +{ + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr ref = mPrincipal; + return ref.forget(); +} + +ManagerId::ManagerId(nsIPrincipal* aPrincipal, const nsACString& aOrigin, + uint32_t aAppId, bool aInBrowserElement) + : mPrincipal(aPrincipal) + , mOrigin(aOrigin) + , mAppId(aAppId) + , mInBrowserElement(aInBrowserElement) +{ + MOZ_ASSERT(mPrincipal); +} + +ManagerId::~ManagerId() +{ + // If we're already on the main thread, then default destruction is fine + if (NS_IsMainThread()) { + return; + } + + // Otherwise we need to proxy to main thread to do the release + + // The PBackground worker thread shouldn't be running after the main thread + // is stopped. So main thread is guaranteed to exist here. + nsCOMPtr mainThread = do_GetMainThread(); + MOZ_ASSERT(mainThread); + + NS_ProxyRelease(mainThread, mPrincipal.forget().take()); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/ManagerId.h b/dom/cache/ManagerId.h new file mode 100644 index 0000000000..6d0ce0ec51 --- /dev/null +++ b/dom/cache/ManagerId.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_ManagerId_h +#define mozilla_dom_cache_ManagerId_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/cache/Types.h" +#include "nsCOMPtr.h" +#include "nsError.h" +#include "nsISupportsImpl.h" +#include "nsString.h" + +class nsIPrincipal; + +namespace mozilla { +namespace dom { +namespace cache { + +class ManagerId MOZ_FINAL +{ +public: + // nsTArray comparator that compares by value instead of pointer values. + class MOZ_STACK_CLASS Comparator MOZ_FINAL + { + public: + bool Equals(ManagerId *aA, ManagerId* aB) const { return *aA == *aB; } + bool LessThan(ManagerId *aA, ManagerId* aB) const { return *aA < *aB; } + }; + + // Main thread only + static nsresult Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut); + + // Main thread only + already_AddRefed Principal() const; + + const nsACString& Origin() const { return mOrigin; } + + bool operator==(const ManagerId& aOther) const + { + return mOrigin == aOther.mOrigin && + mAppId == aOther.mAppId && + mInBrowserElement == aOther.mInBrowserElement; + } + + bool operator<(const ManagerId& aOther) const + { + return mOrigin < aOther.mOrigin || + (mOrigin == aOther.mOrigin && mAppId < aOther.mAppId) || + (mOrigin == aOther.mOrigin && mAppId == aOther.mAppId && + mInBrowserElement < aOther.mInBrowserElement); + } + +private: + ManagerId(nsIPrincipal* aPrincipal, const nsACString& aOrigin, + uint32_t aAppId, bool aInBrowserElement); + ~ManagerId(); + + ManagerId(const ManagerId&) = delete; + ManagerId& operator=(const ManagerId&) = delete; + + // only accessible on main thread + nsCOMPtr mPrincipal; + + // immutable to allow threadsfe access + const nsCString mOrigin; + const uint32_t mAppId; + const bool mInBrowserElement; + +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::cache::ManagerId) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_ManagerId_h diff --git a/dom/cache/PCache.ipdl b/dom/cache/PCache.ipdl new file mode 100644 index 0000000000..bc36df1435 --- /dev/null +++ b/dom/cache/PCache.ipdl @@ -0,0 +1,46 @@ +/* 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 protocol PBackground; +include PCacheTypes; +include protocol PFileDescriptorSet; + +include protocol PBlob; // FIXME: bug 792908 +include protocol PCacheStreamControl; + +using mozilla::dom::cache::RequestId from "mozilla/dom/cache/Types.h"; +include "mozilla/dom/cache/IPCUtils.h"; + +namespace mozilla { +namespace dom { +namespace cache { + +protocol PCache +{ + manager PBackground; + +parent: + Teardown(); + Match(RequestId requestId, PCacheRequest request, PCacheQueryParams params); + MatchAll(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params); + AddAll(RequestId requestId, PCacheRequest[] requests); + Put(RequestId requestId, CacheRequestResponse aPut); + Delete(RequestId requestId, PCacheRequest request, PCacheQueryParams params); + Keys(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params); + +child: + MatchResponse(RequestId requestId, nsresult aRv, PCacheResponseOrVoid aResponse); + MatchAllResponse(RequestId requestId, nsresult aRv, PCacheResponse[] responses); + AddAllResponse(RequestId requestId, nsresult aRv); + PutResponse(RequestId requestId, nsresult aRv); + DeleteResponse(RequestId requestId, nsresult aRv, bool success); + KeysResponse(RequestId requestId, nsresult aRv, PCacheRequest[] requests); + +both: + __delete__(); +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/PCacheStorage.ipdl b/dom/cache/PCacheStorage.ipdl new file mode 100644 index 0000000000..030b2fbc84 --- /dev/null +++ b/dom/cache/PCacheStorage.ipdl @@ -0,0 +1,44 @@ +/* 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 protocol PBackground; +include protocol PCache; +include PCacheTypes; +include protocol PFileDescriptorSet; + +include protocol PBlob; // FIXME: bug 792908 +include protocol PCacheStreamControl; + +using mozilla::dom::cache::RequestId from "mozilla/dom/cache/IPCUtils.h"; + +namespace mozilla { +namespace dom { +namespace cache { + +protocol PCacheStorage +{ + manager PBackground; + +parent: + Teardown(); + Match(RequestId aRequestId, PCacheRequest aRequest, + PCacheQueryParams aParams); + Has(RequestId aRequestId, nsString aKey); + Open(RequestId aRequestId, nsString aKey); + Delete(RequestId aRequestId, nsString aKey); + Keys(RequestId aRequestId); + +child: + MatchResponse(RequestId aRequestId, nsresult aRv, + PCacheResponseOrVoid aResponseOrVoid); + HasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess); + OpenResponse(RequestId aRequestId, nsresult aRv, nullable PCache aActor); + DeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess); + KeysResponse(RequestId aRequestId, nsresult aRv, nsString[] aKeys); + __delete__(); +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/PCacheStreamControl.ipdl b/dom/cache/PCacheStreamControl.ipdl new file mode 100644 index 0000000000..21155584b2 --- /dev/null +++ b/dom/cache/PCacheStreamControl.ipdl @@ -0,0 +1,28 @@ +/* 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 protocol PBackground; + +using struct nsID from "nsID.h"; + +namespace mozilla { +namespace dom { +namespace cache { + +protocol PCacheStreamControl +{ + manager PBackground; + +parent: + NoteClosed(nsID aStreamId); + +child: + Close(nsID aStreamId); + CloseAll(); + __delete__(); +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/PCacheTypes.ipdlh b/dom/cache/PCacheTypes.ipdlh new file mode 100644 index 0000000000..03a6b6e633 --- /dev/null +++ b/dom/cache/PCacheTypes.ipdlh @@ -0,0 +1,89 @@ +/* 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 protocol PCacheStreamControl; +include PHeaders; +include InputStreamParams; + +using HeadersGuardEnum from "mozilla/dom/FetchIPCUtils.h"; +using RequestCredentials from "mozilla/dom/FetchIPCUtils.h"; +using RequestMode from "mozilla/dom/FetchIPCUtils.h"; +using mozilla::dom::ResponseType from "mozilla/dom/FetchIPCUtils.h"; +using mozilla::void_t from "ipc/IPCMessageUtils.h"; +using struct nsID from "nsID.h"; + +namespace mozilla { +namespace dom { +namespace cache { + +struct PCacheQueryParams +{ + bool ignoreSearch; + bool ignoreMethod; + bool ignoreVary; + bool prefixMatch; + bool cacheNameSet; + nsString cacheName; +}; + +struct PCacheReadStream +{ + nsID id; + OptionalInputStreamParams params; + OptionalFileDescriptorSet fds; + nullable PCacheStreamControl control; +}; + +union PCacheReadStreamOrVoid +{ + void_t; + PCacheReadStream; +}; + +struct PCacheRequest +{ + nsCString method; + nsString url; + nsString urlWithoutQuery; + PHeadersEntry[] headers; + HeadersGuardEnum headersGuard; + nsString referrer; + RequestMode mode; + RequestCredentials credentials; + PCacheReadStreamOrVoid body; + uint32_t context; +}; + +union PCacheRequestOrVoid +{ + void_t; + PCacheRequest; +}; + +struct PCacheResponse +{ + ResponseType type; + nsString url; + uint32_t status; + nsCString statusText; + PHeadersEntry[] headers; + HeadersGuardEnum headersGuard; + PCacheReadStreamOrVoid body; +}; + +union PCacheResponseOrVoid +{ + void_t; + PCacheResponse; +}; + +struct CacheRequestResponse +{ + PCacheRequest request; + PCacheResponse response; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/PrincipalVerifier.cpp b/dom/cache/PrincipalVerifier.cpp new file mode 100644 index 0000000000..ee387f8780 --- /dev/null +++ b/dom/cache/PrincipalVerifier.cpp @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/PrincipalVerifier.h" + +#include "mozilla/AppProcessChecker.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/cache/ManagerId.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "mozilla/ipc/PBackgroundParent.h" +#include "mozilla/ipc/BackgroundUtils.h" +#include "nsIPrincipal.h" +#include "nsIScriptSecurityManager.h" +#include "nsNetUtil.h" + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::ipc::AssertIsOnBackgroundThread; +using mozilla::ipc::BackgroundParent; +using mozilla::ipc::PBackgroundParent; +using mozilla::ipc::PrincipalInfo; +using mozilla::ipc::PrincipalInfoToPrincipal; + +// static +already_AddRefed +PrincipalVerifier::CreateAndDispatch(Listener* aListener, + PBackgroundParent* aActor, + const PrincipalInfo& aPrincipalInfo) +{ + // We must get the ContentParent actor from the PBackgroundParent. This + // only works on the PBackground thread. + AssertIsOnBackgroundThread(); + + nsRefPtr verifier = new PrincipalVerifier(aListener, + aActor, + aPrincipalInfo); + + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(verifier))); + + return verifier.forget(); +} + +void +PrincipalVerifier::ClearListener() +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mListener); + mListener = nullptr; +} + +PrincipalVerifier::PrincipalVerifier(Listener* aListener, + PBackgroundParent* aActor, + const PrincipalInfo& aPrincipalInfo) + : mListener(aListener) + , mActor(BackgroundParent::GetContentParent(aActor)) + , mPrincipalInfo(aPrincipalInfo) + , mInitiatingThread(NS_GetCurrentThread()) + , mResult(NS_OK) +{ + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mListener); + MOZ_ASSERT(mInitiatingThread); +} + +PrincipalVerifier::~PrincipalVerifier() +{ + // Since the PrincipalVerifier is a Runnable that executes on multiple + // threads, its a race to see which thread de-refs us last. Therefore + // we cannot guarantee which thread we destruct on. + + MOZ_ASSERT(!mListener); + + // We should always be able to explicitly release the actor on the main + // thread. + MOZ_ASSERT(!mActor); +} + +NS_IMETHODIMP +PrincipalVerifier::Run() +{ + // Executed twice. First, on the main thread and then back on the + // originating thread. + + if (NS_IsMainThread()) { + VerifyOnMainThread(); + return NS_OK; + } + + CompleteOnInitiatingThread(); + return NS_OK; +} + +void +PrincipalVerifier::VerifyOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + + // No matter what happens, we need to release the actor before leaving + // this method. + nsRefPtr actor; + actor.swap(mActor); + + nsresult rv; + nsRefPtr principal = PrincipalInfoToPrincipal(mPrincipalInfo, + &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + DispatchToInitiatingThread(rv); + return; + } + + // We disallow null principal and unknown app IDs on the client side, but + // double-check here. + if (NS_WARN_IF(principal->GetIsNullPrincipal() || + principal->GetUnknownAppId())) { + DispatchToInitiatingThread(NS_ERROR_FAILURE); + return; + } + + // Verify that a child process claims to own the app for this principal + if (NS_WARN_IF(actor && !AssertAppPrincipal(actor, principal))) { + DispatchToInitiatingThread(NS_ERROR_FAILURE); + return; + } + actor = nullptr; + + nsCOMPtr ssm = nsContentUtils::GetSecurityManager(); + if (NS_WARN_IF(!ssm)) { + DispatchToInitiatingThread(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + +#ifdef DEBUG + // Sanity check principal origin by using it to construct a URI and security + // checking it. Don't do this for the system principal, though, as its origin + // is a synthetic [System Principal] string. + if (!ssm->IsSystemPrincipal(principal)) { + nsAutoCString origin; + rv = principal->GetOrigin(getter_Copies(origin)); + if (NS_WARN_IF(NS_FAILED(rv))) { + DispatchToInitiatingThread(rv); + return; + } + nsCOMPtr uri; + rv = NS_NewURI(getter_AddRefs(uri), origin); + if (NS_WARN_IF(NS_FAILED(rv))) { + DispatchToInitiatingThread(rv); + return; + } + rv = principal->CheckMayLoad(uri, false, false); + if (NS_WARN_IF(NS_FAILED(rv))) { + DispatchToInitiatingThread(rv); + return; + } + } +#endif + + rv = ManagerId::Create(principal, getter_AddRefs(mManagerId)); + if (NS_WARN_IF(NS_FAILED(rv))) { + DispatchToInitiatingThread(rv); + return; + } + + DispatchToInitiatingThread(NS_OK); +} + +void +PrincipalVerifier::CompleteOnInitiatingThread() +{ + AssertIsOnBackgroundThread(); + + // This can happen if the listener is destroyed before we finish. For + // example, if the child process OOMs and the actor is destroyed. + if (!mListener) { + return; + } + + mListener->OnPrincipalVerified(mResult, mManagerId); + + // The listener must clear their reference in OnPrincipalVerified() + MOZ_ASSERT(!mListener); +} + +void +PrincipalVerifier::DispatchToInitiatingThread(nsresult aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + + mResult = aRv; + + // The Cache ShutdownObserver does not track all principal verifiers, so we + // cannot ensure this always succeeds. Instead, simply warn on failures. + // This will result in a new CacheStorage object delaying operations until + // shutdown completes and the browser goes away. This is as graceful as + // we can get here. + nsresult rv = mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("Cache unable to complete principal verification due to shutdown."); + } +} + +} // namesapce cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/PrincipalVerifier.h b/dom/cache/PrincipalVerifier.h new file mode 100644 index 0000000000..342b2389cd --- /dev/null +++ b/dom/cache/PrincipalVerifier.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_PrincipalVerifier_h +#define mozilla_dom_cache_PrincipalVerifier_h + +#include "mozilla/ipc/PBackgroundSharedTypes.h" +#include "nsThreadUtils.h" + +namespace mozilla { + +namespace ipc { + class PBackgroundParent; +} + +namespace dom { +namespace cache { + +class ManagerId; + +class PrincipalVerifier MOZ_FINAL : public nsRunnable +{ +public: + // An interface to be implemented by code wishing to use the + // PrincipalVerifier. Note, the Listener implementation is responsible + // for calling ClearListener() on the PrincipalVerifier to clear the + // weak reference. + class Listener + { + public: + virtual void OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId) = 0; + }; + + static already_AddRefed + CreateAndDispatch(Listener* aListener, mozilla::ipc::PBackgroundParent* aActor, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo); + + // The Listener must call ClearListener() when OnPrincipalVerified() is + // called or when the Listener is destroyed. + void ClearListener(); + +private: + PrincipalVerifier(Listener* aListener, mozilla::ipc::PBackgroundParent* aActor, + const mozilla::ipc::PrincipalInfo& aPrincipalInfo); + virtual ~PrincipalVerifier(); + + void VerifyOnMainThread(); + void CompleteOnInitiatingThread(); + + void DispatchToInitiatingThread(nsresult aRv); + + // Weak reference cleared by ClearListener() + Listener* mListener; + + // set in originating thread at construction, but must be accessed and + // released on main thread + nsRefPtr mActor; + + const mozilla::ipc::PrincipalInfo mPrincipalInfo; + nsCOMPtr mInitiatingThread; + nsresult mResult; + nsRefPtr mManagerId; + +public: + NS_DECL_NSIRUNNABLE +}; + +} // namesapce cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_PrincipalVerifier_h diff --git a/dom/cache/QuotaClient.cpp b/dom/cache/QuotaClient.cpp new file mode 100644 index 0000000000..e7187a3f1e --- /dev/null +++ b/dom/cache/QuotaClient.cpp @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/QuotaClient.h" + +#include "mozilla/DebugOnly.h" +#include "mozilla/dom/cache/Manager.h" +#include "mozilla/dom/quota/QuotaManager.h" +#include "mozilla/dom/quota/UsageInfo.h" +#include "nsIFile.h" +#include "nsISimpleEnumerator.h" +#include "nsThreadUtils.h" + +namespace { + +using mozilla::DebugOnly; +using mozilla::dom::cache::Manager; +using mozilla::dom::quota::Client; +using mozilla::dom::quota::PersistenceType; +using mozilla::dom::quota::QuotaManager; +using mozilla::dom::quota::UsageInfo; + +static nsresult +GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo) +{ + nsCOMPtr entries; + nsresult rv = aDir->GetDirectoryEntries(getter_AddRefs(entries)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMore; + while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore && + !aUsageInfo->Canceled()) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr file = do_QueryInterface(entry); + + bool isDir; + rv = file->IsDirectory(&isDir); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (isDir) { + rv = GetBodyUsage(file, aUsageInfo); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + continue; + } + + int64_t fileSize; + rv = file->GetFileSize(&fileSize); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(fileSize >= 0); + + aUsageInfo->AppendToFileUsage(fileSize); + } + + return NS_OK; +} + +class CacheQuotaClient MOZ_FINAL : public Client +{ +public: + virtual Type + GetType() MOZ_OVERRIDE + { + return DOMCACHE; + } + + virtual nsresult + InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, + const nsACString& aOrigin, UsageInfo* aUsageInfo) MOZ_OVERRIDE + { + return NS_OK; + } + + virtual nsresult + GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, + const nsACString& aOrigin, + UsageInfo* aUsageInfo) MOZ_OVERRIDE + { + QuotaManager* qm = QuotaManager::Get(); + MOZ_ASSERT(qm); + + nsCOMPtr dir; + nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin, + getter_AddRefs(dir)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + rv = dir->Append(NS_LITERAL_STRING(DOMCACHE_DIRECTORY_NAME)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr entries; + rv = dir->GetDirectoryEntries(getter_AddRefs(entries)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool hasMore; + while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore && + !aUsageInfo->Canceled()) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + nsCOMPtr file = do_QueryInterface(entry); + + nsAutoString leafName; + rv = file->GetLeafName(leafName); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + bool isDir; + rv = file->IsDirectory(&isDir); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + if (isDir) { + if (leafName.EqualsLiteral("morgue")) { + rv = GetBodyUsage(file, aUsageInfo); + } else { + NS_WARNING("Unknown Cache directory found!"); + } + + continue; + } + + // Ignore transient sqlite files + if (leafName.EqualsLiteral("caches.sqlite-journal") || + leafName.EqualsLiteral("caches.sqlite-shm") || + leafName.Find(NS_LITERAL_CSTRING("caches.sqlite-mj"), false, 0, 0) == 0) { + continue; + } + + if (leafName.EqualsLiteral("caches.sqlite") || + leafName.EqualsLiteral("caches.sqlite-wal")) { + int64_t fileSize; + rv = file->GetFileSize(&fileSize); + if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(fileSize >= 0); + + aUsageInfo->AppendToDatabaseUsage(fileSize); + continue; + } + + NS_WARNING("Unknown Cache file found!"); + } + + return NS_OK; + } + + virtual void + OnOriginClearCompleted(PersistenceType aPersistenceType, + const nsACString& aOrigin) MOZ_OVERRIDE + { + // nothing to do + } + + virtual void + ReleaseIOThreadObjects() MOZ_OVERRIDE + { + // nothing to do + } + + virtual bool + IsFileServiceUtilized() MOZ_OVERRIDE + { + return false; + } + + virtual bool + IsTransactionServiceActivated() MOZ_OVERRIDE + { + // TODO: implement nsIOfflineStorage interface (bug 1110487) + return false; + } + + virtual void + WaitForStoragesToComplete(nsTArray& aStorages, + nsIRunnable* aCallback) MOZ_OVERRIDE + { + // TODO: implement nsIOfflineStorage interface (bug 1110487) + } + + + virtual void + ShutdownTransactionService() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + // spins the event loop and synchronously shuts down all Managers + Manager::ShutdownAllOnMainThread(); + } + +private: + ~CacheQuotaClient() { } + +public: + NS_INLINE_DECL_REFCOUNTING(CacheQuotaClient) +}; + +} // anonymous namespace; + +namespace mozilla { +namespace dom { +namespace cache { + +already_AddRefed CreateQuotaClient() +{ + nsRefPtr ref = new CacheQuotaClient(); + return ref.forget(); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/QuotaClient.h b/dom/cache/QuotaClient.h new file mode 100644 index 0000000000..f76143d645 --- /dev/null +++ b/dom/cache/QuotaClient.h @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_QuotaClient_h +#define mozilla_dom_cache_QuotaClient_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/quota/Client.h" + +namespace mozilla { +namespace dom { +namespace cache { + +already_AddRefed CreateQuotaClient(); + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_QuotaClient_h diff --git a/dom/cache/ReadStream.cpp b/dom/cache/ReadStream.cpp new file mode 100644 index 0000000000..3e0a411d37 --- /dev/null +++ b/dom/cache/ReadStream.cpp @@ -0,0 +1,543 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/ReadStream.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/cache/CacheStreamControlChild.h" +#include "mozilla/dom/cache/CacheStreamControlParent.h" +#include "mozilla/dom/cache/PCacheStreamControlChild.h" +#include "mozilla/dom/cache/PCacheStreamControlParent.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/ipc/FileDescriptor.h" +#include "mozilla/ipc/FileDescriptorSetChild.h" +#include "mozilla/ipc/FileDescriptorSetParent.h" +#include "mozilla/ipc/InputStreamParams.h" +#include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/ipc/PBackgroundParent.h" +#include "mozilla/ipc/PFileDescriptorSetChild.h" +#include "mozilla/ipc/PFileDescriptorSetParent.h" +#include "mozilla/SnappyUncompressInputStream.h" +#include "nsIAsyncInputStream.h" +#include "nsTArray.h" + +namespace { + +using mozilla::unused; +using mozilla::void_t; +using mozilla::dom::cache::CacheStreamControlChild; +using mozilla::dom::cache::CacheStreamControlParent; +using mozilla::dom::cache::PCacheReadStream; +using mozilla::dom::cache::PCacheStreamControlChild; +using mozilla::dom::cache::PCacheStreamControlParent; +using mozilla::dom::cache::ReadStream; +using mozilla::ipc::FileDescriptor; +using mozilla::ipc::PFileDescriptorSetChild; +using mozilla::ipc::PFileDescriptorSetParent; + +// There are separate concrete implementations of ReadStream for the child +// and parent processes. This is unfortunately necessary because the +// actor types are distinct for these two cases. Also, the interface for +// reporting the close event differs slightly for the child and parent +// StreamControl actors. + +// ---------------------------------------------------------------------------- + +class ReadStreamChild MOZ_FINAL : public ReadStream +{ +public: + ReadStreamChild(PCacheStreamControlChild* aControl, const nsID& aId, + nsIInputStream* aStream) + : ReadStream(aId, aStream) + , mControl(static_cast(aControl)) + { + MOZ_ASSERT(mControl); + mControl->AddListener(this); + } + + virtual ~ReadStreamChild() + { + NS_ASSERT_OWNINGTHREAD(ReadStream); + + NoteClosed(); + } + + virtual void NoteClosedOnOwningThread() MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(ReadStream); + + if (mClosed) { + return; + } + + mClosed = true; + mControl->RemoveListener(this); + mControl->NoteClosed(mId); + } + + virtual void ForgetOnOwningThread() MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(ReadStream); + + if (mClosed) { + return; + } + + mClosed = true; + mControl->RemoveListener(this); + } + + virtual void SerializeControl(PCacheReadStream* aReadStreamOut) MOZ_OVERRIDE + { + MOZ_ASSERT(aReadStreamOut); + MOZ_ASSERT(!mClosed); + aReadStreamOut->controlParent() = nullptr; + aReadStreamOut->controlChild() = mControl; + } + + virtual void + SerializeFds(PCacheReadStream* aReadStreamOut, + const nsTArray& fds) MOZ_OVERRIDE + { + MOZ_ASSERT(!mClosed); + PFileDescriptorSetChild* fdSet = nullptr; + if (!fds.IsEmpty()) { + fdSet = mControl->Manager()->SendPFileDescriptorSetConstructor(fds[0]); + for (uint32_t i = 1; i < fds.Length(); ++i) { + unused << fdSet->SendAddFileDescriptor(fds[i]); + } + } + + if (fdSet) { + aReadStreamOut->fds() = fdSet; + } else { + aReadStreamOut->fds() = void_t(); + } + } + +private: + CacheStreamControlChild* mControl; +}; + +// ---------------------------------------------------------------------------- + +class ReadStreamParent MOZ_FINAL : public ReadStream +{ +public: + ReadStreamParent(PCacheStreamControlParent* aControl, const nsID& aId, + nsIInputStream* aStream) + : ReadStream(aId, aStream) + , mControl(static_cast(aControl)) + { + MOZ_ASSERT(mControl); + mControl->AddListener(this); + } + + virtual ~ReadStreamParent() + { + NS_ASSERT_OWNINGTHREAD(ReadStream); + + NoteClosed(); + } + + virtual void NoteClosedOnOwningThread() MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(ReadStream); + + if (mClosed) { + return; + } + + mClosed = true; + mControl->RemoveListener(this); + // This can cause mControl to be destructed + mControl->RecvNoteClosed(mId); + mControl = nullptr; + } + + virtual void ForgetOnOwningThread() MOZ_OVERRIDE + { + NS_ASSERT_OWNINGTHREAD(ReadStream); + + if (mClosed) { + return; + } + + mClosed = true; + // This can cause mControl to be destroyed + mControl->RemoveListener(this); + mControl = nullptr; + } + + virtual void SerializeControl(PCacheReadStream* aReadStreamOut) MOZ_OVERRIDE + { + MOZ_ASSERT(aReadStreamOut); + MOZ_ASSERT(!mClosed); + MOZ_ASSERT(mControl); + aReadStreamOut->controlChild() = nullptr; + aReadStreamOut->controlParent() = mControl; + } + + virtual void + SerializeFds(PCacheReadStream* aReadStreamOut, + const nsTArray& fds) MOZ_OVERRIDE + { + MOZ_ASSERT(!mClosed); + MOZ_ASSERT(mControl); + PFileDescriptorSetParent* fdSet = nullptr; + if (!fds.IsEmpty()) { + fdSet = mControl->Manager()->SendPFileDescriptorSetConstructor(fds[0]); + for (uint32_t i = 1; i < fds.Length(); ++i) { + unused << fdSet->SendAddFileDescriptor(fds[i]); + } + } + + if (fdSet) { + aReadStreamOut->fds() = fdSet; + } else { + aReadStreamOut->fds() = void_t(); + } + } + +private: + CacheStreamControlParent* mControl; +}; + +// ---------------------------------------------------------------------------- + +} // anonymous namespace + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::unused; +using mozilla::ipc::FileDescriptor; +using mozilla::ipc::FileDescriptorSetChild; +using mozilla::ipc::FileDescriptorSetParent; +using mozilla::ipc::InputStreamParams; +using mozilla::ipc::OptionalFileDescriptorSet; +using mozilla::ipc::PFileDescriptorSetChild; + +// Runnable to notify actors that the ReadStream has closed. This must +// be done on the thread associated with the PBackground actor. Must be +// cancelable to execute on Worker threads (which can occur when the +// ReadStream is constructed on a child process Worker thread). +class ReadStream::NoteClosedRunnable MOZ_FINAL : public nsCancelableRunnable +{ +public: + explicit NoteClosedRunnable(ReadStream* aStream) + : mStream(aStream) + { } + + NS_IMETHOD Run() + { + mStream->NoteClosedOnOwningThread(); + return NS_OK; + } + + // Note, we must proceed with the Run() method since our actor will not + // clean itself up until we note that the stream is closed. + NS_IMETHOD Cancel() + { + Run(); + return NS_OK; + } + +private: + ~NoteClosedRunnable() { } + + nsRefPtr mStream; +}; + +// Runnable to clear actors without reporting that the ReadStream has +// closed. Since this can trigger actor destruction, we need to do +// it on the thread associated with the PBackground actor. Must be +// cancelable to execute on Worker threads (which can occur when the +// ReadStream is constructed on a child process Worker thread). +class ReadStream::ForgetRunnable MOZ_FINAL : public nsCancelableRunnable +{ +public: + explicit ForgetRunnable(ReadStream* aStream) + : mStream(aStream) + { } + + NS_IMETHOD Run() + { + mStream->ForgetOnOwningThread(); + return NS_OK; + } + + // Note, we must proceed with the Run() method so that we properly + // call RemoveListener on the actor. + NS_IMETHOD Cancel() + { + Run(); + return NS_OK; + } + +private: + ~ForgetRunnable() { } + + nsRefPtr mStream; +}; + +NS_IMPL_ISUPPORTS(mozilla::dom::cache::ReadStream, nsIInputStream, + ReadStream); + +// static +already_AddRefed +ReadStream::Create(const PCacheReadStreamOrVoid& aReadStreamOrVoid) +{ + if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) { + return nullptr; + } + + return Create(aReadStreamOrVoid.get_PCacheReadStream()); +} + +// static +already_AddRefed +ReadStream::Create(const PCacheReadStream& aReadStream) +{ + // The parameter may or may not be for a Cache created stream. The way we + // tell is by looking at the stream control actor. If the actor exists, + // then we know the Cache created it. + if (!aReadStream.controlChild() && !aReadStream.controlParent()) { + return nullptr; + } + + nsAutoTArray fds; + if (aReadStream.fds().type() == + OptionalFileDescriptorSet::TPFileDescriptorSetChild) { + + FileDescriptorSetChild* fdSetActor = + static_cast(aReadStream.fds().get_PFileDescriptorSetChild()); + MOZ_ASSERT(fdSetActor); + + fdSetActor->ForgetFileDescriptors(fds); + MOZ_ASSERT(!fds.IsEmpty()); + + unused << fdSetActor->Send__delete__(fdSetActor); + } else if (aReadStream.fds().type() == + OptionalFileDescriptorSet::TPFileDescriptorSetParent) { + + FileDescriptorSetParent* fdSetActor = + static_cast(aReadStream.fds().get_PFileDescriptorSetParent()); + MOZ_ASSERT(fdSetActor); + + fdSetActor->ForgetFileDescriptors(fds); + MOZ_ASSERT(!fds.IsEmpty()); + + if (!fdSetActor->Send__delete__(fdSetActor)) { + // child process is gone, warn and allow actor to clean up normally + NS_WARNING("Cache failed to delete fd set actor."); + } + } + + nsCOMPtr stream = + DeserializeInputStream(aReadStream.params(), fds); + MOZ_ASSERT(stream); + + // Currently we expect all cache read streams to be blocking file streams. +#ifdef DEBUG + nsCOMPtr asyncStream = do_QueryInterface(stream); + MOZ_ASSERT(!asyncStream); +#endif + + nsRefPtr ref; + + if (aReadStream.controlChild()) { + ref = new ReadStreamChild(aReadStream.controlChild(), aReadStream.id(), + stream); + } else { + ref = new ReadStreamParent(aReadStream.controlParent(), aReadStream.id(), + stream); + } + + return ref.forget(); +} + +// static +already_AddRefed +ReadStream::Create(PCacheStreamControlParent* aControl, const nsID& aId, + nsIInputStream* aStream) +{ + nsRefPtr ref = new ReadStreamParent(aControl, aId, aStream); + return ref.forget(); +} + +void +ReadStream::Serialize(PCacheReadStreamOrVoid* aReadStreamOut) +{ + MOZ_ASSERT(aReadStreamOut); + PCacheReadStream stream; + Serialize(&stream); + *aReadStreamOut = stream; +} + +void +ReadStream::Serialize(PCacheReadStream* aReadStreamOut) +{ + MOZ_ASSERT(aReadStreamOut); + MOZ_ASSERT(!mClosed); + + aReadStreamOut->id() = mId; + SerializeControl(aReadStreamOut); + + nsAutoTArray fds; + SerializeInputStream(mStream, aReadStreamOut->params(), fds); + + SerializeFds(aReadStreamOut, fds); + + // We're passing ownership across the IPC barrier with the control, so + // do not signal that the stream is closed here. + Forget(); +} + +void +ReadStream::CloseStream() +{ + Close(); +} + +void +ReadStream::CloseStreamWithoutReporting() +{ + Forget(); +} + +bool +ReadStream::MatchId(const nsID& aId) const +{ + return mId.Equals(aId); +} + +ReadStream::ReadStream(const nsID& aId, nsIInputStream* aStream) + : mId(aId) + , mStream(aStream) + , mSnappyStream(new SnappyUncompressInputStream(aStream)) + , mOwningThread(NS_GetCurrentThread()) + , mClosed(false) +{ + MOZ_ASSERT(mStream); +} + +ReadStream::~ReadStream() +{ + NS_ASSERT_OWNINGTHREAD(ReadStream); + + // We cannot directly call NoteClosed() here. The concrete subclasses + // destructors must do this because it takes code paths through virtual + // methods. We don't want to execute these while partially destroyed. + MOZ_ASSERT(mClosed); +} + +void +ReadStream::NoteClosed() +{ + if (mClosed) { + return; + } + + if (NS_GetCurrentThread() == mOwningThread) { + NoteClosedOnOwningThread(); + return; + } + + nsCOMPtr runnable = new NoteClosedRunnable(this); + nsresult rv = mOwningThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to dispatch Cache ReadStream NoteClosed() runnable."); + } +} + +void +ReadStream::Forget() +{ + if (mClosed) { + return; + } + + if (NS_GetCurrentThread() == mOwningThread) { + ForgetOnOwningThread(); + return; + } + + nsCOMPtr runnable = new ForgetRunnable(this); + nsresult rv = mOwningThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to dispatch Cache ReadStream Forget() runnable."); + } +} + +NS_IMETHODIMP +ReadStream::Close() +{ + NoteClosed(); + return mStream->Close(); +} + +NS_IMETHODIMP +ReadStream::Available(uint64_t* aNumAvailableOut) +{ + nsresult rv = mSnappyStream->Available(aNumAvailableOut); + + if (NS_FAILED(rv)) { + NoteClosed(); + } + + return rv; +} + +NS_IMETHODIMP +ReadStream::Read(char* aBuf, uint32_t aCount, uint32_t* aNumReadOut) +{ + MOZ_ASSERT(aNumReadOut); + + nsresult rv = mSnappyStream->Read(aBuf, aCount, aNumReadOut); + + // Don't auto-close when end of stream is hit. We want to close + // this stream on a particular thread in the parent case. + + if ((NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) || + *aNumReadOut == 0) { + NoteClosed(); + } + + return rv; +} + +NS_IMETHODIMP +ReadStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, + uint32_t aCount, uint32_t* aNumReadOut) +{ + MOZ_ASSERT(aNumReadOut); + + nsresult rv = mSnappyStream->ReadSegments(aWriter, aClosure, aCount, + aNumReadOut); + + // Don't auto-close when end of stream is hit. We want to close + // this stream on a particular thread in the parent case. + + if ((NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK && + rv != NS_ERROR_NOT_IMPLEMENTED) || *aNumReadOut == 0) { + NoteClosed(); + } + + return rv; +} + +NS_IMETHODIMP +ReadStream::IsNonBlocking(bool* aNonBlockingOut) +{ + return mSnappyStream->IsNonBlocking(aNonBlockingOut); +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/ReadStream.h b/dom/cache/ReadStream.h new file mode 100644 index 0000000000..b89dc7c97a --- /dev/null +++ b/dom/cache/ReadStream.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_ReadStream_h +#define mozilla_dom_cache_ReadStream_h + +#include "mozilla/ipc/FileDescriptor.h" +#include "nsCOMPtr.h" +#include "nsID.h" +#include "nsIInputStream.h" +#include "nsISupportsImpl.h" +#include "nsTArrayForwardDeclare.h" + +class nsIThread; + +namespace mozilla { +namespace dom { +namespace cache { + +class PCacheReadStream; +class PCacheReadStreamOrVoid; +class PCacheStreamControlParent; + +// IID for the dom::cache::ReadStream interface +#define NS_DOM_CACHE_READSTREAM_IID \ +{0x8e5da7c9, 0x0940, 0x4f1d, \ + {0x97, 0x25, 0x5c, 0x59, 0x38, 0xdd, 0xb9, 0x9f}} + +// Custom stream class for Request and Response bodies being read from +// a Cache. The main purpose of this class is to report back to the +// Cache's Manager when the stream is closed. This allows the Cache to +// accurately determine when the underlying body file can be deleted, +// etc. +// +// The ReadStream class also provides us with a convenient QI'able +// interface that we can use to pass additional meta-data with the +// stream channel. For example, Cache.put() can detect that the content +// script is passing a Cache-originated-stream back into the Cache +// again. This enables certain optimizations. +class ReadStream : public nsIInputStream +{ +public: + static already_AddRefed + Create(const PCacheReadStreamOrVoid& aReadStreamOrVoid); + + static already_AddRefed + Create(const PCacheReadStream& aReadStream); + + static already_AddRefed + Create(PCacheStreamControlParent* aControl, const nsID& aId, + nsIInputStream* aStream); + + void Serialize(PCacheReadStreamOrVoid* aReadStreamOut); + void Serialize(PCacheReadStream* aReadStreamOut); + + // methods called from the child and parent CacheStreamControl actors + void CloseStream(); + void CloseStreamWithoutReporting(); + bool MatchId(const nsID& aId) const; + +protected: + class NoteClosedRunnable; + class ForgetRunnable; + + ReadStream(const nsID& aId, nsIInputStream* aStream); + virtual ~ReadStream(); + + void NoteClosed(); + void Forget(); + + virtual void NoteClosedOnOwningThread() = 0; + virtual void ForgetOnOwningThread() = 0; + virtual void SerializeControl(PCacheReadStream* aReadStreamOut) = 0; + + virtual void + SerializeFds(PCacheReadStream* aReadStreamOut, + const nsTArray& fds) = 0; + + const nsID mId; + nsCOMPtr mStream; + nsCOMPtr mSnappyStream; + nsCOMPtr mOwningThread; + bool mClosed; + +public: + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_CACHE_READSTREAM_IID); + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIINPUTSTREAM +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(ReadStream, NS_DOM_CACHE_READSTREAM_IID); + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_ReadStream_h diff --git a/dom/cache/SavedTypes.h b/dom/cache/SavedTypes.h new file mode 100644 index 0000000000..62f770ff27 --- /dev/null +++ b/dom/cache/SavedTypes.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_SavedTypes_h +#define mozilla_dom_cache_SavedTypes_h + +// NOTE: This cannot be rolled into Types.h because the IPC dependency. +// breaks webidl unified builds. + +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/dom/cache/Types.h" +#include "nsCOMPtr.h" +#include "nsID.h" +#include "nsIOutputStream.h" + +namespace mozilla { +namespace dom { +namespace cache { + +struct StreamHolder +{ + nsCOMPtr mValue; +}; + +struct SavedRequest +{ + SavedRequest() : mHasBodyId(false) { mValue.body() = void_t(); } + PCacheRequest mValue; + bool mHasBodyId; + nsID mBodyId; + CacheId mCacheId; +}; + +struct SavedResponse +{ + SavedResponse() : mHasBodyId(false) { mValue.body() = void_t(); } + PCacheResponse mValue; + bool mHasBodyId; + nsID mBodyId; + CacheId mCacheId; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_SavedTypes_h diff --git a/dom/cache/StreamList.cpp b/dom/cache/StreamList.cpp new file mode 100644 index 0000000000..5992a93a6f --- /dev/null +++ b/dom/cache/StreamList.cpp @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/StreamList.h" + +#include "mozilla/dom/cache/CacheStreamControlParent.h" +#include "mozilla/dom/cache/Context.h" +#include "mozilla/dom/cache/Manager.h" +#include "nsIInputStream.h" + +namespace mozilla { +namespace dom { +namespace cache { + +StreamList::StreamList(Manager* aManager, Context* aContext) + : mManager(aManager) + , mContext(aContext) + , mCacheId(0) + , mStreamControl(nullptr) + , mActivated(false) +{ + MOZ_ASSERT(mManager); + MOZ_ASSERT(mContext); +} + +void +StreamList::SetStreamControl(CacheStreamControlParent* aStreamControl) +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + MOZ_ASSERT(aStreamControl); + + // For cases where multiple streams are serialized for a single list + // then the control will get passed multiple times. This is ok, but + // it should be the same control each time. + if (mStreamControl) { + MOZ_ASSERT(aStreamControl == mStreamControl); + return; + } + + mStreamControl = aStreamControl; + mStreamControl->SetStreamList(this); +} + +void +StreamList::RemoveStreamControl(CacheStreamControlParent* aStreamControl) +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + MOZ_ASSERT(mStreamControl); + MOZ_ASSERT(mStreamControl == aStreamControl); + mStreamControl = nullptr; +} + +void +StreamList::Activate(CacheId aCacheId) +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + MOZ_ASSERT(!mActivated); + MOZ_ASSERT(!mCacheId); + mActivated = true; + mCacheId = aCacheId; + mManager->AddRefCacheId(mCacheId); + mManager->AddStreamList(this); + + for (uint32_t i = 0; i < mList.Length(); ++i) { + mManager->AddRefBodyId(mList[i].mId); + } +} + +void +StreamList::Add(const nsID& aId, nsIInputStream* aStream) +{ + // All streams should be added on IO thread before we set the stream + // control on the owning IPC thread. + MOZ_ASSERT(!mStreamControl); + MOZ_ASSERT(aStream); + Entry* entry = mList.AppendElement(); + entry->mId = aId; + entry->mStream = aStream; +} + +already_AddRefed +StreamList::Extract(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + for (uint32_t i = 0; i < mList.Length(); ++i) { + if (mList[i].mId == aId) { + return mList[i].mStream.forget(); + } + } + return nullptr; +} + +void +StreamList::NoteClosed(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + for (uint32_t i = 0; i < mList.Length(); ++i) { + if (mList[i].mId == aId) { + mList.RemoveElementAt(i); + mManager->ReleaseBodyId(aId); + break; + } + } + + if (mList.IsEmpty() && mStreamControl) { + mStreamControl->Shutdown(); + } +} + +void +StreamList::NoteClosedAll() +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + for (uint32_t i = 0; i < mList.Length(); ++i) { + mManager->ReleaseBodyId(mList[i].mId); + } + mList.Clear(); + + if (mStreamControl) { + mStreamControl->Shutdown(); + } +} + +void +StreamList::Close(const nsID& aId) +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + if (mStreamControl) { + mStreamControl->Close(aId); + } +} + +void +StreamList::CloseAll() +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + if (mStreamControl) { + mStreamControl->CloseAll(); + } +} + +StreamList::~StreamList() +{ + NS_ASSERT_OWNINGTHREAD(StreamList); + MOZ_ASSERT(!mStreamControl); + if (mActivated) { + mManager->RemoveStreamList(this); + for (uint32_t i = 0; i < mList.Length(); ++i) { + mManager->ReleaseBodyId(mList[i].mId); + } + mManager->ReleaseCacheId(mCacheId); + } +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/StreamList.h b/dom/cache/StreamList.h new file mode 100644 index 0000000000..d284759808 --- /dev/null +++ b/dom/cache/StreamList.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_StreamList_h +#define mozilla_dom_cache_StreamList_h + +#include "mozilla/dom/cache/Types.h" +#include "mozilla/nsRefPtr.h" +#include "nsTArray.h" + +class nsIInputStream; + +namespace mozilla { +namespace dom { +namespace cache { + +class CacheStreamControlParent; +class Context; +class Manager; + +class StreamList +{ +public: + StreamList(Manager* aManager, Context* aContext); + + void SetStreamControl(CacheStreamControlParent* aStreamControl); + void RemoveStreamControl(CacheStreamControlParent* aStreamControl); + + void Activate(CacheId aCacheId); + + void Add(const nsID& aId, nsIInputStream* aStream); + already_AddRefed Extract(const nsID& aId); + + void NoteClosed(const nsID& aId); + void NoteClosedAll(); + void Close(const nsID& aId); + void CloseAll(); + +private: + ~StreamList(); + struct Entry + { + nsID mId; + nsCOMPtr mStream; + }; + nsRefPtr mManager; + nsRefPtr mContext; + CacheId mCacheId; + CacheStreamControlParent* mStreamControl; + nsTArray mList; + bool mActivated; + +public: + NS_INLINE_DECL_REFCOUNTING(cache::StreamList) +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_StreamList_h diff --git a/dom/cache/StreamUtils.cpp b/dom/cache/StreamUtils.cpp new file mode 100644 index 0000000000..b0f7eae0ae --- /dev/null +++ b/dom/cache/StreamUtils.cpp @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/StreamUtils.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/cache/CacheStreamControlChild.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/ipc/FileDescriptor.h" +#include "mozilla/ipc/FileDescriptorSetChild.h" + +namespace mozilla { +namespace dom { +namespace cache { + +namespace { + +using mozilla::unused; +using mozilla::void_t; +using mozilla::dom::cache::CacheStreamControlChild; +using mozilla::dom::cache::Feature; +using mozilla::dom::cache::PCacheReadStream; +using mozilla::ipc::FileDescriptor; +using mozilla::ipc::FileDescriptorSetChild; +using mozilla::ipc::OptionalFileDescriptorSet; + +void +StartDestroyStreamChild(const PCacheReadStream& aReadStream) +{ + CacheStreamControlChild* cacheControl = + static_cast(aReadStream.controlChild()); + if (cacheControl) { + cacheControl->StartDestroy(); + } + + if (aReadStream.fds().type() == + OptionalFileDescriptorSet::TPFileDescriptorSetChild) { + nsAutoTArray fds; + + FileDescriptorSetChild* fdSetActor = + static_cast(aReadStream.fds().get_PFileDescriptorSetChild()); + MOZ_ASSERT(fdSetActor); + + fdSetActor->ForgetFileDescriptors(fds); + MOZ_ASSERT(!fds.IsEmpty()); + + unused << fdSetActor->Send__delete__(fdSetActor); + } +} + +void +AddFeatureToStreamChild(const PCacheReadStream& aReadStream, Feature* aFeature) +{ + CacheStreamControlChild* cacheControl = + static_cast(aReadStream.controlChild()); + if (cacheControl) { + cacheControl->SetFeature(aFeature); + } +} + +} // anonymous namespace + +void +StartDestroyStreamChild(const PCacheResponseOrVoid& aResponseOrVoid) +{ + if (aResponseOrVoid.type() == PCacheResponseOrVoid::Tvoid_t) { + return; + } + + StartDestroyStreamChild(aResponseOrVoid.get_PCacheResponse()); +} + +void +StartDestroyStreamChild(const PCacheResponse& aResponse) +{ + if (aResponse.body().type() == PCacheReadStreamOrVoid::Tvoid_t) { + return; + } + + StartDestroyStreamChild(aResponse.body().get_PCacheReadStream()); +} + +void +StartDestroyStreamChild(const nsTArray& aResponses) +{ + for (uint32_t i = 0; i < aResponses.Length(); ++i) { + StartDestroyStreamChild(aResponses[i]); + } +} + +void +StartDestroyStreamChild(const nsTArray& aRequests) +{ + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + if (aRequests[i].body().type() == PCacheReadStreamOrVoid::Tvoid_t) { + continue; + } + StartDestroyStreamChild(aRequests[i].body().get_PCacheReadStream()); + } +} + +void +AddFeatureToStreamChild(const PCacheResponseOrVoid& aResponseOrVoid, + Feature* aFeature) +{ + if (aResponseOrVoid.type() == PCacheResponseOrVoid::Tvoid_t) { + return; + } + + AddFeatureToStreamChild(aResponseOrVoid.get_PCacheResponse(), aFeature); +} + +void +AddFeatureToStreamChild(const PCacheResponse& aResponse, + Feature* aFeature) +{ + if (aResponse.body().type() == PCacheReadStreamOrVoid::Tvoid_t) { + return; + } + + AddFeatureToStreamChild(aResponse.body().get_PCacheReadStream(), aFeature); +} + +void +AddFeatureToStreamChild(const nsTArray& aResponses, + Feature* aFeature) +{ + for (uint32_t i = 0; i < aResponses.Length(); ++i) { + AddFeatureToStreamChild(aResponses[i], aFeature); + } +} + +void +AddFeatureToStreamChild(const nsTArray& aRequests, + Feature* aFeature) +{ + for (uint32_t i = 0; i < aRequests.Length(); ++i) { + if (aRequests[i].body().type() == PCacheReadStreamOrVoid::Tvoid_t) { + continue; + } + AddFeatureToStreamChild(aRequests[i].body().get_PCacheReadStream(), + aFeature); + } +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/StreamUtils.h b/dom/cache/StreamUtils.h new file mode 100644 index 0000000000..cb8d1bb657 --- /dev/null +++ b/dom/cache/StreamUtils.h @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_StreamUtils_h +#define mozilla_dom_cache_StreamUtils_h + +#include "nsTArrayForwardDeclare.h" + +namespace mozilla { +namespace dom { +namespace cache { + +class Feature; +class PCacheRequest; +class PCacheResponse; +class PCacheResponseOrVoid; + +void StartDestroyStreamChild(const PCacheResponseOrVoid& aResponseOrVoid); +void StartDestroyStreamChild(const PCacheResponse& aResponse); +void StartDestroyStreamChild(const nsTArray& aResponses); +void StartDestroyStreamChild(const nsTArray& aRequests); + +void AddFeatureToStreamChild(const PCacheResponseOrVoid& aResponseOrVoid, + Feature* aFeature); +void AddFeatureToStreamChild(const PCacheResponse& aResponse, + Feature* aFeature); +void AddFeatureToStreamChild(const nsTArray& aResponses, + Feature* aFeature); +void AddFeatureToStreamChild(const nsTArray& aRequests, + Feature* aFeature); + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_StreamUtils_h diff --git a/dom/cache/TypeUtils.cpp b/dom/cache/TypeUtils.cpp new file mode 100644 index 0000000000..ff8d9ad34b --- /dev/null +++ b/dom/cache/TypeUtils.cpp @@ -0,0 +1,481 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/cache/TypeUtils.h" + +#include "mozilla/unused.h" +#include "mozilla/dom/CacheBinding.h" +#include "mozilla/dom/InternalRequest.h" +#include "mozilla/dom/Request.h" +#include "mozilla/dom/Response.h" +#include "mozilla/dom/cache/PCacheTypes.h" +#include "mozilla/dom/cache/ReadStream.h" +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/ipc/FileDescriptorSetChild.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/ipc/PFileDescriptorSetChild.h" +#include "mozilla/ipc/InputStreamUtils.h" +#include "nsCOMPtr.h" +#include "nsIAsyncInputStream.h" +#include "nsIAsyncOutputStream.h" +#include "nsIIPCSerializableInputStream.h" +#include "nsStreamUtils.h" +#include "nsString.h" +#include "nsURLParsers.h" + +namespace { + +using mozilla::ErrorResult; + +// Utility function to remove the fragment from a URL, check its scheme, and optionally +// provide a URL without the query. We're not using nsIURL or URL to do this because +// they require going to the main thread. +static void +ProcessURL(nsAString& aUrl, bool* aSchemeValidOut, + nsAString* aUrlWithoutQueryOut, ErrorResult& aRv) +{ + NS_ConvertUTF16toUTF8 flatURL(aUrl); + const char* url = flatURL.get(); + + // off the main thread URL parsing using nsStdURLParser. + nsCOMPtr urlParser = new nsStdURLParser(); + + uint32_t pathPos; + int32_t pathLen; + uint32_t schemePos; + int32_t schemeLen; + aRv = urlParser->ParseURL(url, flatURL.Length(), &schemePos, &schemeLen, + nullptr, nullptr, // ignore authority + &pathPos, &pathLen); + if (NS_WARN_IF(aRv.Failed())) { return; } + + if (aSchemeValidOut) { + nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen)); + *aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") || + scheme.LowerCaseEqualsLiteral("https"); + } + + uint32_t queryPos; + int32_t queryLen; + uint32_t refPos; + int32_t refLen; + + aRv = urlParser->ParsePath(url + pathPos, flatURL.Length() - pathPos, + nullptr, nullptr, // ignore filepath + &queryPos, &queryLen, + &refPos, &refLen); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + + // TODO: Remove this once Request/Response properly strip the fragment (bug 1110476) + if (refLen >= 0) { + // ParsePath gives us ref position relative to the start of the path + refPos += pathPos; + + aUrl = Substring(aUrl, 0, refPos - 1); + } + + if (!aUrlWithoutQueryOut) { + return; + } + + if (queryLen < 0) { + *aUrlWithoutQueryOut = aUrl; + return; + } + + // ParsePath gives us query position relative to the start of the path + queryPos += pathPos; + + // We want everything before the query sine we already removed the trailing + // fragment + *aUrlWithoutQueryOut = Substring(aUrl, 0, queryPos - 1); +} + +} // anonymous namespace + +namespace mozilla { +namespace dom { +namespace cache { + +using mozilla::ipc::BackgroundChild; +using mozilla::ipc::FileDescriptor; +using mozilla::ipc::FileDescriptorSetChild; +using mozilla::ipc::PFileDescriptorSetChild; +using mozilla::ipc::PBackgroundChild; +using mozilla::ipc::OptionalFileDescriptorSet; + + +already_AddRefed +TypeUtils::ToInternalRequest(const RequestOrUSVString& aIn, + BodyAction aBodyAction, ErrorResult& aRv) +{ + if (aIn.IsRequest()) { + Request& request = aIn.GetAsRequest(); + + // Check and set bodyUsed flag immediately because its on Request + // instead of InternalRequest. + CheckAndSetBodyUsed(&request, aBodyAction, aRv); + if (aRv.Failed()) { return nullptr; } + + return request.GetInternalRequest(); + } + + return ToInternalRequest(aIn.GetAsUSVString(), aRv); +} + +already_AddRefed +TypeUtils::ToInternalRequest(const OwningRequestOrUSVString& aIn, + BodyAction aBodyAction, ErrorResult& aRv) +{ + + if (aIn.IsRequest()) { + nsRefPtr request = aIn.GetAsRequest().get(); + + // Check and set bodyUsed flag immediately because its on Request + // instead of InternalRequest. + CheckAndSetBodyUsed(request, aBodyAction, aRv); + if (aRv.Failed()) { return nullptr; } + + return request->GetInternalRequest(); + } + + return ToInternalRequest(aIn.GetAsUSVString(), aRv); +} + +void +TypeUtils::ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn, + BodyAction aBodyAction, + ReferrerAction aReferrerAction, + SchemeAction aSchemeAction, ErrorResult& aRv) +{ + MOZ_ASSERT(aIn); + + aIn->GetMethod(aOut.method()); + + nsAutoCString url; + aIn->GetURL(url); + CopyUTF8toUTF16(url, aOut.url()); + + bool schemeValid; + ProcessURL(aOut.url(), &schemeValid, &aOut.urlWithoutQuery(), aRv); + if (aRv.Failed()) { + return; + } + + if (!schemeValid) { + if (aSchemeAction == TypeErrorOnInvalidScheme) { + NS_NAMED_LITERAL_STRING(label, "Request"); + aRv.ThrowTypeError(MSG_INVALID_URL_SCHEME, &label, &aOut.url()); + return; + } + + if (aSchemeAction == NetworkErrorOnInvalidScheme) { + aRv.Throw(NS_ERROR_DOM_NETWORK_ERR); + return; + } + } + + if (aReferrerAction == ExpandReferrer) { + UpdateRequestReferrer(GetGlobalObject(), aIn); + } + aIn->GetReferrer(aOut.referrer()); + + nsRefPtr headers = aIn->Headers(); + MOZ_ASSERT(headers); + headers->GetPHeaders(aOut.headers()); + aOut.headersGuard() = headers->Guard(); + aOut.mode() = aIn->Mode(); + aOut.credentials() = aIn->GetCredentialsMode(); + aOut.context() = aIn->ContentPolicyType(); + + if (aBodyAction == IgnoreBody) { + aOut.body() = void_t(); + return; + } + + // BodyUsed flag is checked and set previously in ToInternalRequest() + + nsCOMPtr stream; + aIn->GetBody(getter_AddRefs(stream)); + SerializeCacheStream(stream, &aOut.body(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } +} + +void +TypeUtils::ToPCacheResponseWithoutBody(PCacheResponse& aOut, + InternalResponse& aIn, ErrorResult& aRv) +{ + aOut.type() = aIn.Type(); + + nsAutoCString url; + aIn.GetUrl(url); + CopyUTF8toUTF16(url, aOut.url()); + + if (aOut.url() != EmptyString()) { + // Pass all Response URL schemes through... The spec only requires we take + // action on invalid schemes for Request objects. + ProcessURL(aOut.url(), nullptr, nullptr, aRv); + if (aRv.Failed()) { + return; + } + } + + aOut.status() = aIn.GetStatus(); + aOut.statusText() = aIn.GetStatusText(); + nsRefPtr headers = aIn.Headers(); + MOZ_ASSERT(headers); + headers->GetPHeaders(aOut.headers()); + aOut.headersGuard() = headers->Guard(); +} + +void +TypeUtils::ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aRv) +{ + if (aIn.BodyUsed()) { + aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR); + return; + } + + nsRefPtr ir = aIn.GetInternalResponse(); + ToPCacheResponseWithoutBody(aOut, *ir, aRv); + + nsCOMPtr stream; + aIn.GetBody(getter_AddRefs(stream)); + if (stream) { + aIn.SetBodyUsed(); + } + + SerializeCacheStream(stream, &aOut.body(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } +} + +// static +void +TypeUtils::ToPCacheQueryParams(PCacheQueryParams& aOut, + const CacheQueryOptions& aIn) +{ + aOut.ignoreSearch() = aIn.mIgnoreSearch; + aOut.ignoreMethod() = aIn.mIgnoreMethod; + aOut.ignoreVary() = aIn.mIgnoreVary; + aOut.prefixMatch() = aIn.mPrefixMatch; + aOut.cacheNameSet() = aIn.mCacheName.WasPassed(); + if (aOut.cacheNameSet()) { + aOut.cacheName() = aIn.mCacheName.Value(); + } else { + aOut.cacheName() = NS_LITERAL_STRING(""); + } +} + +already_AddRefed +TypeUtils::ToResponse(const PCacheResponse& aIn) +{ + nsRefPtr ir; + switch (aIn.type()) + { + case ResponseType::Error: + ir = InternalResponse::NetworkError(); + break; + case ResponseType::Opaque: + ir = InternalResponse::OpaqueResponse(); + break; + case ResponseType::Default: + ir = new InternalResponse(aIn.status(), aIn.statusText()); + break; + case ResponseType::Basic: + { + nsRefPtr inner = new InternalResponse(aIn.status(), + aIn.statusText()); + ir = InternalResponse::BasicResponse(inner); + break; + } + case ResponseType::Cors: + { + nsRefPtr inner = new InternalResponse(aIn.status(), + aIn.statusText()); + ir = InternalResponse::CORSResponse(inner); + break; + } + default: + MOZ_CRASH("Unexpected ResponseType!"); + } + MOZ_ASSERT(ir); + + ir->SetUrl(NS_ConvertUTF16toUTF8(aIn.url())); + + nsRefPtr internalHeaders = + new InternalHeaders(aIn.headers(), aIn.headersGuard()); + ErrorResult result; + ir->Headers()->SetGuard(aIn.headersGuard(), result); + MOZ_ASSERT(!result.Failed()); + ir->Headers()->Fill(*internalHeaders, result); + MOZ_ASSERT(!result.Failed()); + + nsCOMPtr stream = ReadStream::Create(aIn.body()); + ir->SetBody(stream); + + nsRefPtr ref = new Response(GetGlobalObject(), ir); + return ref.forget(); +} + +already_AddRefed +TypeUtils::ToInternalRequest(const PCacheRequest& aIn) +{ + nsRefPtr internalRequest = new InternalRequest(); + + internalRequest->SetMethod(aIn.method()); + internalRequest->SetURL(NS_ConvertUTF16toUTF8(aIn.url())); + internalRequest->SetReferrer(aIn.referrer()); + internalRequest->SetMode(aIn.mode()); + internalRequest->SetCredentialsMode(aIn.credentials()); + internalRequest->SetContentPolicyType(aIn.context()); + + nsRefPtr internalHeaders = + new InternalHeaders(aIn.headers(), aIn.headersGuard()); + ErrorResult result; + internalRequest->Headers()->SetGuard(aIn.headersGuard(), result); + MOZ_ASSERT(!result.Failed()); + internalRequest->Headers()->Fill(*internalHeaders, result); + MOZ_ASSERT(!result.Failed()); + + nsCOMPtr stream = ReadStream::Create(aIn.body()); + + internalRequest->SetBody(stream); + + return internalRequest.forget(); +} + +already_AddRefed +TypeUtils::ToRequest(const PCacheRequest& aIn) +{ + nsRefPtr internalRequest = ToInternalRequest(aIn); + nsRefPtr request = new Request(GetGlobalObject(), internalRequest); + return request.forget(); +} + +void +TypeUtils::CheckAndSetBodyUsed(Request* aRequest, BodyAction aBodyAction, + ErrorResult& aRv) +{ + MOZ_ASSERT(aRequest); + + if (aBodyAction == IgnoreBody) { + return; + } + + if (aRequest->BodyUsed()) { + aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR); + return; + } + + nsCOMPtr stream; + aRequest->GetBody(getter_AddRefs(stream)); + if (stream) { + aRequest->SetBodyUsed(); + } +} + +already_AddRefed +TypeUtils::ToInternalRequest(const nsAString& aIn, ErrorResult& aRv) +{ + RequestOrUSVString requestOrString; + requestOrString.SetAsUSVString().Rebind(aIn.Data(), aIn.Length()); + + // Re-create a GlobalObject stack object so we can use webidl Constructors. + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(GetGlobalObject()))) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + JSContext* cx = jsapi.cx(); + GlobalObject global(cx, GetGlobalObject()->GetGlobalJSObject()); + MOZ_ASSERT(!global.Failed()); + + nsRefPtr request = Request::Constructor(global, requestOrString, + RequestInit(), aRv); + if (NS_WARN_IF(aRv.Failed())) { return nullptr; } + + return request->GetInternalRequest(); +} + +void +TypeUtils::SerializeCacheStream(nsIInputStream* aStream, + PCacheReadStreamOrVoid* aStreamOut, + ErrorResult& aRv) +{ + *aStreamOut = void_t(); + if (!aStream) { + return; + } + + nsRefPtr controlled = do_QueryObject(aStream); + if (controlled) { + controlled->Serialize(aStreamOut); + return; + } + + // TODO: implement CrossProcessPipe if we cannot directly serialize (bug 1110814) + nsCOMPtr serial = do_QueryInterface(aStream); + if (!serial) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + PCacheReadStream readStream; + readStream.controlChild() = nullptr; + readStream.controlParent() = nullptr; + + nsAutoTArray fds; + SerializeInputStream(aStream, readStream.params(), fds); + + PFileDescriptorSetChild* fdSet = nullptr; + if (!fds.IsEmpty()) { + // We should not be serializing until we have an actor ready + PBackgroundChild* manager = BackgroundChild::GetForCurrentThread(); + MOZ_ASSERT(manager); + + fdSet = manager->SendPFileDescriptorSetConstructor(fds[0]); + for (uint32_t i = 1; i < fds.Length(); ++i) { + unused << fdSet->SendAddFileDescriptor(fds[i]); + } + } + + if (fdSet) { + readStream.fds() = fdSet; + } else { + readStream.fds() = void_t(); + } + + *aStreamOut = readStream; +} + +nsIThread* +TypeUtils::GetStreamThread() +{ + AssertOwningThread(); + + if (!mStreamThread) { + // Named threads only allow 16 bytes for their names. Try to make + // it meaningful... + // TODO: use a thread pool or singleton thread here (bug 1119864) + nsresult rv = NS_NewNamedThread("DOMCacheTypeU", + getter_AddRefs(mStreamThread)); + if (NS_FAILED(rv) || !mStreamThread) { + MOZ_CRASH("Failed to create DOM Cache serialization thread."); + } + } + + return mStreamThread; +} + +} // namespace cache +} // namespace dom +} // namespace mozilla diff --git a/dom/cache/TypeUtils.h b/dom/cache/TypeUtils.h new file mode 100644 index 0000000000..90aae52b4d --- /dev/null +++ b/dom/cache/TypeUtils.h @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_TypesUtils_h +#define mozilla_dom_cache_TypesUtils_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindingUtils.h" +#include "nsCOMPtr.h" +#include "nsError.h" + +class nsIGlobalObject; +class nsIInputStream; + +namespace mozilla { +namespace dom { + +struct CacheQueryOptions; +class InternalRequest; +class InternalResponse; +class OwningRequestOrUSVString; +class Request; +class RequestOrUSVString; +class Response; +template class Optional; + +namespace cache { + +class PCacheQueryParams; +class PCacheReadStream; +class PCacheReadStreamOrVoid; +class PCacheRequest; +class PCacheRequestOrVoid; +class PCacheResponse; +class PCacheStreamControlChild; + +class TypeUtils +{ +public: + enum BodyAction + { + IgnoreBody, + ReadBody + }; + + enum ReferrerAction + { + PassThroughReferrer, + ExpandReferrer + }; + + enum SchemeAction + { + IgnoreInvalidScheme, + TypeErrorOnInvalidScheme, + NetworkErrorOnInvalidScheme + }; + + ~TypeUtils() { } + virtual nsIGlobalObject* GetGlobalObject() const = 0; +#ifdef DEBUG + virtual void AssertOwningThread() const = 0; +#else + inline void AssertOwningThread() const { } +#endif + + already_AddRefed + ToInternalRequest(const RequestOrUSVString& aIn, BodyAction aBodyAction, + ErrorResult& aRv); + + already_AddRefed + ToInternalRequest(const OwningRequestOrUSVString& aIn, BodyAction aBodyAction, + ErrorResult& aRv); + + void + ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn, + BodyAction aBodyAction, ReferrerAction aReferrerAction, + SchemeAction aSchemeAction, ErrorResult& aRv); + + void + ToPCacheResponseWithoutBody(PCacheResponse& aOut, InternalResponse& aIn, + ErrorResult& aRv); + + void + ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aRv); + + void + ToPCacheQueryParams(PCacheQueryParams& aOut, const CacheQueryOptions& aIn); + + already_AddRefed + ToResponse(const PCacheResponse& aIn); + + already_AddRefed + ToInternalRequest(const PCacheRequest& aIn); + + already_AddRefed + ToRequest(const PCacheRequest& aIn); + +private: + void + CheckAndSetBodyUsed(Request* aRequest, BodyAction aBodyAction, + ErrorResult& aRv); + + already_AddRefed + ToInternalRequest(const nsAString& aIn, ErrorResult& aRv); + + void + SerializeCacheStream(nsIInputStream* aStream, PCacheReadStreamOrVoid* aStreamOut, + ErrorResult& aRv); + + nsIThread* GetStreamThread(); + + nsCOMPtr mStreamThread; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_TypesUtils_h diff --git a/dom/cache/Types.h b/dom/cache/Types.h new file mode 100644 index 0000000000..7ffae73c65 --- /dev/null +++ b/dom/cache/Types.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_cache_Types_h +#define mozilla_dom_cache_Types_h + +#include +#include "nsCOMPtr.h" +#include "nsIFile.h" +#include "nsString.h" + +namespace mozilla { +namespace dom { +namespace cache { + +enum Namespace +{ + DEFAULT_NAMESPACE, + CHROME_ONLY_NAMESPACE, + NUMBER_OF_NAMESPACES +}; + +typedef uintptr_t RequestId; +static const RequestId INVALID_REQUEST_ID = 0; + +typedef int32_t CacheId; + +struct QuotaInfo +{ + QuotaInfo() : mIsApp(false) { } + nsCOMPtr mDir; + nsCString mGroup; + nsCString mOrigin; + bool mIsApp; +}; + +} // namespace cache +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_cache_Types_h diff --git a/dom/cache/moz.build b/dom/cache/moz.build new file mode 100644 index 0000000000..bd4b86c3b5 --- /dev/null +++ b/dom/cache/moz.build @@ -0,0 +1,83 @@ +# -*- 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.mozilla.dom.cache += [ + 'Action.h', + 'ActorChild.h', + 'ActorUtils.h', + 'AutoUtils.h', + 'Cache.h', + 'CacheChild.h', + 'CacheParent.h', + 'CacheStorage.h', + 'CacheStorageChild.h', + 'CacheStorageParent.h', + 'CacheStreamControlChild.h', + 'CacheStreamControlParent.h', + 'Context.h', + 'DBAction.h', + 'DBSchema.h', + 'Feature.h', + 'FetchPut.h', + 'FileUtils.h', + 'IPCUtils.h', + 'Manager.h', + 'ManagerId.h', + 'PrincipalVerifier.h', + 'QuotaClient.h', + 'ReadStream.h', + 'SavedTypes.h', + 'StreamList.h', + 'StreamUtils.h', + 'Types.h', + 'TypeUtils.h', +] + +UNIFIED_SOURCES += [ + 'Action.cpp', + 'ActorChild.cpp', + 'AutoUtils.cpp', + 'Cache.cpp', + 'CacheChild.cpp', + 'CacheParent.cpp', + 'CacheStorage.cpp', + 'CacheStorageChild.cpp', + 'CacheStorageParent.cpp', + 'CacheStreamControlChild.cpp', + 'CacheStreamControlParent.cpp', + 'Context.cpp', + 'DBAction.cpp', + 'DBSchema.cpp', + 'Feature.cpp', + 'FetchPut.cpp', + 'FileUtils.cpp', + 'Manager.cpp', + 'ManagerId.cpp', + 'PrincipalVerifier.cpp', + 'QuotaClient.cpp', + 'ReadStream.cpp', + 'StreamList.cpp', + 'StreamUtils.cpp', + 'TypeUtils.cpp', +] + +IPDL_SOURCES += [ + 'CacheInitData.ipdlh', + 'PCache.ipdl', + 'PCacheStorage.ipdl', + 'PCacheStreamControl.ipdl', + 'PCacheTypes.ipdlh', +] + +include('/ipc/chromium/chromium-config.mozbuild') + +LOCAL_INCLUDES += [ + '../workers', +] + +FAIL_ON_WARNINGS = True + +FINAL_LIBRARY = 'xul' diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 19a1c879db..3bf86f468f 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -341,7 +341,7 @@ public: } // Return a SourceSurface that contains the FillPaint or StrokePaint source. - TemporaryRef + already_AddRefed DoSourcePaint(mgfx::IntRect& aRect, CanvasRenderingContext2D::Style aStyle) { if (aRect.IsEmpty()) { @@ -4172,7 +4172,7 @@ bool CanvasRenderingContext2D::IsPointInStroke(const CanvasPath& mPath, double x // Returns a surface that contains only the part needed to draw aSourceRect. // On entry, aSourceRect is relative to aSurface, and on return aSourceRect is // relative to the returned surface. -static TemporaryRef +static already_AddRefed ExtractSubrect(SourceSurface* aSurface, mgfx::Rect* aSourceRect, DrawTarget* aTargetDT) { mgfx::Rect roundedOutSourceRect = *aSourceRect; @@ -5525,7 +5525,7 @@ CanvasPath::CanvasPath(nsISupports* aParent) mPathBuilder = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget()->CreatePathBuilder(); } -CanvasPath::CanvasPath(nsISupports* aParent, TemporaryRef aPathBuilder) +CanvasPath::CanvasPath(nsISupports* aParent, already_AddRefed aPathBuilder) : mParent(aParent), mPathBuilder(aPathBuilder) { if (!mPathBuilder) { @@ -5756,7 +5756,7 @@ CanvasPath::AddPath(CanvasPath& aCanvasPath, const Optional>& tempPath->StreamToSink(mPathBuilder); } -TemporaryRef +already_AddRefed CanvasPath::GetPath(const CanvasWindingRule& winding, const DrawTarget* aTarget) const { FillRule fillRule = FillRule::FILL_WINDING; diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index 2f0f515cb8..a36dd86d2a 100644 --- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -91,14 +91,14 @@ public: const gfx::Point& aCP2, const gfx::Point& aCP3); - TemporaryRef GetPath(const CanvasWindingRule& aWinding, + already_AddRefed GetPath(const CanvasWindingRule& aWinding, const gfx::DrawTarget* aTarget) const; explicit CanvasPath(nsISupports* aParent); - // TemporaryRef arg because the return value from Path::CopyToBuilder() is - // passed directly and we can't drop the only ref to have a raw pointer. + // already_AddRefed arg because the return value from Path::CopyToBuilder() + // is passed directly and we can't drop the only ref to have a raw pointer. CanvasPath(nsISupports* aParent, - TemporaryRef aPathBuilder); + already_AddRefed aPathBuilder); void AddPath(CanvasPath& aCanvasPath, const Optional>& aMatrix); @@ -510,7 +510,7 @@ public: const char16_t* aEncoderOptions, nsIInputStream **aStream) override; - mozilla::TemporaryRef GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) override + already_AddRefed GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) override { EnsureTarget(); if (aPremultAlpha) { diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 770ebf6089..67065ae128 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -1696,7 +1696,7 @@ WebGLContext::MakeContextCurrent() const gl->MakeCurrent(); } -mozilla::TemporaryRef +already_AddRefed WebGLContext::GetSurfaceSnapshot(bool* out_premultAlpha) { if (!gl) diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 210f3413e0..d557f9cdcd 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -223,7 +223,7 @@ public: const char16_t* encoderOptions, nsIInputStream** out_stream) override; - mozilla::TemporaryRef + already_AddRefed GetSurfaceSnapshot(bool* out_premultAlpha) override; NS_IMETHOD SetIsOpaque(bool) override { return NS_OK; }; diff --git a/dom/canvas/WebGLContextLossHandler.cpp b/dom/canvas/WebGLContextLossHandler.cpp index b15b3368e4..bf19b1ddd2 100644 --- a/dom/canvas/WebGLContextLossHandler.cpp +++ b/dom/canvas/WebGLContextLossHandler.cpp @@ -31,7 +31,7 @@ WebGLContextLossHandler::~WebGLContextLossHandler() void WebGLContextLossHandler::StartTimer(unsigned long delayMS) { - // We can't pass a TemporaryRef through InitWithFuncCallback, so we + // We can't pass an already_AddRefed through InitWithFuncCallback, so we // should do the AddRef/Release manually. this->AddRef(); diff --git a/dom/canvas/WebGLProgram.cpp b/dom/canvas/WebGLProgram.cpp index 0e056e8d52..908fcb56bc 100644 --- a/dom/canvas/WebGLProgram.cpp +++ b/dom/canvas/WebGLProgram.cpp @@ -80,7 +80,7 @@ AddActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArra //#define DUMP_SHADERVAR_MAPPINGS -static TemporaryRef +static already_AddRefed QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl) { RefPtr info(new webgl::LinkedProgramInfo(prog)); diff --git a/dom/canvas/nsICanvasRenderingContextInternal.h b/dom/canvas/nsICanvasRenderingContextInternal.h index fb1ef7c847..d7ffcd68d7 100644 --- a/dom/canvas/nsICanvasRenderingContextInternal.h +++ b/dom/canvas/nsICanvasRenderingContextInternal.h @@ -109,7 +109,7 @@ public: // If aPremultAlpha is provided, then it assumed the callee can handle // un-premultiplied surfaces, and *aPremultAlpha will be set to false // if one is returned. - virtual mozilla::TemporaryRef GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) = 0; + virtual already_AddRefed GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) = 0; // If this context is opaque, the backing store of the canvas should // be created as opaque; all compositing operators should assume the diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index e1e7983834..23acde9144 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -2444,13 +2444,16 @@ EventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame, actualDevPixelScrollAmount.y = 0; } + nsIScrollableFrame::ScrollSnapMode snapMode = nsIScrollableFrame::DISABLE_SNAP; nsIAtom* origin = nullptr; switch (aEvent->deltaMode) { case nsIDOMWheelEvent::DOM_DELTA_LINE: origin = nsGkAtoms::mouseWheel; + snapMode = nsIScrollableFrame::ENABLE_SNAP; break; case nsIDOMWheelEvent::DOM_DELTA_PAGE: origin = nsGkAtoms::pages; + snapMode = nsIScrollableFrame::ENABLE_SNAP; break; case nsIDOMWheelEvent::DOM_DELTA_PIXEL: origin = nsGkAtoms::pixels; @@ -2510,7 +2513,7 @@ EventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame, nsIntPoint overflow; aScrollableFrame->ScrollBy(actualDevPixelScrollAmount, nsIScrollableFrame::DEVICE_PIXELS, - mode, &overflow, origin, momentum); + mode, &overflow, origin, momentum, snapMode); if (!scrollFrameWeak.IsAlive()) { // If the scroll causes changing the layout, we can think that the event @@ -3011,6 +3014,13 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, { MOZ_ASSERT(aEvent->mFlags.mIsTrusted); ScrollbarsForWheel::MayInactivate(); + WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent(); + nsIScrollableFrame* scrollTarget = + ComputeScrollTarget(aTargetFrame, wheelEvent, + COMPUTE_DEFAULT_ACTION_TARGET); + if (scrollTarget) { + scrollTarget->ScrollSnap(); + } } break; case NS_WHEEL_WHEEL: diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index adeb40451d..cf0c9dfa1d 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -887,5 +887,13 @@ FetchDriver::OnRedirectVerifyCallback(nsresult aResult) mRedirectCallback = nullptr; return NS_OK; } + +void +FetchDriver::SetDocument(nsIDocument* aDocument) +{ + // Cannot set document after Fetch() has been called. + MOZ_ASSERT(mFetchRecursionCount == 0); + mDocument = aDocument; +} } // namespace dom } // namespace mozilla diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index 96cc10e24a..87f87063f3 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -59,12 +59,7 @@ public: NS_IMETHOD Fetch(FetchDriverObserver* aObserver); void - SetDocument(nsIDocument* aDocument) - { - // Cannot set document after Fetch() has been called. - MOZ_ASSERT(mFetchRecursionCount == 0); - mDocument = aDocument; - } + SetDocument(nsIDocument* aDocument); private: nsCOMPtr mPrincipal; diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 68649f55f0..940430cd9c 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -979,7 +979,7 @@ HTMLCanvasElement::MarkContextClean() mCurrentContext->MarkContextClean(); } -TemporaryRef +already_AddRefed HTMLCanvasElement::GetSurfaceSnapshot(bool* aPremultAlpha) { if (!mCurrentContext) diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index df84528142..a133c2a6cb 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -165,7 +165,7 @@ public: */ bool GetIsOpaque(); - virtual TemporaryRef GetSurfaceSnapshot(bool* aPremultAlpha = nullptr); + virtual already_AddRefed GetSurfaceSnapshot(bool* aPremultAlpha = nullptr); virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute, diff --git a/dom/indexedDB/PBackgroundIDBVersionChangeTransaction.ipdl b/dom/indexedDB/PBackgroundIDBVersionChangeTransaction.ipdl index f0b475f4a4..9b22240c27 100644 --- a/dom/indexedDB/PBackgroundIDBVersionChangeTransaction.ipdl +++ b/dom/indexedDB/PBackgroundIDBVersionChangeTransaction.ipdl @@ -4,6 +4,7 @@ include protocol PBackgroundIDBCursor; include protocol PBackgroundIDBDatabase; +include protocol PBackgroundIDBDatabaseFile; include protocol PBackgroundIDBRequest; include protocol PBlob; diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index b2b4f57d98..4ef09aee9f 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -514,6 +514,7 @@ child: // The following methods correspond to functions on the GoannaContentController // interface in gfx/layers/apz/public/GoannaContentController.h. Refer to documentation // in that file for these functions. + RequestFlingSnap(ViewID aScrollID, CSSPoint aDestination); AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration); HandleDoubleTap(CSSPoint point, ScrollableLayerGuid aGuid); HandleSingleTap(CSSPoint point, ScrollableLayerGuid aGuid); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 1123e5bda5..9b7695add8 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -2034,6 +2034,14 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics) return TabChildBase::UpdateFrameHandler(aFrameMetrics); } +bool +TabChild::RecvRequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) +{ + APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination); + return true; +} + bool TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration) diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 36e0a79747..00818304d0 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -323,6 +323,8 @@ public: const ScreenOrientation& orientation, const nsIntPoint& chromeDisp) MOZ_OVERRIDE; virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE; + virtual bool RecvRequestFlingSnap(const ViewID& aScrollId, + const CSSPoint& aDestination) MOZ_OVERRIDE; virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration) MOZ_OVERRIDE; virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 9ed5016de5..c88e4b7617 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -924,6 +924,15 @@ TabParent::UIResolutionChanged() } } +void +TabParent::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) +{ + if (!mIsDestroyed) { + unused << SendRequestFlingSnap(aScrollId, aDestination); + } +} + void TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration) { diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index d6e24dc89a..0b96dba448 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -247,6 +247,8 @@ public: const nsIntPoint& chromeDisp); void UpdateFrame(const layers::FrameMetrics& aFrameMetrics); void UIResolutionChanged(); + void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination); void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration); void HandleDoubleTap(const CSSPoint& aPoint, int32_t aModifiers, diff --git a/dom/media/MediaTaskQueue.cpp b/dom/media/MediaTaskQueue.cpp index 66cd6902e8..0670849e68 100644 --- a/dom/media/MediaTaskQueue.cpp +++ b/dom/media/MediaTaskQueue.cpp @@ -10,7 +10,7 @@ namespace mozilla { -MediaTaskQueue::MediaTaskQueue(TemporaryRef aPool, +MediaTaskQueue::MediaTaskQueue(already_AddRefed aPool, bool aRequireTailDispatch) : AbstractThread(aRequireTailDispatch) , mPool(aPool) @@ -74,7 +74,7 @@ MediaTaskQueue::DispatchLocked(already_AddRefed aRunnable, class MediaTaskQueueSyncRunnable : public nsRunnable { public: - explicit MediaTaskQueueSyncRunnable(TemporaryRef aRunnable) + explicit MediaTaskQueueSyncRunnable(already_AddRefed aRunnable) : mRunnable(aRunnable) , mMonitor("MediaTaskQueueSyncRunnable") , mDone(false) @@ -104,9 +104,9 @@ private: }; void -MediaTaskQueue::SyncDispatch(TemporaryRef aRunnable) { +MediaTaskQueue::SyncDispatch(already_AddRefed aRunnable) { NS_WARNING("MediaTaskQueue::SyncDispatch is deprecated and potentially dangerous. Don't use!"); - nsRefPtr task(new MediaTaskQueueSyncRunnable(aRunnable)); + nsRefPtr task(new MediaTaskQueueSyncRunnable(Move(aRunnable))); // Tail dispatchers don't interact nicely with sync dispatch. We require that // nothing is already in the tail dispatcher, and then sidestep it for this @@ -185,7 +185,7 @@ FlushableMediaTaskQueue::Flush() } nsresult -FlushableMediaTaskQueue::FlushAndDispatch(TemporaryRef aRunnable) +FlushableMediaTaskQueue::FlushAndDispatch(already_AddRefed aRunnable) { MonitorAutoLock mon(mQueueMonitor); AutoSetFlushing autoFlush(this); diff --git a/dom/media/MediaTaskQueue.h b/dom/media/MediaTaskQueue.h index eb690b94ca..e9fc55f026 100644 --- a/dom/media/MediaTaskQueue.h +++ b/dom/media/MediaTaskQueue.h @@ -31,14 +31,7 @@ typedef MediaPromise ShutdownPromise; // to make this threadsafe for objects that aren't already threadsafe. class MediaTaskQueue : public AbstractThread { public: - explicit MediaTaskQueue(TemporaryRef aPool, bool aRequireTailDispatch = false); - - void Dispatch(TemporaryRef aRunnable, - DispatchFailureHandling aFailureHandling = AssertDispatchSuccess) - { - nsCOMPtr r = dont_AddRef(aRunnable.take()); - return Dispatch(r.forget(), aFailureHandling); - } + explicit MediaTaskQueue(already_AddRefed aPool, bool aSupportsTailDispatch = false); TaskDispatcher& TailDispatcher() override; @@ -54,7 +47,7 @@ public: // DEPRECATED; do not use! If a flush happens at the same time, this function // can hang and block forever! This needs to be removed in the future. - void SyncDispatch(TemporaryRef aRunnable); + void SyncDispatch(already_AddRefed aRunnable); // Puts the queue in a shutdown state and returns immediately. The queue will // remain alive at least until all the events are drained, because the Runners @@ -171,8 +164,8 @@ protected: class FlushableMediaTaskQueue : public MediaTaskQueue { public: - explicit FlushableMediaTaskQueue(TemporaryRef aPool) : MediaTaskQueue(aPool) {} - nsresult FlushAndDispatch(TemporaryRef aRunnable); + explicit FlushableMediaTaskQueue(already_AddRefed aPool) : MediaTaskQueue(Move(aPool)) {} + nsresult FlushAndDispatch(already_AddRefed aRunnable); void Flush(); bool IsDispatchReliable() override { return false; } diff --git a/dom/media/SharedThreadPool.cpp b/dom/media/SharedThreadPool.cpp index 5ea29b56ea..4098d9e711 100644 --- a/dom/media/SharedThreadPool.cpp +++ b/dom/media/SharedThreadPool.cpp @@ -58,7 +58,7 @@ SharedThreadPool::SpinUntilEmpty() } } -TemporaryRef +already_AddRefed SharedThreadPool::Get(const nsCString& aName, uint32_t aThreadLimit) { MOZ_ASSERT(sMonitor && sPools); diff --git a/dom/media/SharedThreadPool.h b/dom/media/SharedThreadPool.h index fcf40689d6..ff457438dc 100644 --- a/dom/media/SharedThreadPool.h +++ b/dom/media/SharedThreadPool.h @@ -32,7 +32,7 @@ public: // Gets (possibly creating) the shared thread pool singleton instance with // thread pool named aName. // *Must* be called on the main thread. - static TemporaryRef Get(const nsCString& aName, + static already_AddRefed Get(const nsCString& aName, uint32_t aThreadLimit = 4); // We implement custom threadsafe AddRef/Release pair, that destroys the diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index b2d9b5fa94..05643c2f49 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -221,7 +221,7 @@ IsValidVideoRegion(const nsIntSize& aFrame, const nsIntRect& aPicture, aDisplay.width * aDisplay.height != 0; } -TemporaryRef GetMediaThreadPool(MediaThreadType aType) +already_AddRefed GetMediaThreadPool(MediaThreadType aType) { const char *name; switch (aType) { diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h index 8bdd093403..6fb711784b 100644 --- a/dom/media/VideoUtils.h +++ b/dom/media/VideoUtils.h @@ -223,7 +223,7 @@ enum class MediaThreadType { }; // Returns the thread pool that is shared amongst all decoder state machines // for decoding streams. -TemporaryRef GetMediaThreadPool(MediaThreadType aType); +already_AddRefed GetMediaThreadPool(MediaThreadType aType); enum H264_PROFILE { H264_PROFILE_UNKNOWN = 0, diff --git a/dom/media/directshow/AudioSinkInputPin.cpp b/dom/media/directshow/AudioSinkInputPin.cpp index 5351414c10..a6e78738a5 100644 --- a/dom/media/directshow/AudioSinkInputPin.cpp +++ b/dom/media/directshow/AudioSinkInputPin.cpp @@ -135,7 +135,7 @@ AudioSinkInputPin::Receive(IMediaSample* aSample ) return S_OK; } -TemporaryRef +already_AddRefed AudioSinkInputPin::GetConnectedPinSeeking() { RefPtr peer = GetConnected(); diff --git a/dom/media/directshow/AudioSinkInputPin.h b/dom/media/directshow/AudioSinkInputPin.h index 041c11ff78..aa565772cd 100644 --- a/dom/media/directshow/AudioSinkInputPin.h +++ b/dom/media/directshow/AudioSinkInputPin.h @@ -54,7 +54,7 @@ public: // Returns the IMediaSeeking interface of the connected output pin. // We forward seeking requests upstream from the sink to the source // filters. - TemporaryRef GetConnectedPinSeeking(); + already_AddRefed GetConnectedPinSeeking(); SampleSink* GetSampleSink(); diff --git a/dom/media/directshow/DirectShowUtils.cpp b/dom/media/directshow/DirectShowUtils.cpp index 27b37d4797..f3a496817d 100644 --- a/dom/media/directshow/DirectShowUtils.cpp +++ b/dom/media/directshow/DirectShowUtils.cpp @@ -287,7 +287,7 @@ MatchUnconnectedPin(IPin* aPin, } // Return the first unconnected input pin or output pin. -TemporaryRef +already_AddRefed GetUnconnectedPin(IBaseFilter* aFilter, PIN_DIRECTION aPinDir) { RefPtr enumPins; diff --git a/dom/media/platforms/wmf/MFTDecoder.cpp b/dom/media/platforms/wmf/MFTDecoder.cpp index d8dd31354d..58449c9a1c 100644 --- a/dom/media/platforms/wmf/MFTDecoder.cpp +++ b/dom/media/platforms/wmf/MFTDecoder.cpp @@ -73,7 +73,7 @@ MFTDecoder::SetMediaTypes(IMFMediaType* aInputType, return S_OK; } -TemporaryRef +already_AddRefed MFTDecoder::GetAttributes() { RefPtr attr; diff --git a/dom/media/platforms/wmf/MFTDecoder.h b/dom/media/platforms/wmf/MFTDecoder.h index b53257431f..65e5d74d54 100644 --- a/dom/media/platforms/wmf/MFTDecoder.h +++ b/dom/media/platforms/wmf/MFTDecoder.h @@ -43,7 +43,7 @@ public: void* aData = nullptr); // Returns the MFT's IMFAttributes object. - TemporaryRef GetAttributes(); + already_AddRefed GetAttributes(); // Retrieves the media type being output. This may not be valid until // the first sample is decoded. diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp index 50573c1285..1c40a4ce28 100644 --- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp @@ -117,7 +117,7 @@ WMFAudioMFTManager::GetMediaSubtypeGUID() }; } -TemporaryRef +already_AddRefed WMFAudioMFTManager::Init() { NS_ENSURE_TRUE(mStreamType != Unknown, nullptr); diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.h b/dom/media/platforms/wmf/WMFAudioMFTManager.h index cbd1a6f62e..82abf4d24b 100644 --- a/dom/media/platforms/wmf/WMFAudioMFTManager.h +++ b/dom/media/platforms/wmf/WMFAudioMFTManager.h @@ -20,7 +20,7 @@ public: WMFAudioMFTManager(const AudioInfo& aConfig); ~WMFAudioMFTManager(); - virtual TemporaryRef Init() override; + virtual already_AddRefed Init() override; virtual HRESULT Input(MediaRawData* aSample) override; diff --git a/dom/media/platforms/wmf/WMFMediaDataDecoder.h b/dom/media/platforms/wmf/WMFMediaDataDecoder.h index 2edeca5bb7..2c885a8c4a 100644 --- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h +++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h @@ -24,7 +24,7 @@ public: // Creates an initializs the MFTDecoder. // Returns nullptr on failure. - virtual TemporaryRef Init() = 0; + virtual already_AddRefed Init() = 0; // Submit a compressed sample for decoding. // This should forward to the MFTDecoder after performing diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp index 92a8829418..132affe79a 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp @@ -177,7 +177,7 @@ WMFVideoMFTManager::InitializeDXVA() return mDXVA2Manager != nullptr; } -TemporaryRef +already_AddRefed WMFVideoMFTManager::Init() { mUseHwAccel = false; // default value; changed if D3D setup succeeds. diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.h b/dom/media/platforms/wmf/WMFVideoMFTManager.h index 88f2093913..b5dcae8c33 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.h +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h @@ -26,7 +26,7 @@ public: bool aDXVAEnabled); ~WMFVideoMFTManager(); - virtual TemporaryRef Init() override; + virtual already_AddRefed Init() override; virtual HRESULT Input(MediaRawData* aSample) override; diff --git a/dom/media/webaudio/PannerNode.cpp b/dom/media/webaudio/PannerNode.cpp index 2c02c80e47..0b1c5f4d19 100644 --- a/dom/media/webaudio/PannerNode.cpp +++ b/dom/media/webaudio/PannerNode.cpp @@ -63,9 +63,9 @@ public: , mLeftOverData(INT_MIN) { // HRTFDatabaseLoader needs to be fetched on the main thread. - TemporaryRef loader = + already_AddRefed loader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(aNode->Context()->SampleRate()); - mHRTFPanner = new HRTFPanner(aNode->Context()->SampleRate(), loader); + mHRTFPanner = new HRTFPanner(aNode->Context()->SampleRate(), Move(loader)); } virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override diff --git a/dom/media/webaudio/blink/HRTFDatabaseLoader.cpp b/dom/media/webaudio/blink/HRTFDatabaseLoader.cpp index 0c02728294..1ef34036d9 100644 --- a/dom/media/webaudio/blink/HRTFDatabaseLoader.cpp +++ b/dom/media/webaudio/blink/HRTFDatabaseLoader.cpp @@ -42,7 +42,7 @@ size_t HRTFDatabaseLoader::sizeOfLoaders(mozilla::MallocSizeOf aMallocSizeOf) return s_loaderMap ? s_loaderMap->SizeOfIncludingThis(aMallocSizeOf) : 0; } -TemporaryRef HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate) +already_AddRefed HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate) { MOZ_ASSERT(NS_IsMainThread()); diff --git a/dom/media/webaudio/blink/HRTFDatabaseLoader.h b/dom/media/webaudio/blink/HRTFDatabaseLoader.h index 239e7fba5c..637cbb2196 100644 --- a/dom/media/webaudio/blink/HRTFDatabaseLoader.h +++ b/dom/media/webaudio/blink/HRTFDatabaseLoader.h @@ -48,7 +48,7 @@ public: // and starts loading asynchronously (when created the first time). // Returns the HRTFDatabaseLoader. // Must be called from the main thread. - static mozilla::TemporaryRef createAndLoadAsynchronouslyIfNecessary(float sampleRate); + static already_AddRefed createAndLoadAsynchronouslyIfNecessary(float sampleRate); // AddRef and Release may be called from any thread. void AddRef() diff --git a/dom/media/webaudio/blink/HRTFPanner.cpp b/dom/media/webaudio/blink/HRTFPanner.cpp index 5a63408d48..7107e56cfd 100644 --- a/dom/media/webaudio/blink/HRTFPanner.cpp +++ b/dom/media/webaudio/blink/HRTFPanner.cpp @@ -41,7 +41,7 @@ const double MaxDelayTimeSeconds = 0.002; const int UninitializedAzimuth = -1; const unsigned RenderingQuantum = WEBAUDIO_BLOCK_SIZE; -HRTFPanner::HRTFPanner(float sampleRate, mozilla::TemporaryRef databaseLoader) +HRTFPanner::HRTFPanner(float sampleRate, already_AddRefed databaseLoader) : m_databaseLoader(databaseLoader) , m_sampleRate(sampleRate) , m_crossfadeSelection(CrossfadeSelection1) diff --git a/dom/media/webaudio/blink/HRTFPanner.h b/dom/media/webaudio/blink/HRTFPanner.h index d15b317ade..61ca369cd9 100644 --- a/dom/media/webaudio/blink/HRTFPanner.h +++ b/dom/media/webaudio/blink/HRTFPanner.h @@ -41,7 +41,7 @@ using mozilla::AudioChunk; class HRTFPanner { public: - HRTFPanner(float sampleRate, mozilla::TemporaryRef databaseLoader); + HRTFPanner(float sampleRate, already_AddRefed databaseLoader); ~HRTFPanner(); // chunk durations must be 128 diff --git a/dom/moz.build b/dom/moz.build index d3c27a32a5..06aa5ec1be 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -47,6 +47,7 @@ DIRS += [ 'bindings', 'battery', 'browser-element', + 'cache', 'canvas', 'cellbroadcast', 'contacts', diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index a40508f6db..db3635e9ff 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -958,7 +958,7 @@ void nsNPAPIPluginInstance::ReleaseContentTexture(nsNPAPIPluginInstance::Texture mContentTexture->Release(aTextureInfo); } -TemporaryRef nsNPAPIPluginInstance::CreateSurfaceTexture() +already_AddRefed nsNPAPIPluginInstance::CreateSurfaceTexture() { if (!EnsureGLContext()) return nullptr; diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 8f150be2bb..04bad18f5e 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -385,7 +385,7 @@ private: #ifdef MOZ_WIDGET_ANDROID void EnsureSharedTexture(); - mozilla::TemporaryRef CreateSurfaceTexture(); + already_AddRefed CreateSurfaceTexture(); std::map mVideos; bool mOnScreen; diff --git a/dom/quota/Client.h b/dom/quota/Client.h index 9a36cac305..1da6110b9c 100644 --- a/dom/quota/Client.h +++ b/dom/quota/Client.h @@ -16,6 +16,7 @@ class nsIRunnable; #define IDB_DIRECTORY_NAME "idb" #define ASMJSCACHE_DIRECTORY_NAME "asmjs" +#define DOMCACHE_DIRECTORY_NAME "cache" BEGIN_QUOTA_NAMESPACE @@ -39,6 +40,7 @@ public: //LS, //APPCACHE, ASMJS, + DOMCACHE, TYPE_MAX }; @@ -57,6 +59,10 @@ public: aText.AssignLiteral(ASMJSCACHE_DIRECTORY_NAME); break; + case DOMCACHE: + aText.AssignLiteral(DOMCACHE_DIRECTORY_NAME); + break; + case TYPE_MAX: default: NS_NOTREACHED("Bad id value!"); @@ -75,6 +81,9 @@ public: else if (aText.EqualsLiteral(ASMJSCACHE_DIRECTORY_NAME)) { aType = ASMJS; } + else if (aText.EqualsLiteral(DOMCACHE_DIRECTORY_NAME)) { + aType = DOMCACHE; + } else { return NS_ERROR_FAILURE; } diff --git a/dom/quota/QuotaManager.cpp b/dom/quota/QuotaManager.cpp index 6a9c8254a7..b510918e38 100644 --- a/dom/quota/QuotaManager.cpp +++ b/dom/quota/QuotaManager.cpp @@ -30,6 +30,7 @@ #include "mozilla/CondVar.h" #include "mozilla/dom/asmjscache/AsmJSCache.h" #include "mozilla/dom/FileService.h" +#include "mozilla/dom/cache/QuotaClient.h" #include "mozilla/dom/indexedDB/ActorsParent.h" #include "mozilla/Mutex.h" #include "mozilla/LazyIdleThread.h" @@ -1419,8 +1420,8 @@ QuotaManager::Init() NS_WARNING("Unable to respond to testing pref changes!"); } - static_assert(Client::IDB == 0 && Client::ASMJS == 1 && Client::TYPE_MAX == 2, - "Fix the registration!"); + static_assert(Client::IDB == 0 && Client::ASMJS == 1 && Client::DOMCACHE == 2 && + Client::TYPE_MAX == 3, "Fix the registration!"); NS_ASSERTION(mClients.Capacity() == Client::TYPE_MAX, "Should be using an auto array with correct capacity!"); @@ -1430,6 +1431,7 @@ QuotaManager::Init() // Register clients. mClients.AppendElement(idbClient); mClients.AppendElement(asmjscache::CreateClient()); + mClients.AppendElement(cache::CreateQuotaClient()); return NS_OK; } diff --git a/dom/svg/SVGCircleElement.cpp b/dom/svg/SVGCircleElement.cpp index 1cd9680fb8..1ab93c540d 100644 --- a/dom/svg/SVGCircleElement.cpp +++ b/dom/svg/SVGCircleElement.cpp @@ -108,7 +108,7 @@ SVGCircleElement::GetGeometryBounds( return false; } -TemporaryRef +already_AddRefed SVGCircleElement::BuildPath(PathBuilder* aBuilder) { float x, y, r; diff --git a/dom/svg/SVGCircleElement.h b/dom/svg/SVGCircleElement.h index 96c417ce09..adedf3a292 100644 --- a/dom/svg/SVGCircleElement.h +++ b/dom/svg/SVGCircleElement.h @@ -32,7 +32,7 @@ public: // nsSVGPathGeometryElement methods: virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform) override; - virtual TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/svg/SVGContentUtils.cpp b/dom/svg/SVGContentUtils.cpp index c5540d44ac..6d88c51d1b 100644 --- a/dom/svg/SVGContentUtils.cpp +++ b/dom/svg/SVGContentUtils.cpp @@ -790,7 +790,7 @@ SVGContentUtils::CoordToFloat(nsSVGElement *aContent, } } -TemporaryRef +already_AddRefed SVGContentUtils::GetPath(const nsAString& aPathString) { SVGPathData pathData; diff --git a/dom/svg/SVGContentUtils.h b/dom/svg/SVGContentUtils.h index be709df33d..cfd2d2aea6 100644 --- a/dom/svg/SVGContentUtils.h +++ b/dom/svg/SVGContentUtils.h @@ -321,7 +321,7 @@ public: * Returns a path * string formatted as an SVG path */ - static mozilla::TemporaryRef + static already_AddRefed GetPath(const nsAString& aPathString); }; diff --git a/dom/svg/SVGEllipseElement.cpp b/dom/svg/SVGEllipseElement.cpp index 713018332d..adf132b5e6 100644 --- a/dom/svg/SVGEllipseElement.cpp +++ b/dom/svg/SVGEllipseElement.cpp @@ -120,7 +120,7 @@ SVGEllipseElement::GetGeometryBounds( return false; } -TemporaryRef +already_AddRefed SVGEllipseElement::BuildPath(PathBuilder* aBuilder) { float x, y, rx, ry; diff --git a/dom/svg/SVGEllipseElement.h b/dom/svg/SVGEllipseElement.h index e69e3db973..538c3d8c31 100644 --- a/dom/svg/SVGEllipseElement.h +++ b/dom/svg/SVGEllipseElement.h @@ -32,7 +32,7 @@ public: // nsSVGPathGeometryElement methods: virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform) override; - virtual TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/svg/SVGImageElement.cpp b/dom/svg/SVGImageElement.cpp index 32a0f03dc8..51463db4aa 100644 --- a/dom/svg/SVGImageElement.cpp +++ b/dom/svg/SVGImageElement.cpp @@ -241,7 +241,7 @@ SVGImageElement::GetGeometryBounds( return true; } -TemporaryRef +already_AddRefed SVGImageElement::BuildPath(PathBuilder* aBuilder) { // We get called in order to get bounds for this element, and for diff --git a/dom/svg/SVGImageElement.h b/dom/svg/SVGImageElement.h index 5360754b70..ae25c446c9 100644 --- a/dom/svg/SVGImageElement.h +++ b/dom/svg/SVGImageElement.h @@ -55,7 +55,7 @@ public: // nsSVGPathGeometryElement methods: virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform) override; - virtual TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; // nsSVGSVGElement methods: virtual bool HasValidDimensions() const override; diff --git a/dom/svg/SVGLineElement.cpp b/dom/svg/SVGLineElement.cpp index 6b64bd84ae..c9c54c06e7 100644 --- a/dom/svg/SVGLineElement.cpp +++ b/dom/svg/SVGLineElement.cpp @@ -114,7 +114,7 @@ SVGLineElement::GetAsSimplePath(SimplePath* aSimplePath) aSimplePath->SetLine(x1, y1, x2, y2); } -TemporaryRef +already_AddRefed SVGLineElement::BuildPath(PathBuilder* aBuilder) { float x1, y1, x2, y2; diff --git a/dom/svg/SVGLineElement.h b/dom/svg/SVGLineElement.h index 246aa049d0..0dc4709cc8 100644 --- a/dom/svg/SVGLineElement.h +++ b/dom/svg/SVGLineElement.h @@ -33,7 +33,7 @@ public: virtual bool IsMarkable() override { return true; } virtual void GetMarkPoints(nsTArray *aMarks) override; virtual void GetAsSimplePath(SimplePath* aSimplePath) override; - virtual TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform) override; diff --git a/dom/svg/SVGMotionSMILPathUtils.cpp b/dom/svg/SVGMotionSMILPathUtils.cpp index 40016375fc..76d4799b4a 100644 --- a/dom/svg/SVGMotionSMILPathUtils.cpp +++ b/dom/svg/SVGMotionSMILPathUtils.cpp @@ -79,7 +79,7 @@ SVGMotionSMILPathUtils::PathGenerator:: return true; } -TemporaryRef +already_AddRefed SVGMotionSMILPathUtils::PathGenerator::GetResultingPath() { return mPathBuilder->Finish(); diff --git a/dom/svg/SVGMotionSMILPathUtils.h b/dom/svg/SVGMotionSMILPathUtils.h index 6e13603f55..14213596f2 100644 --- a/dom/svg/SVGMotionSMILPathUtils.h +++ b/dom/svg/SVGMotionSMILPathUtils.h @@ -61,7 +61,7 @@ public: // Accessor to let clients check if we've received any commands yet. inline bool HaveReceivedCommands() { return mHaveReceivedCommands; } // Accessor to get the finalized path - mozilla::TemporaryRef GetResultingPath(); + already_AddRefed GetResultingPath(); protected: // Helper methods diff --git a/dom/svg/SVGPathData.cpp b/dom/svg/SVGPathData.cpp index 0e11782754..1532ea04ad 100644 --- a/dom/svg/SVGPathData.cpp +++ b/dom/svg/SVGPathData.cpp @@ -272,7 +272,7 @@ ApproximateZeroLengthSubpathSquareCaps(PathBuilder* aPB, } \ } while(0) -TemporaryRef +already_AddRefed SVGPathData::BuildPath(PathBuilder* builder, uint8_t aStrokeLineCap, Float aStrokeWidth) const @@ -506,7 +506,7 @@ SVGPathData::BuildPath(PathBuilder* builder, return builder->Finish(); } -TemporaryRef +already_AddRefed SVGPathData::BuildPathForMeasuring() const { // Since the path that we return will not be used for painting it doesn't diff --git a/dom/svg/SVGPathData.h b/dom/svg/SVGPathData.h index d794e8b099..b382fd8470 100644 --- a/dom/svg/SVGPathData.h +++ b/dom/svg/SVGPathData.h @@ -163,9 +163,9 @@ public: * ApproximateZeroLengthSubpathSquareCaps can insert if we have square-caps. * See the comment for that function for more info on that. */ - TemporaryRef BuildPathForMeasuring() const; + already_AddRefed BuildPathForMeasuring() const; - TemporaryRef BuildPath(PathBuilder* aBuilder, + already_AddRefed BuildPath(PathBuilder* aBuilder, uint8_t aCapStyle, Float aStrokeWidth) const; diff --git a/dom/svg/SVGPathElement.cpp b/dom/svg/SVGPathElement.cpp index cfea5966e1..fb73ecddfb 100644 --- a/dom/svg/SVGPathElement.cpp +++ b/dom/svg/SVGPathElement.cpp @@ -304,7 +304,7 @@ SVGPathElement::IsAttributeMapped(const nsIAtom* name) const SVGPathElementBase::IsAttributeMapped(name); } -TemporaryRef +already_AddRefed SVGPathElement::GetOrBuildPathForMeasuring() { return mD.GetAnimValue().BuildPathForMeasuring(); @@ -363,7 +363,7 @@ SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor) return 1.0; } -TemporaryRef +already_AddRefed SVGPathElement::BuildPath(PathBuilder* aBuilder) { // The Moz2D PathBuilder that our SVGPathData will be using only cares about diff --git a/dom/svg/SVGPathElement.h b/dom/svg/SVGPathElement.h index e86106b44c..4216138913 100644 --- a/dom/svg/SVGPathElement.h +++ b/dom/svg/SVGPathElement.h @@ -50,14 +50,14 @@ public: virtual bool AttributeDefinesGeometry(const nsIAtom *aName) override; virtual bool IsMarkable() override; virtual void GetMarkPoints(nsTArray *aMarks) override; - virtual TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; /** * This returns a path without the extra little line segments that * ApproximateZeroLengthSubpathSquareCaps can insert if we have square-caps. * See the comment for that function for more info on that. */ - virtual TemporaryRef GetOrBuildPathForMeasuring() override; + virtual already_AddRefed GetOrBuildPathForMeasuring() override; // nsIContent interface virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/svg/SVGPolygonElement.cpp b/dom/svg/SVGPolygonElement.cpp index 4969bef295..f3fcf7960c 100644 --- a/dom/svg/SVGPolygonElement.cpp +++ b/dom/svg/SVGPolygonElement.cpp @@ -61,7 +61,7 @@ SVGPolygonElement::GetMarkPoints(nsTArray *aMarks) nsSVGMark::eEnd)); } -TemporaryRef +already_AddRefed SVGPolygonElement::BuildPath(PathBuilder* aBuilder) { const SVGPointList &points = mPoints.GetAnimValue(); diff --git a/dom/svg/SVGPolygonElement.h b/dom/svg/SVGPolygonElement.h index 8f8236f233..88fd18a215 100644 --- a/dom/svg/SVGPolygonElement.h +++ b/dom/svg/SVGPolygonElement.h @@ -28,7 +28,7 @@ protected: public: // nsSVGPathGeometryElement methods: virtual void GetMarkPoints(nsTArray *aMarks) override; - virtual mozilla::TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; }; diff --git a/dom/svg/SVGPolylineElement.cpp b/dom/svg/SVGPolylineElement.cpp index 624cd2c654..5b96a6d49a 100644 --- a/dom/svg/SVGPolylineElement.cpp +++ b/dom/svg/SVGPolylineElement.cpp @@ -37,7 +37,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPolylineElement) //---------------------------------------------------------------------- // nsSVGPathGeometryElement methods -TemporaryRef +already_AddRefed SVGPolylineElement::BuildPath(PathBuilder* aBuilder) { const SVGPointList &points = mPoints.GetAnimValue(); diff --git a/dom/svg/SVGPolylineElement.h b/dom/svg/SVGPolylineElement.h index 686336c554..f9434229c4 100644 --- a/dom/svg/SVGPolylineElement.h +++ b/dom/svg/SVGPolylineElement.h @@ -25,7 +25,7 @@ protected: already_AddRefed&& aNodeInfo)); // nsSVGPathGeometryElement methods: - virtual mozilla::TemporaryRef BuildPath(PathBuilder* aBuilder) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) override; public: // nsIContent interface diff --git a/dom/svg/SVGRectElement.cpp b/dom/svg/SVGRectElement.cpp index 14bc28fb60..3751076371 100644 --- a/dom/svg/SVGRectElement.cpp +++ b/dom/svg/SVGRectElement.cpp @@ -167,7 +167,7 @@ SVGRectElement::GetAsSimplePath(SimplePath* aSimplePath) aSimplePath->SetRect(x, y, width, height); } -TemporaryRef +already_AddRefed SVGRectElement::BuildPath(PathBuilder* aBuilder) { float x, y, width, height, rx, ry; diff --git a/dom/svg/SVGRectElement.h b/dom/svg/SVGRectElement.h index cc60f803cf..d729a50bd9 100644 --- a/dom/svg/SVGRectElement.h +++ b/dom/svg/SVGRectElement.h @@ -33,7 +33,7 @@ public: virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform) override; virtual void GetAsSimplePath(SimplePath* aSimplePath) override; - virtual TemporaryRef BuildPath(PathBuilder* aBuilder = nullptr) override; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder = nullptr) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/svg/nsSVGPathGeometryElement.cpp b/dom/svg/nsSVGPathGeometryElement.cpp index 704824a459..fb1a144f30 100644 --- a/dom/svg/nsSVGPathGeometryElement.cpp +++ b/dom/svg/nsSVGPathGeometryElement.cpp @@ -74,7 +74,7 @@ nsSVGPathGeometryElement::GetMarkPoints(nsTArray *aMarks) { } -TemporaryRef +already_AddRefed nsSVGPathGeometryElement::GetOrBuildPath(const DrawTarget& aDrawTarget, FillRule aFillRule) { @@ -100,7 +100,7 @@ nsSVGPathGeometryElement::GetOrBuildPath(const DrawTarget& aDrawTarget, return path.forget(); } -TemporaryRef +already_AddRefed nsSVGPathGeometryElement::GetOrBuildPathForMeasuring() { return nullptr; diff --git a/dom/svg/nsSVGPathGeometryElement.h b/dom/svg/nsSVGPathGeometryElement.h index 05d9421df5..e38b648e17 100644 --- a/dom/svg/nsSVGPathGeometryElement.h +++ b/dom/svg/nsSVGPathGeometryElement.h @@ -147,7 +147,7 @@ public: * this element. May return nullptr if there is no [valid] path. The path * that is created may be cached and returned on subsequent calls. */ - virtual mozilla::TemporaryRef GetOrBuildPath(const DrawTarget& aDrawTarget, + virtual already_AddRefed GetOrBuildPath(const DrawTarget& aDrawTarget, FillRule fillRule); /** @@ -155,7 +155,7 @@ public: * previously cached Path, nor caches the Path that in does return). * this element. May return nullptr if there is no [valid] path. */ - virtual mozilla::TemporaryRef BuildPath(PathBuilder* aBuilder) = 0; + virtual already_AddRefed BuildPath(PathBuilder* aBuilder) = 0; /** * Returns a Path that can be used to measure the length of this elements @@ -172,7 +172,7 @@ public: * run into problems with the inserted lines negatively affecting measuring * for content. */ - virtual mozilla::TemporaryRef GetOrBuildPathForMeasuring(); + virtual already_AddRefed GetOrBuildPathForMeasuring(); /** * Returns the current computed value of the CSS property 'fill-rule' for diff --git a/dom/system/gonk/MozMtpDatabase.cpp b/dom/system/gonk/MozMtpDatabase.cpp index 9855ecf662..d1f3e58951 100644 --- a/dom/system/gonk/MozMtpDatabase.cpp +++ b/dom/system/gonk/MozMtpDatabase.cpp @@ -154,7 +154,7 @@ MozMtpDatabase::FindEntryByPath(const nsACString& aPath) return 0; } -TemporaryRef +already_AddRefed MozMtpDatabase::GetEntry(MtpObjectHandle aHandle) { MutexAutoLock lock(mMutex); diff --git a/dom/system/gonk/MozMtpDatabase.h b/dom/system/gonk/MozMtpDatabase.h index b8463e9571..c54268d546 100644 --- a/dom/system/gonk/MozMtpDatabase.h +++ b/dom/system/gonk/MozMtpDatabase.h @@ -235,7 +235,7 @@ private: void AddEntryAndNotify(DbEntry* aEntr, RefCountedMtpServer* aMtpServer); void DumpEntries(const char* aLabel); MtpObjectHandle FindEntryByPath(const nsACString& aPath); - mozilla::TemporaryRef GetEntry(MtpObjectHandle aHandle); + already_AddRefed GetEntry(MtpObjectHandle aHandle); void RemoveEntry(MtpObjectHandle aHandle); void RemoveEntryAndNotify(MtpObjectHandle aHandle, RefCountedMtpServer* aMtpServer); void UpdateEntry(MtpObjectHandle aHandle, DeviceStorageFile* aFile); diff --git a/dom/system/gonk/VolumeManager.cpp b/dom/system/gonk/VolumeManager.cpp index a822089e32..4b99c3acd1 100644 --- a/dom/system/gonk/VolumeManager.cpp +++ b/dom/system/gonk/VolumeManager.cpp @@ -71,7 +71,7 @@ VolumeManager::NumVolumes() } //static -TemporaryRef +already_AddRefed VolumeManager::GetVolume(size_t aIndex) { MOZ_ASSERT(aIndex < NumVolumes()); @@ -125,7 +125,7 @@ void VolumeManager::UnregisterStateObserver(StateObserver* aObserver) } //static -TemporaryRef +already_AddRefed VolumeManager::FindVolumeByName(const nsCSubstring& aName) { if (!sVolumeManager) { @@ -143,7 +143,7 @@ VolumeManager::FindVolumeByName(const nsCSubstring& aName) } //static -TemporaryRef +already_AddRefed VolumeManager::FindAddVolumeByName(const nsCSubstring& aName) { RefPtr vol = FindVolumeByName(aName); diff --git a/dom/system/gonk/VolumeManager.h b/dom/system/gonk/VolumeManager.h index 9fbf53003e..882ae77c4f 100644 --- a/dom/system/gonk/VolumeManager.h +++ b/dom/system/gonk/VolumeManager.h @@ -125,9 +125,9 @@ public: static void Dump(const char* aLabel); static VolumeArray::size_type NumVolumes(); - static TemporaryRef GetVolume(VolumeArray::index_type aIndex); - static TemporaryRef FindVolumeByName(const nsCSubstring& aName); - static TemporaryRef FindAddVolumeByName(const nsCSubstring& aName); + static already_AddRefed GetVolume(VolumeArray::index_type aIndex); + static already_AddRefed FindVolumeByName(const nsCSubstring& aName); + static already_AddRefed FindAddVolumeByName(const nsCSubstring& aName); static void InitConfig(); static void PostCommand(VolumeCommand* aCommand); diff --git a/dom/webidl/Cache.webidl b/dom/webidl/Cache.webidl new file mode 100644 index 0000000000..099701d2bd --- /dev/null +++ b/dom/webidl/Cache.webidl @@ -0,0 +1,45 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html + * + */ + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache + +[Exposed=(Window,Worker), + Func="mozilla::dom::cache::Cache::PrefEnabled"] +interface Cache { +[Throws] +Promise match(RequestInfo request, optional CacheQueryOptions options); +[Throws] +Promise> matchAll(optional RequestInfo request, optional CacheQueryOptions options); +[Throws] +Promise add(RequestInfo request); +[Throws] +Promise addAll(sequence requests); +[Throws] +Promise put(RequestInfo request, Response response); +[Throws] +Promise delete(RequestInfo request, optional CacheQueryOptions options); +[Throws] +Promise> keys(optional RequestInfo request, optional CacheQueryOptions options); +}; + +dictionary CacheQueryOptions { +boolean ignoreSearch = false; +boolean ignoreMethod = false; +boolean ignoreVary = false; +boolean prefixMatch = false; +DOMString cacheName; +}; + +dictionary CacheBatchOperation { +DOMString type; +Request request; +Response response; +CacheQueryOptions options; +}; diff --git a/dom/webidl/CacheStorage.webidl b/dom/webidl/CacheStorage.webidl new file mode 100644 index 0000000000..ef845a64a1 --- /dev/null +++ b/dom/webidl/CacheStorage.webidl @@ -0,0 +1,26 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html + * + */ + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-storage + +[Exposed=(Window,Worker), + Func="mozilla::dom::cache::CacheStorage::PrefEnabled"] +interface CacheStorage { +[Throws] +Promise match(RequestInfo request, optional CacheQueryOptions options); +[Throws] +Promise has(DOMString cacheName); +[Throws] +Promise open(DOMString cacheName); +[Throws] +Promise delete(DOMString cacheName); +[Throws] +Promise> keys(); +}; diff --git a/dom/webidl/Element.webidl b/dom/webidl/Element.webidl index 3eb82b99bb..850fb6d0dc 100644 --- a/dom/webidl/Element.webidl +++ b/dom/webidl/Element.webidl @@ -191,6 +191,11 @@ partial interface Element { void scrollTo(optional ScrollToOptions options); void scrollBy(unrestricted double x, unrestricted double y); void scrollBy(optional ScrollToOptions options); + // mozScrollSnap is used by chrome to perform scroll snapping after the + // user performs actions that may affect scroll position + // mozScrollSnap is deprecated, to be replaced by a web accessible API, such + // as an extension to the ScrollOptions dictionary. See bug 1137937. + [ChromeOnly] void mozScrollSnap(); readonly attribute long clientTop; readonly attribute long clientLeft; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 54c89c6628..bd94c8b455 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -191,6 +191,11 @@ partial interface Window { void scrollBy(unrestricted double x, unrestricted double y); void scrollBy(optional ScrollToOptions options); [Replaceable, Throws] readonly attribute double scrollX; + // mozScrollSnap is used by chrome to perform scroll snapping after the + // user performs actions that may affect scroll position + // mozScrollSnap is deprecated, to be replaced by a web accessible API, such + // as an extension to the ScrollOptions dictionary. See bug 1137937. + [ChromeOnly] void mozScrollSnap(); [Throws] readonly attribute double pageXOffset; [Replaceable, Throws] readonly attribute double scrollY; [Throws] readonly attribute double pageYOffset; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 3b3c2da7d6..6ebb4650a6 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -57,6 +57,8 @@ WEBIDL_FILES = [ 'BroadcastChannel.webidl', 'BrowserElement.webidl', 'BrowserElementDictionaries.webidl', + 'Cache.webidl', + 'CacheStorage.webidl', 'CallsList.webidl', 'CameraCapabilities.webidl', 'CameraControl.webidl', diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index b1e0e3e7b7..23bbda370e 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -339,7 +339,7 @@ public: * This function will get a DataSourceSurface for this surface, a * DataSourceSurface's data can be accessed directly. */ - virtual TemporaryRef GetDataSurface() = 0; + virtual already_AddRefed GetDataSurface() = 0; /** Tries to get this SourceSurface's native surface. This will fail if aType * is not the type of this SourceSurface's native surface. @@ -430,7 +430,7 @@ public: * Returns a DataSourceSurface with the same data as this one, but * guaranteed to have surface->GetType() == SurfaceType::DATA. */ - virtual TemporaryRef GetDataSurface() override; + virtual already_AddRefed GetDataSurface() override; protected: bool mIsMapped; @@ -487,8 +487,8 @@ public: /** This returns a PathBuilder object that contains a copy of the contents of * this path and is still writable. */ - virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0; - virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, + virtual already_AddRefed CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0; + virtual already_AddRefed TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule = FillRule::FILL_WINDING) const = 0; /** This function checks if a point lies within a path. It allows passing a @@ -552,7 +552,7 @@ public: /** Finish writing to the path and return a Path object that can be used for * drawing. Future use of the builder results in a crash! */ - virtual TemporaryRef Finish() = 0; + virtual already_AddRefed Finish() = 0; virtual BackendType GetBackendType() const = 0; }; @@ -592,7 +592,7 @@ public: * can be used with any DrawTarget that has the same backend as the one * passed in. */ - virtual TemporaryRef GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) = 0; + virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) = 0; /** This copies the path describing the glyphs into a PathBuilder. We use this * API rather than a generic API to append paths because it allows easier @@ -656,7 +656,7 @@ public: * Multiple calls to Snapshot() without any drawing operations in between will * normally return the same SourceSurface object. */ - virtual TemporaryRef Snapshot() = 0; + virtual already_AddRefed Snapshot() = 0; virtual IntSize GetSize() = 0; /** @@ -892,7 +892,7 @@ public: * * The SourceSurface does not take ownership of aData, and may be freed at any time. */ - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const = 0; @@ -902,20 +902,20 @@ public: * arbitrary SourceSurface type supported by this backend. This may return * aSourceSurface or some other existing surface. */ - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const = 0; + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const = 0; /** * Create a SourceSurface for a type of NativeSurface. This may fail if the * draw target does not know how to deal with the type of NativeSurface passed * in. */ - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const = 0; /** * Create a DrawTarget whose snapshot is optimized for use with this DrawTarget. */ - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0; /** @@ -924,7 +924,7 @@ public: * * @param aSize Size of the area this DT will capture. */ - virtual TemporaryRef CreateCaptureDT(const IntSize& aSize); + virtual already_AddRefed CreateCaptureDT(const IntSize& aSize); /** * Create a draw target optimized for drawing a shadow. @@ -934,7 +934,7 @@ public: * surface, the caller is still responsible for including the shadow area in * its size. */ - virtual TemporaryRef + virtual already_AddRefed CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, float aSigma) const { @@ -948,7 +948,7 @@ public: * ID2D1SimplifiedGeometrySink requires the fill mode * to be set before calling BeginFigure(). */ - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0; + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0; /** * Create a GradientStops object that holds information about a set of @@ -960,7 +960,7 @@ public: * @param aExtendNone This describes how to extend the stop color outside of the * gradient area. */ - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const = 0; @@ -971,7 +971,7 @@ public: * * @param aType Type of filter node to be created. */ - virtual TemporaryRef CreateFilter(FilterType aType) = 0; + virtual already_AddRefed CreateFilter(FilterType aType) = 0; Matrix GetTransform() const { return mTransform; } @@ -1117,18 +1117,18 @@ public: static bool AllowedSurfaceSize(const IntSize &aSize); - static TemporaryRef CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr); + static already_AddRefed CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr); - static TemporaryRef + static already_AddRefed CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat); - static TemporaryRef + static already_AddRefed CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT); - static TemporaryRef + static already_AddRefed CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); - static TemporaryRef + static already_AddRefed CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize); /** @@ -1140,7 +1140,7 @@ public: * @param aGlyphSize Size of the glyphs in this ScaledFont * @param aType Type of ScaledFont that should be created. */ - static TemporaryRef + static already_AddRefed CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, uint32_t aFaceIndex, Float aGlyphSize, FontType aType); /** @@ -1148,7 +1148,7 @@ public: * must be used when using the Cairo backend. The NativeFont and * cairo_scaled_font_t* parameters must correspond to the same font. */ - static TemporaryRef + static already_AddRefed CreateScaledFontWithCairo(const NativeFont &aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont); /** @@ -1157,7 +1157,7 @@ public: * destroyed. The caller is responsible for handing the case where nullptr * is returned. The surface is not zeroed unless requested. */ - static TemporaryRef + static already_AddRefed CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat, bool aZero = false); /** @@ -1167,7 +1167,7 @@ public: * the surface is destroyed. The caller is responsible for handling the case * where nullptr is returned. The surface is not zeroed unless requested. */ - static TemporaryRef + static already_AddRefed CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride, bool aZero = false); /** @@ -1176,11 +1176,11 @@ public: * responsible for deallocating the memory only after destruction of the * surface. */ - static TemporaryRef + static already_AddRefed CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride, const IntSize &aSize, SurfaceFormat aFormat); - static TemporaryRef + static already_AddRefed CreateEventRecorderForFile(const char *aFilename); static void SetGlobalEventRecorder(DrawEventRecorder *aRecorder); @@ -1197,7 +1197,7 @@ private: public: #ifdef USE_SKIA_GPU - static TemporaryRef + static already_AddRefed CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, const IntSize &aSize, SurfaceFormat aFormat); @@ -1206,10 +1206,10 @@ public: static void PurgeAllCaches(); #if defined(USE_SKIA) && defined(MOZ_ENABLE_FREETYPE) - static TemporaryRef + static already_AddRefed CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting); #endif - static TemporaryRef + static already_AddRefed CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB); /* @@ -1218,33 +1218,33 @@ public: * individual offset. The tiles in the set must each have the same backend * and format. */ - static TemporaryRef CreateTiledDrawTarget(const TileSet& aTileSet); + static already_AddRefed CreateTiledDrawTarget(const TileSet& aTileSet); static bool DoesBackendSupportDataDrawtarget(BackendType aType); #ifdef XP_MACOSX - static TemporaryRef CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize); - static TemporaryRef + static already_AddRefed CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize); + static already_AddRefed CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor); #endif #ifdef WIN32 - static TemporaryRef CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); - static TemporaryRef + static already_AddRefed CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); + static already_AddRefed CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA, ID3D10Texture2D *aTextureB, SurfaceFormat aFormat); static void SetDirect3D10Device(ID3D10Device1 *aDevice); static ID3D10Device1 *GetDirect3D10Device(); - static TemporaryRef CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat); + static already_AddRefed CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat); static void SetDirect3D11Device(ID3D11Device *aDevice); static ID3D11Device *GetDirect3D11Device(); static ID2D1Device *GetD2D1Device(); static bool SupportsD2D1(); - static TemporaryRef + static already_AddRefed CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams); static uint64_t GetD2DVRAMUsageDrawTarget(); diff --git a/gfx/2d/DataSourceSurface.cpp b/gfx/2d/DataSourceSurface.cpp index b9a63d45ba..c3a837f996 100644 --- a/gfx/2d/DataSourceSurface.cpp +++ b/gfx/2d/DataSourceSurface.cpp @@ -9,7 +9,7 @@ namespace mozilla { namespace gfx { -TemporaryRef +already_AddRefed DataSourceSurface::GetDataSurface() { RefPtr surface = diff --git a/gfx/2d/DataSurfaceHelpers.cpp b/gfx/2d/DataSurfaceHelpers.cpp index d0f08fa295..cc4a8291d8 100644 --- a/gfx/2d/DataSurfaceHelpers.cpp +++ b/gfx/2d/DataSurfaceHelpers.cpp @@ -270,7 +270,7 @@ CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest, } } -TemporaryRef +already_AddRefed CreateDataSourceSurfaceByCloning(DataSourceSurface* aSource) { RefPtr copy = diff --git a/gfx/2d/DataSurfaceHelpers.h b/gfx/2d/DataSurfaceHelpers.h index e1afecee1d..9cb9f4054b 100644 --- a/gfx/2d/DataSurfaceHelpers.h +++ b/gfx/2d/DataSurfaceHelpers.h @@ -83,7 +83,7 @@ CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest, * * @return a dss allocated by Factory that contains a copy a aSource. */ -TemporaryRef +already_AddRefed CreateDataSourceSurfaceByCloning(DataSourceSurface* aSource); /** diff --git a/gfx/2d/DrawTarget.cpp b/gfx/2d/DrawTarget.cpp index 21b8512562..f2a46681be 100644 --- a/gfx/2d/DrawTarget.cpp +++ b/gfx/2d/DrawTarget.cpp @@ -11,7 +11,7 @@ namespace mozilla { namespace gfx { -TemporaryRef +already_AddRefed DrawTarget::CreateCaptureDT(const IntSize& aSize) { RefPtr dt = new DrawTargetCaptureImpl(); diff --git a/gfx/2d/DrawTargetCG.cpp b/gfx/2d/DrawTargetCG.cpp index 640fcc4110..327b0fd990 100644 --- a/gfx/2d/DrawTargetCG.cpp +++ b/gfx/2d/DrawTargetCG.cpp @@ -185,7 +185,7 @@ DrawTargetCG::GetBackendType() const } } -TemporaryRef +already_AddRefed DrawTargetCG::Snapshot() { if (!mSnapshot) { @@ -200,7 +200,7 @@ DrawTargetCG::Snapshot() return snapshot.forget(); } -TemporaryRef +already_AddRefed DrawTargetCG::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { // XXX: in thebes we use CGLayers to do this kind of thing. It probably makes sense @@ -212,7 +212,7 @@ DrawTargetCG::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aForma return nullptr; } -TemporaryRef +already_AddRefed DrawTargetCG::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -259,7 +259,7 @@ GetRetainedImageFromSourceSurface(SourceSurface *aSurface) } } -TemporaryRef +already_AddRefed DrawTargetCG::OptimizeSourceSurface(SourceSurface *aSurface) const { RefPtr surface(aSurface); @@ -385,7 +385,7 @@ DrawTargetCG::DrawSurface(SourceSurface *aSurface, CGContextRestoreGState(mCg); } -TemporaryRef +already_AddRefed DrawTargetCG::CreateFilter(FilterType aType) { return FilterNodeSoftware::Create(aType); @@ -461,7 +461,7 @@ class GradientStopsCG : public GradientStops ExtendMode mExtend; }; -TemporaryRef +already_AddRefed DrawTargetCG::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const { @@ -1733,7 +1733,7 @@ DrawTargetCG::Init(BackendType aType, const IntSize &aSize, SurfaceFormat &aForm return Init(aType, nullptr, aSize, stride, aFormat); } -TemporaryRef +already_AddRefed DrawTargetCG::CreatePathBuilder(FillRule aFillRule) const { return MakeAndAddRef(aFillRule); diff --git a/gfx/2d/DrawTargetCG.h b/gfx/2d/DrawTargetCG.h index 67651dabb2..5e9a5ab9a0 100644 --- a/gfx/2d/DrawTargetCG.h +++ b/gfx/2d/DrawTargetCG.h @@ -119,7 +119,7 @@ public: virtual DrawTargetType GetType() const override; virtual BackendType GetBackendType() const override; - virtual TemporaryRef Snapshot() override; + virtual already_AddRefed Snapshot() override; virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, @@ -162,12 +162,12 @@ public: virtual void PushClip(const Path *) override; virtual void PushClipRect(const Rect &aRect) override; virtual void PopClip() override; - virtual TemporaryRef CreateSourceSurfaceFromNativeSurface(const NativeSurface&) const override { return nullptr;} - virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &, SurfaceFormat) const override; - virtual TemporaryRef CreatePathBuilder(FillRule) const override; - virtual TemporaryRef CreateGradientStops(GradientStop *, uint32_t, + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface&) const override { return nullptr;} + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &, SurfaceFormat) const override; + virtual already_AddRefed CreatePathBuilder(FillRule) const override; + virtual already_AddRefed CreateGradientStops(GradientStop *, uint32_t, ExtendMode aExtendMode = ExtendMode::CLAMP) const override; - virtual TemporaryRef CreateFilter(FilterType aType) override; + virtual already_AddRefed CreateFilter(FilterType aType) override; virtual void *GetNativeSurface(NativeSurfaceType) override; @@ -175,11 +175,11 @@ public: /* This is for creating good compatible surfaces */ - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const override; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const override; + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override; CGContextRef GetCGContext() { return mCg; } diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index c2833014ec..25db049807 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -652,7 +652,7 @@ DrawTargetCairo::GetSize() return mSize; } -TemporaryRef +already_AddRefed DrawTargetCairo::Snapshot() { if (mSnapshot) { @@ -1323,7 +1323,7 @@ DrawTargetCairo::PopClip() "Transforms are out of sync"); } -TemporaryRef +already_AddRefed DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FillRule::FILL_WINDING */) const { return MakeAndAddRef(aFillRule); @@ -1342,20 +1342,20 @@ DrawTargetCairo::ClearSurfaceForUnboundedSource(const CompositionOp &aOperator) } -TemporaryRef +already_AddRefed DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const { return MakeAndAddRef(aStops, aNumStops, aExtendMode); } -TemporaryRef +already_AddRefed DrawTargetCairo::CreateFilter(FilterType aType) { return FilterNodeSoftware::Create(aType); } -TemporaryRef +already_AddRefed DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -1397,7 +1397,7 @@ DestroyPixmap(void *data) } #endif -TemporaryRef +already_AddRefed DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const { RefPtr surface(aSurface); @@ -1486,7 +1486,7 @@ DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const return surface.forget(); } -TemporaryRef +already_AddRefed DrawTargetCairo::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { if (aSurface.mType == NativeSurfaceType::CAIRO_SURFACE) { @@ -1502,7 +1502,7 @@ DrawTargetCairo::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurf return nullptr; } -TemporaryRef +already_AddRefed DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { cairo_surface_t* similar = cairo_surface_create_similar(mSurface, @@ -1554,7 +1554,7 @@ DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& return true; } -TemporaryRef +already_AddRefed DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, float aSigma) const { diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index db9e8b4a30..f250766fea 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -60,7 +60,7 @@ public: virtual DrawTargetType GetType() const override; virtual BackendType GetBackendType() const override { return BackendType::CAIRO; } - virtual TemporaryRef Snapshot() override; + virtual already_AddRefed Snapshot() override; virtual IntSize GetSize() override; virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) override; @@ -133,27 +133,27 @@ public: virtual void PushClipRect(const Rect &aRect) override; virtual void PopClip() override; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const override; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const override; - virtual TemporaryRef + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override; + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override; - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override; - virtual TemporaryRef + virtual already_AddRefed CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, float aSigma) const override; - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override; - virtual TemporaryRef CreateFilter(FilterType aType) override; + virtual already_AddRefed CreateFilter(FilterType aType) override; virtual void *GetNativeSurface(NativeSurfaceType aType) override; diff --git a/gfx/2d/DrawTargetCapture.cpp b/gfx/2d/DrawTargetCapture.cpp index d53a98ec77..69c118c640 100644 --- a/gfx/2d/DrawTargetCapture.cpp +++ b/gfx/2d/DrawTargetCapture.cpp @@ -35,7 +35,7 @@ DrawTargetCaptureImpl::Init(const IntSize& aSize, DrawTarget* aRefDT) return true; } -TemporaryRef +already_AddRefed DrawTargetCaptureImpl::Snapshot() { RefPtr dt = mRefDT->CreateSimilarDrawTarget(mSize, mRefDT->GetFormat()); diff --git a/gfx/2d/DrawTargetCapture.h b/gfx/2d/DrawTargetCapture.h index 2ef8f0e625..3d2d56ce21 100644 --- a/gfx/2d/DrawTargetCapture.h +++ b/gfx/2d/DrawTargetCapture.h @@ -27,7 +27,7 @@ public: virtual BackendType GetBackendType() const { return mRefDT->GetBackendType(); } virtual DrawTargetType GetType() const { return mRefDT->GetType(); } - virtual TemporaryRef Snapshot(); + virtual already_AddRefed Snapshot(); virtual IntSize GetSize() { return mSize; } virtual void Flush() {} @@ -90,43 +90,43 @@ public: virtual void SetTransform(const Matrix &aTransform); - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const { return mRefDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat); } - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const { return mRefDT->OptimizeSourceSurface(aSurface); } - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { return mRefDT->CreateSourceSurfaceFromNativeSurface(aSurface); } - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { return mRefDT->CreateSimilarDrawTarget(aSize, aFormat); } - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const { return mRefDT->CreatePathBuilder(aFillRule); } - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const { return mRefDT->CreateGradientStops(aStops, aNumStops, aExtendMode); } - virtual TemporaryRef CreateFilter(FilterType aType) + virtual already_AddRefed CreateFilter(FilterType aType) { return mRefDT->CreateFilter(aType); } diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index 8d03efcf8f..acbb1fd58f 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -215,7 +215,7 @@ DrawTargetD2D::~DrawTargetD2D() /* * DrawTarget Implementation */ -TemporaryRef +already_AddRefed DrawTargetD2D::Snapshot() { if (!mSnapshot) { @@ -255,7 +255,7 @@ DrawTargetD2D::AddDependencyOnSource(SourceSurfaceD2DTarget* aSource) } } -TemporaryRef +already_AddRefed DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, Rect &aSource) { @@ -321,7 +321,7 @@ DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, return bitmap.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::GetImageForSurface(SourceSurface *aSurface) { RefPtr image; @@ -1179,7 +1179,7 @@ DrawTargetD2D::PopClip() mPushedClips.pop_back(); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -1194,7 +1194,7 @@ DrawTargetD2D::CreateSourceSurfaceFromData(unsigned char *aData, return newSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::OptimizeSourceSurface(SourceSurface *aSurface) const { if (aSurface->GetType() == SurfaceType::D2D1_BITMAP || @@ -1221,7 +1221,7 @@ DrawTargetD2D::OptimizeSourceSurface(SourceSurface *aSurface) const return newSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { if (aSurface.mType != NativeSurfaceType::D3D10_TEXTURE) { @@ -1241,7 +1241,7 @@ DrawTargetD2D::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurfac return newSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { RefPtr newTarget = @@ -1255,7 +1255,7 @@ DrawTargetD2D::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aForm return newTarget.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreatePathBuilder(FillRule aFillRule) const { RefPtr path; @@ -1280,7 +1280,7 @@ DrawTargetD2D::CreatePathBuilder(FillRule aFillRule) const return MakeAndAddRef(sink, path, aFillRule, BackendType::DIRECT2D); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const { D2D1_GRADIENT_STOP *stops = new D2D1_GRADIENT_STOP[aNumStops]; @@ -1306,7 +1306,7 @@ DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, E return MakeAndAddRef(stopCollection, Factory::GetDirect3D11Device()); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateFilter(FilterType aType) { RefPtr dc; @@ -1474,7 +1474,7 @@ DrawTargetD2D::GetByteSize() const return mSize.width * mSize.height * BytesPerPixel(mFormat); } -TemporaryRef +already_AddRefed DrawTargetD2D::GetCachedLayer() { RefPtr layer; @@ -1855,7 +1855,7 @@ DrawTargetD2D::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAlig return true; } -TemporaryRef +already_AddRefed DrawTargetD2D::GetClippedGeometry(IntRect *aClipBounds) { if (mCurrentClippedGeometry) { @@ -1944,7 +1944,7 @@ DrawTargetD2D::GetClippedGeometry(IntRect *aClipBounds) return clippedGeometry.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat) { HRESULT hr; @@ -2271,7 +2271,7 @@ DrawTargetD2D::FillGlyphsManual(ScaledFontDWrite *aFont, return true; } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha) { if (!IsPatternSupportedByD2D(aPattern)) { @@ -2434,7 +2434,7 @@ DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha) return nullptr; } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops) { CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 4096, 1, 1, 1); @@ -2506,7 +2506,7 @@ DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops) return tex.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D::CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds) { HRESULT hr; diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h index 5eea0a132b..eae24d73f4 100644 --- a/gfx/2d/DrawTargetD2D.h +++ b/gfx/2d/DrawTargetD2D.h @@ -45,7 +45,7 @@ public: virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; } virtual BackendType GetBackendType() const { return BackendType::DIRECT2D; } - virtual TemporaryRef Snapshot(); + virtual already_AddRefed Snapshot(); virtual IntSize GetSize() { return mSize; } virtual void Flush(); @@ -106,26 +106,26 @@ public: virtual void PushClipRect(const Rect &aRect); virtual void PopClip(); - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const; - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const; - virtual TemporaryRef CreateFilter(FilterType aType); + virtual already_AddRefed CreateFilter(FilterType aType); virtual bool SupportsRegionClipping() const { return false; } @@ -135,10 +135,10 @@ public: bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); bool InitD3D10Data(); uint32_t GetByteSize() const; - TemporaryRef GetCachedLayer(); + already_AddRefed GetCachedLayer(); void PopCachedLayer(ID2D1RenderTarget *aRT); - TemporaryRef GetImageForSurface(SourceSurface *aSurface); + already_AddRefed GetImageForSurface(SourceSurface *aSurface); static ID2D1Factory *factory(); static void CleanupD2D(); @@ -159,7 +159,7 @@ public: static uint64_t mVRAMUsageSS; private: - TemporaryRef + already_AddRefed GetBitmapForSurface(SourceSurface *aSurface, Rect &aSource); friend class AutoSaveRestoreClippedOut; @@ -199,20 +199,20 @@ private: IDWriteRenderingParams *aParams, const DrawOptions &aOptions = DrawOptions()); - TemporaryRef CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); + already_AddRefed CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); // This returns the clipped geometry, in addition it returns aClipBounds which // represents the intersection of all pixel-aligned rectangular clips that // are currently set. The returned clipped geometry must be clipped by these // bounds to correctly reflect the total clip. This is in device space. - TemporaryRef GetClippedGeometry(IntRect *aClipBounds); + already_AddRefed GetClippedGeometry(IntRect *aClipBounds); bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); - TemporaryRef CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); + already_AddRefed CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); - TemporaryRef CreateGradientTexture(const GradientStopsD2D *aStops); - TemporaryRef CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds); + already_AddRefed CreateGradientTexture(const GradientStopsD2D *aStops); + already_AddRefed CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds); void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern); void SetupStateForRendering(); diff --git a/gfx/2d/DrawTargetD2D1.cpp b/gfx/2d/DrawTargetD2D1.cpp index 5098a627a2..f0d13933c9 100644 --- a/gfx/2d/DrawTargetD2D1.cpp +++ b/gfx/2d/DrawTargetD2D1.cpp @@ -65,7 +65,7 @@ DrawTargetD2D1::~DrawTargetD2D1() } } -TemporaryRef +already_AddRefed DrawTargetD2D1::Snapshot() { if (mSnapshot) { @@ -642,7 +642,7 @@ DrawTargetD2D1::PopClip() mPushedClips.pop_back(); } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -662,7 +662,7 @@ DrawTargetD2D1::CreateSourceSurfaceFromData(unsigned char *aData, return MakeAndAddRef(bitmap.get(), mDC, aFormat, aSize); } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { RefPtr dt = new DrawTargetD2D1(); @@ -674,7 +674,7 @@ DrawTargetD2D1::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFor return dt.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreatePathBuilder(FillRule aFillRule) const { RefPtr path; @@ -699,7 +699,7 @@ DrawTargetD2D1::CreatePathBuilder(FillRule aFillRule) const return MakeAndAddRef(sink, path, aFillRule, BackendType::DIRECT2D1_1); } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const { if (aNumStops == 0) { @@ -730,7 +730,7 @@ DrawTargetD2D1::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, return MakeAndAddRef(stopCollection, Factory::GetDirect3D11Device()); } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreateFilter(FilterType aType) { return FilterNodeD2D1::Create(mDC, aType); @@ -1109,7 +1109,7 @@ DrawTargetD2D1::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAli return true; } -TemporaryRef +already_AddRefed DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds) { if (mCurrentClippedGeometry) { @@ -1200,7 +1200,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds) return clippedGeometry.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D1::GetInverseClippedGeometry() { IntRect bounds; @@ -1266,13 +1266,13 @@ DrawTargetD2D1::PopClipsFromDC(ID2D1DeviceContext *aDC) } } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreateTransparentBlackBrush() { return GetSolidColorBrush(D2D1::ColorF(0, 0)); } -TemporaryRef +already_AddRefed DrawTargetD2D1::GetSolidColorBrush(const D2D_COLOR_F& aColor) { RefPtr brush = mSolidColorBrush; @@ -1280,7 +1280,7 @@ DrawTargetD2D1::GetSolidColorBrush(const D2D_COLOR_F& aColor) return brush.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha) { if (!IsPatternSupportedByD2D(aPattern)) { @@ -1407,7 +1407,7 @@ DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha) return CreateTransparentBlackBrush(); } -TemporaryRef +already_AddRefed DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform, ExtendMode aExtendMode, const IntRect* aSourceRect) { @@ -1437,7 +1437,7 @@ DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTrans return image.forget(); } -TemporaryRef +already_AddRefed DrawTargetD2D1::OptimizeSourceSurface(SourceSurface* aSurface) const { if (aSurface->GetType() == SurfaceType::D2D1_1_IMAGE) { diff --git a/gfx/2d/DrawTargetD2D1.h b/gfx/2d/DrawTargetD2D1.h index dd1b453aaa..9aa5934e17 100644 --- a/gfx/2d/DrawTargetD2D1.h +++ b/gfx/2d/DrawTargetD2D1.h @@ -37,7 +37,7 @@ public: virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; } virtual BackendType GetBackendType() const { return BackendType::DIRECT2D1_1; } - virtual TemporaryRef Snapshot(); + virtual already_AddRefed Snapshot(); virtual IntSize GetSize() { return mSize; } virtual void Flush(); @@ -97,26 +97,26 @@ public: virtual void PushClipRect(const Rect &aRect); virtual void PopClip(); - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const; - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { return nullptr; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const; - virtual TemporaryRef CreateFilter(FilterType aType); + virtual already_AddRefed CreateFilter(FilterType aType); virtual bool SupportsRegionClipping() const { return false; } @@ -126,10 +126,10 @@ public: bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat); uint32_t GetByteSize() const; - TemporaryRef GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform, + already_AddRefed GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform, ExtendMode aExtendMode, const IntRect* aSourceRect = nullptr); - TemporaryRef GetImageForSurface(SourceSurface *aSurface, ExtendMode aExtendMode) { + already_AddRefed GetImageForSurface(SourceSurface *aSurface, ExtendMode aExtendMode) { Matrix mat; return GetImageForSurface(aSurface, mat, aExtendMode, nullptr); } @@ -173,9 +173,9 @@ private: // represents the intersection of all pixel-aligned rectangular clips that // are currently set. The returned clipped geometry must be clipped by these // bounds to correctly reflect the total clip. This is in device space. - TemporaryRef GetClippedGeometry(IntRect *aClipBounds); + already_AddRefed GetClippedGeometry(IntRect *aClipBounds); - TemporaryRef GetInverseClippedGeometry(); + already_AddRefed GetInverseClippedGeometry(); bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); @@ -184,9 +184,9 @@ private: void PushClipsToDC(ID2D1DeviceContext *aDC); void PopClipsFromDC(ID2D1DeviceContext *aDC); - TemporaryRef CreateTransparentBlackBrush(); - TemporaryRef GetSolidColorBrush(const D2D_COLOR_F& aColor); - TemporaryRef CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); + already_AddRefed CreateTransparentBlackBrush(); + already_AddRefed GetSolidColorBrush(const D2D_COLOR_F& aColor); + already_AddRefed CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); void PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform); diff --git a/gfx/2d/DrawTargetDual.cpp b/gfx/2d/DrawTargetDual.cpp index 86ad04d7f3..d5ed632a28 100644 --- a/gfx/2d/DrawTargetDual.cpp +++ b/gfx/2d/DrawTargetDual.cpp @@ -181,7 +181,7 @@ DrawTargetDual::Mask(const Pattern &aSource, const Pattern &aMask, const DrawOpt mB->Mask(*source.mB, *mask.mB, aOptions); } -TemporaryRef +already_AddRefed DrawTargetDual::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { RefPtr dtA = mA->CreateSimilarDrawTarget(aSize, aFormat); diff --git a/gfx/2d/DrawTargetDual.h b/gfx/2d/DrawTargetDual.h index 591b7da755..6c8a05abe5 100644 --- a/gfx/2d/DrawTargetDual.h +++ b/gfx/2d/DrawTargetDual.h @@ -45,7 +45,7 @@ public: virtual DrawTargetType GetType() const override { return mA->GetType(); } virtual BackendType GetBackendType() const override { return mA->GetBackendType(); } - virtual TemporaryRef Snapshot() override { + virtual already_AddRefed Snapshot() override { return MakeAndAddRef(mA, mB); } virtual IntSize GetSize() override { return mA->GetSize(); } @@ -105,7 +105,7 @@ public: virtual void Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions) override; - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -114,26 +114,26 @@ public: return mA->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat); } - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const override + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override { return mA->OptimizeSourceSurface(aSurface); } - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override { return mA->CreateSourceSurfaceFromNativeSurface(aSurface); } - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override { return mA->CreatePathBuilder(aFillRule); } - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override @@ -141,7 +141,7 @@ public: return mA->CreateGradientStops(aStops, aNumStops, aExtendMode); } - virtual TemporaryRef CreateFilter(FilterType aType) override + virtual already_AddRefed CreateFilter(FilterType aType) override { return mA->CreateFilter(aType); } diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp index b437229fa9..e541e07ef6 100644 --- a/gfx/2d/DrawTargetRecording.cpp +++ b/gfx/2d/DrawTargetRecording.cpp @@ -31,7 +31,7 @@ public: virtual SurfaceType GetType() const { return SurfaceType::RECORDING; } virtual IntSize GetSize() const { return mFinalSurface->GetSize(); } virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); } - virtual TemporaryRef GetDataSurface() { return mFinalSurface->GetDataSurface(); } + virtual already_AddRefed GetDataSurface() { return mFinalSurface->GetDataSurface(); } RefPtr mFinalSurface; RefPtr mRecorder; @@ -365,7 +365,7 @@ DrawTargetRecording::Stroke(const Path *aPath, mFinalDT->Stroke(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aStrokeOptions, aOptions); } -TemporaryRef +already_AddRefed DrawTargetRecording::Snapshot() { RefPtr surf = mFinalDT->Snapshot(); @@ -410,7 +410,7 @@ DrawTargetRecording::DrawFilter(FilterNode *aNode, mFinalDT->DrawFilter(GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions); } -TemporaryRef +already_AddRefed DrawTargetRecording::CreateFilter(FilterType aType) { RefPtr node = mFinalDT->CreateFilter(aType); @@ -461,7 +461,7 @@ DrawTargetRecording::PopClip() mFinalDT->PopClip(); } -TemporaryRef +already_AddRefed DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -476,7 +476,7 @@ DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData, return retSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const { RefPtr surf = mFinalDT->OptimizeSourceSurface(aSurface); @@ -509,7 +509,7 @@ DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const return retSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { RefPtr surf = mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface); @@ -537,21 +537,21 @@ DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &a return retSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { RefPtr dt = mFinalDT->CreateSimilarDrawTarget(aSize, aFormat); return MakeAndAddRef(mRecorder.get(), dt); } -TemporaryRef +already_AddRefed DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const { RefPtr builder = mFinalDT->CreatePathBuilder(aFillRule); return MakeAndAddRef(builder, aFillRule); } -TemporaryRef +already_AddRefed DrawTargetRecording::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const diff --git a/gfx/2d/DrawTargetRecording.h b/gfx/2d/DrawTargetRecording.h index ba89769c24..0e2b3fee7f 100644 --- a/gfx/2d/DrawTargetRecording.h +++ b/gfx/2d/DrawTargetRecording.h @@ -22,7 +22,7 @@ public: virtual DrawTargetType GetType() const override { return mFinalDT->GetType(); } virtual BackendType GetBackendType() const override { return mFinalDT->GetBackendType(); } - virtual TemporaryRef Snapshot() override; + virtual already_AddRefed Snapshot() override; virtual IntSize GetSize() override { return mFinalDT->GetSize(); } @@ -210,7 +210,7 @@ public: * * The SourceSurface does not take ownership of aData, and may be freed at any time. */ - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const override; @@ -220,20 +220,20 @@ public: * an arbitrary other SourceSurface. This may return aSourceSurface or some * other existing surface. */ - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const override; + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override; /* * Create a SourceSurface for a type of NativeSurface. This may fail if the * draw target does not know how to deal with the type of NativeSurface passed * in. */ - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override; /* * Create a DrawTarget whose snapshot is optimized for use with this DrawTarget. */ - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override; /* @@ -243,7 +243,7 @@ public: * ID2D1SimplifiedGeometrySink requires the fill mode * to be set before calling BeginFigure(). */ - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; /* * Create a GradientStops object that holds information about a set of @@ -255,12 +255,12 @@ public: * aExtendNone This describes how to extend the stop color outside of the * gradient area. */ - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override; - virtual TemporaryRef CreateFilter(FilterType aType) override; + virtual already_AddRefed CreateFilter(FilterType aType) override; /* * Set a transform on the surface, this transform is applied at drawing time diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index c6829d5709..c5a5a11e04 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -133,7 +133,7 @@ DrawTargetSkia::~DrawTargetSkia() { } -TemporaryRef +already_AddRefed DrawTargetSkia::Snapshot() { RefPtr snapshot = mSnapshot; @@ -608,7 +608,7 @@ DrawTargetSkia::MaskSurface(const Pattern &aSource, } } -TemporaryRef +already_AddRefed DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, @@ -624,7 +624,7 @@ DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData, return newSurf.forget(); } -TemporaryRef +already_AddRefed DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { RefPtr target = new DrawTargetSkia(); @@ -644,7 +644,7 @@ DrawTargetSkia::UsingSkiaGPU() const #endif } -TemporaryRef +already_AddRefed DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const { if (aSurface->GetType() == SurfaceType::SKIA) { @@ -676,7 +676,7 @@ DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const return result.forget(); } -TemporaryRef +already_AddRefed DrawTargetSkia::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { if (aSurface.mType == NativeSurfaceType::CAIRO_SURFACE) { @@ -870,7 +870,7 @@ DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType) } -TemporaryRef +already_AddRefed DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const { return MakeAndAddRef(aFillRule); @@ -916,7 +916,7 @@ DrawTargetSkia::PopClip() mCanvas->restore(); } -TemporaryRef +already_AddRefed DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const { std::vector stops; @@ -929,7 +929,7 @@ DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, Ex return MakeAndAddRef(stops, aNumStops, aExtendMode); } -TemporaryRef +already_AddRefed DrawTargetSkia::CreateFilter(FilterType aType) { return FilterNodeSoftware::Create(aType); diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index 08b0f742da..260941ebda 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -34,7 +34,7 @@ public: virtual DrawTargetType GetType() const override; virtual BackendType GetBackendType() const override { return BackendType::SKIA; } - virtual TemporaryRef Snapshot() override; + virtual already_AddRefed Snapshot() override; virtual IntSize GetSize() override { return mSize; } virtual void Flush() override; virtual void DrawSurface(SourceSurface *aSurface, @@ -90,18 +90,18 @@ public: virtual void PushClip(const Path *aPath) override; virtual void PushClipRect(const Rect& aRect) override; virtual void PopClip() override; - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const override; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const override; - virtual TemporaryRef + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override; + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override; - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; - virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override; - virtual TemporaryRef CreateFilter(FilterType aType) override; + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override; + virtual already_AddRefed CreateFilter(FilterType aType) override; virtual void SetTransform(const Matrix &aTransform) override; virtual void *GetNativeSurface(NativeSurfaceType aType) override; diff --git a/gfx/2d/DrawTargetTiled.cpp b/gfx/2d/DrawTargetTiled.cpp index 739ae6a26e..8b419ed5e4 100644 --- a/gfx/2d/DrawTargetTiled.cpp +++ b/gfx/2d/DrawTargetTiled.cpp @@ -50,7 +50,7 @@ DrawTargetTiled::Init(const TileSet& aTiles) return true; } -TemporaryRef +already_AddRefed DrawTargetTiled::Snapshot() { return MakeAndAddRef(mTiles, mRect); diff --git a/gfx/2d/DrawTargetTiled.h b/gfx/2d/DrawTargetTiled.h index 75fa6a8bc9..b709aee694 100644 --- a/gfx/2d/DrawTargetTiled.h +++ b/gfx/2d/DrawTargetTiled.h @@ -40,7 +40,7 @@ public: virtual DrawTargetType GetType() const override { return mTiles[0].mDrawTarget->GetType(); } virtual BackendType GetBackendType() const override { return mTiles[0].mDrawTarget->GetBackendType(); } - virtual TemporaryRef Snapshot() override; + virtual already_AddRefed Snapshot() override; virtual IntSize GetSize() override { MOZ_ASSERT(mRect.width > 0 && mRect.height > 0); return IntSize(mRect.XMost(), mRect.YMost()); @@ -106,43 +106,43 @@ public: virtual void SetTransform(const Matrix &aTransform) override; - virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, + virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const override { return mTiles[0].mDrawTarget->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat); } - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const override + virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override { return mTiles[0].mDrawTarget->OptimizeSourceSurface(aSurface); } - virtual TemporaryRef + virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override { return mTiles[0].mDrawTarget->CreateSourceSurfaceFromNativeSurface(aSurface); } - virtual TemporaryRef + virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override { return mTiles[0].mDrawTarget->CreateSimilarDrawTarget(aSize, aFormat); } - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override + virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override { return mTiles[0].mDrawTarget->CreatePathBuilder(aFillRule); } - virtual TemporaryRef + virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const override { return mTiles[0].mDrawTarget->CreateGradientStops(aStops, aNumStops, aExtendMode); } - virtual TemporaryRef CreateFilter(FilterType aType) override + virtual already_AddRefed CreateFilter(FilterType aType) override { return mTiles[0].mDrawTarget->CreateFilter(aType); } @@ -172,7 +172,7 @@ public: } virtual SurfaceFormat GetFormat() const { return mSnapshots[0]->GetFormat(); } - virtual TemporaryRef GetDataSurface() + virtual already_AddRefed GetDataSurface() { RefPtr surf = Factory::CreateDataSourceSurface(GetSize(), GetFormat()); diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 9ada63c691..ae01ddbb94 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -318,7 +318,7 @@ Factory::CheckSurfaceSize(const IntSize &sz, return true; } -TemporaryRef +already_AddRefed Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat) { if (!AllowedSurfaceSize(aSize)) { @@ -398,13 +398,13 @@ Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFor return retVal.forget(); } -TemporaryRef +already_AddRefed Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT) { return MakeAndAddRef(aRecorder, aDT); } -TemporaryRef +already_AddRefed Factory::CreateDrawTargetForData(BackendType aBackend, unsigned char *aData, const IntSize &aSize, @@ -466,7 +466,7 @@ Factory::CreateDrawTargetForData(BackendType aBackend, return retVal.forget(); } -TemporaryRef +already_AddRefed Factory::CreateTiledDrawTarget(const TileSet& aTileSet) { RefPtr dt = new DrawTargetTiled(); @@ -521,7 +521,7 @@ Factory::GetMaxSurfaceSize(BackendType aType) } } -TemporaryRef +already_AddRefed Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize) { switch (aNativeFont.mType) { @@ -555,7 +555,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz } } -TemporaryRef +already_AddRefed Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, uint32_t aFaceIndex, Float aGlyphSize, FontType aType) @@ -573,7 +573,7 @@ Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, } } -TemporaryRef +already_AddRefed Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont) { #ifdef USE_CAIRO @@ -589,7 +589,7 @@ Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, c #endif } -TemporaryRef +already_AddRefed Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB) { MOZ_ASSERT(targetA && targetB); @@ -608,7 +608,7 @@ Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB) #ifdef WIN32 -TemporaryRef +already_AddRefed Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat) { MOZ_ASSERT(aTexture); @@ -632,7 +632,7 @@ Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceForma return nullptr; } -TemporaryRef +already_AddRefed Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA, ID3D10Texture2D *aTextureB, SurfaceFormat aFormat) @@ -687,7 +687,7 @@ Factory::GetDirect3D10Device() return mD3D10Device; } -TemporaryRef +already_AddRefed Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat) { MOZ_ASSERT(aTexture); @@ -750,7 +750,7 @@ Factory::SupportsD2D1() return !!D2DFactory1(); } -TemporaryRef +already_AddRefed Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams) { return MakeAndAddRef(aParams); @@ -782,7 +782,7 @@ Factory::D2DCleanup() #endif // XP_WIN #ifdef USE_SKIA_GPU -TemporaryRef +already_AddRefed Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, const IntSize &aSize, SurfaceFormat aFormat) @@ -802,7 +802,7 @@ Factory::PurgeAllCaches() } #ifdef USE_SKIA_FREETYPE -TemporaryRef +already_AddRefed Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting) { RefPtr options = @@ -814,7 +814,7 @@ Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHintin } #endif -TemporaryRef +already_AddRefed Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat) { RefPtr retVal; @@ -834,7 +834,7 @@ Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSiz } #ifdef XP_MACOSX -TemporaryRef +already_AddRefed Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize) { RefPtr retVal; @@ -851,14 +851,14 @@ Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize return retVal.forget(); } -TemporaryRef +already_AddRefed Factory::CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor) { return MakeAndAddRef(aFontSmoothingBackgroundColor); } #endif -TemporaryRef +already_AddRefed Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride, const IntSize &aSize, SurfaceFormat aFormat) @@ -877,7 +877,7 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride, return nullptr; } -TemporaryRef +already_AddRefed Factory::CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat, bool aZero) @@ -896,7 +896,7 @@ Factory::CreateDataSourceSurface(const IntSize &aSize, return nullptr; } -TemporaryRef +already_AddRefed Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride, @@ -916,7 +916,7 @@ Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize, return nullptr; } -TemporaryRef +already_AddRefed Factory::CreateEventRecorderForFile(const char *aFilename) { return MakeAndAddRef(aFilename); diff --git a/gfx/2d/FilterNodeD2D1.cpp b/gfx/2d/FilterNodeD2D1.cpp index 58f132269f..898c82621d 100644 --- a/gfx/2d/FilterNodeD2D1.cpp +++ b/gfx/2d/FilterNodeD2D1.cpp @@ -150,7 +150,7 @@ D2D1_CHANNEL_SELECTOR D2DChannelSelector(uint32_t aMode) return D2D1_CHANNEL_SELECTOR_R; } -TemporaryRef GetImageForSourceSurface(DrawTarget *aDT, SourceSurface *aSurface) +already_AddRefed GetImageForSourceSurface(DrawTarget *aDT, SourceSurface *aSurface) { if (aDT->IsTiledDrawTarget() || aDT->IsDualDrawTarget()) { MOZ_CRASH("Incompatible draw target type!"); @@ -537,7 +537,7 @@ IsTransferFilterType(FilterType aType) } /* static */ -TemporaryRef +already_AddRefed FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType) { if (aType == FilterType::CONVOLVE_MATRIX) { diff --git a/gfx/2d/FilterNodeD2D1.h b/gfx/2d/FilterNodeD2D1.h index 612dbfbef7..1f06dda6f5 100644 --- a/gfx/2d/FilterNodeD2D1.h +++ b/gfx/2d/FilterNodeD2D1.h @@ -19,7 +19,7 @@ class FilterNodeD2D1 : public FilterNode { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeD2D1) - static TemporaryRef Create(ID2D1DeviceContext *aDC, FilterType aType); + static already_AddRefed Create(ID2D1DeviceContext *aDC, FilterType aType); FilterNodeD2D1(ID2D1Effect *aEffect, FilterType aType) : mEffect(aEffect) diff --git a/gfx/2d/FilterNodeSoftware.cpp b/gfx/2d/FilterNodeSoftware.cpp index ead4990ee0..79363a227b 100644 --- a/gfx/2d/FilterNodeSoftware.cpp +++ b/gfx/2d/FilterNodeSoftware.cpp @@ -180,7 +180,7 @@ NS_lround(double x) return x >= 0.0 ? int32_t(x + 0.5) : int32_t(x - 0.5); } -TemporaryRef +already_AddRefed CloneAligned(DataSourceSurface* aSource) { return CreateDataSourceSurfaceByCloning(aSource); @@ -382,7 +382,7 @@ TileSurface(DataSourceSurface* aSource, DataSourceSurface* aTarget, const IntPoi } } -static TemporaryRef +static already_AddRefed GetDataSurfaceInRect(SourceSurface *aSurface, const IntRect &aSurfaceRect, const IntRect &aDestRect, @@ -435,7 +435,7 @@ GetDataSurfaceInRect(SourceSurface *aSurface, return target.forget(); } -/* static */ TemporaryRef +/* static */ already_AddRefed FilterNodeSoftware::Create(FilterType aType) { RefPtr filter; @@ -590,7 +590,7 @@ FilterNodeSoftware::Draw(DrawTarget* aDrawTarget, } } -TemporaryRef +already_AddRefed FilterNodeSoftware::GetOutput(const IntRect &aRect) { MOZ_ASSERT(GetOutputRectInRect(aRect).Contains(aRect)); @@ -651,7 +651,7 @@ FilterNodeSoftware::DesiredFormat(SurfaceFormat aCurrentFormat, return SurfaceFormat::B8G8R8A8; } -TemporaryRef +already_AddRefed FilterNodeSoftware::GetInputDataSourceSurface(uint32_t aInputEnumIndex, const IntRect& aRect, FormatHint aFormatHint, @@ -950,7 +950,7 @@ static CompositionOp ToBlendOp(BlendMode aOp) return CompositionOp::OP_OVER; } -TemporaryRef +already_AddRefed FilterNodeBlendSoftware::Render(const IntRect& aRect) { RefPtr input1 = @@ -1064,7 +1064,7 @@ FilterNodeTransformSoftware::SourceRectForOutputRect(const IntRect &aRect) return GetInputRectInRect(IN_TRANSFORM_IN, neededIntRect); } -TemporaryRef +already_AddRefed FilterNodeTransformSoftware::Render(const IntRect& aRect) { IntRect srcRect = SourceRectForOutputRect(aRect); @@ -1169,7 +1169,7 @@ FilterNodeMorphologySoftware::SetAttribute(uint32_t aIndex, Invalidate(); } -static TemporaryRef +static already_AddRefed ApplyMorphology(const IntRect& aSourceRect, DataSourceSurface* aInput, const IntRect& aDestRect, int32_t rx, int32_t ry, MorphologyOperator aOperator) @@ -1224,7 +1224,7 @@ ApplyMorphology(const IntRect& aSourceRect, DataSourceSurface* aInput, return dest.forget(); } -TemporaryRef +already_AddRefed FilterNodeMorphologySoftware::Render(const IntRect& aRect) { IntRect srcRect = aRect; @@ -1295,7 +1295,7 @@ FilterNodeColorMatrixSoftware::SetAttribute(uint32_t aIndex, Invalidate(); } -static TemporaryRef +static already_AddRefed Premultiply(DataSourceSurface* aSurface) { if (aSurface->GetFormat() == SurfaceFormat::A8) { @@ -1321,7 +1321,7 @@ Premultiply(DataSourceSurface* aSurface) return target.forget(); } -static TemporaryRef +static already_AddRefed Unpremultiply(DataSourceSurface* aSurface) { if (aSurface->GetFormat() == SurfaceFormat::A8) { @@ -1347,7 +1347,7 @@ Unpremultiply(DataSourceSurface* aSurface) return target.forget(); } -TemporaryRef +already_AddRefed FilterNodeColorMatrixSoftware::Render(const IntRect& aRect) { RefPtr input = @@ -1416,7 +1416,7 @@ FormatForColor(Color aColor) return SurfaceFormat::B8G8R8A8; } -TemporaryRef +already_AddRefed FilterNodeFloodSoftware::Render(const IntRect& aRect) { SurfaceFormat format = FormatForColor(mColor); @@ -1454,7 +1454,7 @@ FilterNodeFloodSoftware::Render(const IntRect& aRect) // Override GetOutput to get around caching. Rendering simple floods is // comparatively fast. -TemporaryRef +already_AddRefed FilterNodeFloodSoftware::GetOutput(const IntRect& aRect) { return Render(aRect); @@ -1507,7 +1507,7 @@ struct CompareIntRects }; } -TemporaryRef +already_AddRefed FilterNodeTileSoftware::Render(const IntRect& aRect) { if (mSourceRect.IsEmpty()) { @@ -1673,7 +1673,7 @@ IsAllZero(uint8_t aLookupTable[256]) return true; } -TemporaryRef +already_AddRefed FilterNodeComponentTransferSoftware::Render(const IntRect& aRect) { if (mDisableR && mDisableG && mDisableB && mDisableA) { @@ -2287,7 +2287,7 @@ ConvolvePixel(const uint8_t *aSourceData, } } -TemporaryRef +already_AddRefed FilterNodeConvolveMatrixSoftware::Render(const IntRect& aRect) { if (mKernelUnitLength.width == floor(mKernelUnitLength.width) && @@ -2354,7 +2354,7 @@ TranslateDoubleToShifts(double aDouble, int32_t &aShiftL, int32_t &aShiftR) } template -TemporaryRef +already_AddRefed FilterNodeConvolveMatrixSoftware::DoRender(const IntRect& aRect, CoordType aKernelUnitLengthX, CoordType aKernelUnitLengthY) @@ -2519,7 +2519,7 @@ FilterNodeDisplacementMapSoftware::SetAttribute(uint32_t aIndex, uint32_t aValue Invalidate(); } -TemporaryRef +already_AddRefed FilterNodeDisplacementMapSoftware::Render(const IntRect& aRect) { IntRect srcRect = InflatedSourceOrDestRect(aRect); @@ -2661,7 +2661,7 @@ FilterNodeTurbulenceSoftware::SetAttribute(uint32_t aIndex, uint32_t aValue) Invalidate(); } -TemporaryRef +already_AddRefed FilterNodeTurbulenceSoftware::Render(const IntRect& aRect) { return FilterProcessing::RenderTurbulence( @@ -2706,7 +2706,7 @@ FilterNodeArithmeticCombineSoftware::SetAttribute(uint32_t aIndex, Invalidate(); } -TemporaryRef +already_AddRefed FilterNodeArithmeticCombineSoftware::Render(const IntRect& aRect) { RefPtr input1 = @@ -2780,7 +2780,7 @@ FilterNodeCompositeSoftware::SetAttribute(uint32_t aIndex, uint32_t aCompositeOp Invalidate(); } -TemporaryRef +already_AddRefed FilterNodeCompositeSoftware::Render(const IntRect& aRect) { RefPtr start = @@ -2856,7 +2856,7 @@ FilterNodeBlurXYSoftware::InputIndex(uint32_t aInputEnumIndex) } } -TemporaryRef +already_AddRefed FilterNodeBlurXYSoftware::Render(const IntRect& aRect) { Size sigmaXY = StdDeviationXY(); @@ -3018,7 +3018,7 @@ FilterNodeCropSoftware::SetAttribute(uint32_t aIndex, Invalidate(); } -TemporaryRef +already_AddRefed FilterNodeCropSoftware::Render(const IntRect& aRect) { return GetInputDataSourceSurface(IN_CROP_IN, aRect.Intersect(mCropRect)); @@ -3045,7 +3045,7 @@ FilterNodePremultiplySoftware::InputIndex(uint32_t aInputEnumIndex) } } -TemporaryRef +already_AddRefed FilterNodePremultiplySoftware::Render(const IntRect& aRect) { RefPtr input = @@ -3074,7 +3074,7 @@ FilterNodeUnpremultiplySoftware::InputIndex(uint32_t aInputEnumIndex) } } -TemporaryRef +already_AddRefed FilterNodeUnpremultiplySoftware::Render(const IntRect& aRect) { RefPtr input = @@ -3354,7 +3354,7 @@ GenerateNormal(const uint8_t *data, int32_t stride, } template -TemporaryRef +already_AddRefed FilterNodeLightingSoftware::Render(const IntRect& aRect) { if (mKernelUnitLength.width == floor(mKernelUnitLength.width) && @@ -3375,7 +3375,7 @@ FilterNodeLightingSoftware::RequestFromInputsForRect(co } template template -TemporaryRef +already_AddRefed FilterNodeLightingSoftware::DoRender(const IntRect& aRect, CoordType aKernelUnitLengthX, CoordType aKernelUnitLengthY) diff --git a/gfx/2d/FilterNodeSoftware.h b/gfx/2d/FilterNodeSoftware.h index dfef8ba017..74a6026998 100644 --- a/gfx/2d/FilterNodeSoftware.h +++ b/gfx/2d/FilterNodeSoftware.h @@ -42,7 +42,7 @@ public: virtual ~FilterNodeSoftware(); // Factory method, intended to be called from DrawTarget*::CreateFilter. - static TemporaryRef Create(FilterType aType); + static already_AddRefed Create(FilterType aType); // Draw the filter, intended to be called by DrawTarget*::DrawFilter. void Draw(DrawTarget* aDrawTarget, const Rect &aSourceRect, @@ -90,7 +90,7 @@ protected: * pass through input surfaces unchanged. * Callers need to treat the returned surface as immutable. */ - virtual TemporaryRef Render(const IntRect& aRect) = 0; + virtual already_AddRefed Render(const IntRect& aRect) = 0; /** * Call RequestRect (see below) on any input filters with the desired input @@ -104,7 +104,7 @@ protected: * by subclasses that don't want to cache their output. Those classes should * call Render(aRect) directly from here. */ - virtual TemporaryRef GetOutput(const IntRect &aRect); + virtual already_AddRefed GetOutput(const IntRect &aRect); // The following methods are non-virtual helper methods. @@ -139,7 +139,7 @@ protected: * surface is guaranteed to be of SurfaceFormat::B8G8R8A8 always. * Each pixel row of the returned surface is guaranteed to be 16-byte aligned. */ - TemporaryRef + already_AddRefed GetInputDataSourceSurface(uint32_t aInputEnumIndex, const IntRect& aRect, FormatHint aFormatHint = CAN_HANDLE_A8, ConvolveMatrixEdgeMode aEdgeMode = EDGE_MODE_NONE, @@ -226,7 +226,7 @@ public: virtual void SetAttribute(uint32_t aIndex, const Matrix &aMatrix) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -247,7 +247,7 @@ public: virtual void SetAttribute(uint32_t aIndex, uint32_t aBlendMode) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -267,7 +267,7 @@ public: virtual void SetAttribute(uint32_t aIndex, uint32_t aOperator) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -287,7 +287,7 @@ public: virtual void SetAttribute(uint32_t aIndex, uint32_t aAlphaMode) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -306,8 +306,8 @@ public: virtual void SetAttribute(uint32_t aIndex, const Color &aColor) override; protected: - virtual TemporaryRef GetOutput(const IntRect &aRect) override; - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed GetOutput(const IntRect &aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; private: @@ -323,7 +323,7 @@ public: virtual void SetAttribute(uint32_t aIndex, const IntRect &aSourceRect) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -345,7 +345,7 @@ public: virtual void SetAttribute(uint32_t aIndex, bool aDisable) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -470,14 +470,14 @@ public: virtual void SetAttribute(uint32_t aIndex, bool aPreserveAlpha) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; private: template - TemporaryRef DoRender(const IntRect& aRect, + already_AddRefed DoRender(const IntRect& aRect, CoordType aKernelUnitLengthX, CoordType aKernelUnitLengthY); @@ -506,7 +506,7 @@ public: virtual void SetAttribute(uint32_t aIndex, uint32_t aValue) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -532,7 +532,7 @@ public: virtual void SetAttribute(uint32_t aIndex, uint32_t aValue) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; @@ -555,7 +555,7 @@ public: virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -577,7 +577,7 @@ public: virtual void SetAttribute(uint32_t aIndex, uint32_t aOperator) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -593,7 +593,7 @@ class FilterNodeBlurXYSoftware : public FilterNodeSoftware public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlurXYSoftware, override) protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; IntRect InflatedSourceOrDestRect(const IntRect &aDestRect); @@ -646,7 +646,7 @@ public: virtual void SetAttribute(uint32_t aIndex, const Rect &aSourceRect) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -661,7 +661,7 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodePremultiplySoftware, override) virtual const char* GetName() override { return "Premultiply"; } protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -673,7 +673,7 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeUnpremultiplySoftware, override) virtual const char* GetName() override { return "Unpremultiply"; } protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; @@ -697,14 +697,14 @@ public: virtual void SetAttribute(uint32_t aIndex, const Color &) override; protected: - virtual TemporaryRef Render(const IntRect& aRect) override; + virtual already_AddRefed Render(const IntRect& aRect) override; virtual IntRect GetOutputRectInRect(const IntRect& aRect) override; virtual int32_t InputIndex(uint32_t aInputEnumIndex) override; virtual void RequestFromInputsForRect(const IntRect &aRect) override; private: template - TemporaryRef DoRender(const IntRect& aRect, + already_AddRefed DoRender(const IntRect& aRect, CoordType aKernelUnitLengthX, CoordType aKernelUnitLengthY); diff --git a/gfx/2d/FilterProcessing.cpp b/gfx/2d/FilterProcessing.cpp index 084f9476c5..63be4f9d58 100644 --- a/gfx/2d/FilterProcessing.cpp +++ b/gfx/2d/FilterProcessing.cpp @@ -9,7 +9,7 @@ namespace mozilla { namespace gfx { -TemporaryRef +already_AddRefed FilterProcessing::ExtractAlpha(DataSourceSurface* aSource) { IntSize size = aSource->GetSize(); @@ -33,7 +33,7 @@ FilterProcessing::ExtractAlpha(DataSourceSurface* aSource) return alpha.forget(); } -TemporaryRef +already_AddRefed FilterProcessing::ConvertToB8G8R8A8(SourceSurface* aSurface) { if (Factory::HasSSE2()) { @@ -44,7 +44,7 @@ FilterProcessing::ConvertToB8G8R8A8(SourceSurface* aSurface) return ConvertToB8G8R8A8_Scalar(aSurface); } -TemporaryRef +already_AddRefed FilterProcessing::ApplyBlending(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode) { @@ -90,7 +90,7 @@ FilterProcessing::ApplyMorphologyVertical(uint8_t* aSourceData, int32_t aSourceS } } -TemporaryRef +already_AddRefed FilterProcessing::ApplyColorMatrix(DataSourceSurface* aInput, const Matrix5x4 &aMatrix) { if (Factory::HasSSE2()) { @@ -147,7 +147,7 @@ FilterProcessing::SeparateColorChannels(DataSourceSurface* aSource, } } -TemporaryRef +already_AddRefed FilterProcessing::CombineColorChannels(DataSourceSurface* aChannel0, DataSourceSurface* aChannel1, DataSourceSurface* aChannel2, DataSourceSurface* aChannel3) { @@ -208,7 +208,7 @@ FilterProcessing::DoUnpremultiplicationCalculation(const IntSize& aSize, } } -TemporaryRef +already_AddRefed FilterProcessing::RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) { @@ -220,7 +220,7 @@ FilterProcessing::RenderTurbulence(const IntSize &aSize, const Point &aOffset, c return RenderTurbulence_Scalar(aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect); } -TemporaryRef +already_AddRefed FilterProcessing::ApplyArithmeticCombine(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4) { if (Factory::HasSSE2()) { diff --git a/gfx/2d/FilterProcessing.h b/gfx/2d/FilterProcessing.h index 253d16543a..802d791a07 100644 --- a/gfx/2d/FilterProcessing.h +++ b/gfx/2d/FilterProcessing.h @@ -31,9 +31,9 @@ public: return ((v << 8) + v + 255) >> 16; } - static TemporaryRef ExtractAlpha(DataSourceSurface* aSource); - static TemporaryRef ConvertToB8G8R8A8(SourceSurface* aSurface); - static TemporaryRef ApplyBlending(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode); + static already_AddRefed ExtractAlpha(DataSourceSurface* aSource); + static already_AddRefed ConvertToB8G8R8A8(SourceSurface* aSurface); + static already_AddRefed ApplyBlending(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode); static void ApplyMorphologyHorizontal(uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, @@ -42,14 +42,14 @@ public: uint8_t* aDestData, int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, MorphologyOperator aOperator); - static TemporaryRef ApplyColorMatrix(DataSourceSurface* aInput, const Matrix5x4 &aMatrix); + static already_AddRefed ApplyColorMatrix(DataSourceSurface* aInput, const Matrix5x4 &aMatrix); static void ApplyComposition(DataSourceSurface* aSource, DataSourceSurface* aDest, CompositeOperator aOperator); static void SeparateColorChannels(DataSourceSurface* aSource, RefPtr& aChannel0, RefPtr& aChannel1, RefPtr& aChannel2, RefPtr& aChannel3); - static TemporaryRef + static already_AddRefed CombineColorChannels(DataSourceSurface* aChannel0, DataSourceSurface* aChannel1, DataSourceSurface* aChannel2, DataSourceSurface* aChannel3); static void DoPremultiplicationCalculation(const IntSize& aSize, @@ -58,15 +58,15 @@ public: static void DoUnpremultiplicationCalculation(const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride, uint8_t* aSourceData, int32_t aSourceStride); - static TemporaryRef + static already_AddRefed RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect); - static TemporaryRef + static already_AddRefed ApplyArithmeticCombine(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4); protected: static void ExtractAlpha_Scalar(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride); - static TemporaryRef ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface); + static already_AddRefed ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface); static void ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, @@ -75,7 +75,7 @@ protected: uint8_t* aDestData, int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, MorphologyOperator aOperator); - static TemporaryRef ApplyColorMatrix_Scalar(DataSourceSurface* aInput, const Matrix5x4 &aMatrix); + static already_AddRefed ApplyColorMatrix_Scalar(DataSourceSurface* aInput, const Matrix5x4 &aMatrix); static void ApplyComposition_Scalar(DataSourceSurface* aSource, DataSourceSurface* aDest, CompositeOperator aOperator); static void SeparateColorChannels_Scalar(const IntSize &size, uint8_t* sourceData, int32_t sourceStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data, int32_t channelStride); @@ -86,16 +86,16 @@ protected: static void DoUnpremultiplicationCalculation_Scalar(const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride, uint8_t* aSourceData, int32_t aSourceStride); - static TemporaryRef + static already_AddRefed RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect); - static TemporaryRef + static already_AddRefed ApplyArithmeticCombine_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4); #ifdef USE_SSE2 static void ExtractAlpha_SSE2(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride); - static TemporaryRef ConvertToB8G8R8A8_SSE2(SourceSurface* aSurface); - static TemporaryRef ApplyBlending_SSE2(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode); + static already_AddRefed ConvertToB8G8R8A8_SSE2(SourceSurface* aSurface); + static already_AddRefed ApplyBlending_SSE2(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode); static void ApplyMorphologyHorizontal_SSE2(uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, @@ -104,7 +104,7 @@ protected: uint8_t* aDestData, int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, MorphologyOperator aOperator); - static TemporaryRef ApplyColorMatrix_SSE2(DataSourceSurface* aInput, const Matrix5x4 &aMatrix); + static already_AddRefed ApplyColorMatrix_SSE2(DataSourceSurface* aInput, const Matrix5x4 &aMatrix); static void ApplyComposition_SSE2(DataSourceSurface* aSource, DataSourceSurface* aDest, CompositeOperator aOperator); static void SeparateColorChannels_SSE2(const IntSize &size, uint8_t* sourceData, int32_t sourceStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data, int32_t channelStride); static void CombineColorChannels_SSE2(const IntSize &size, int32_t resultStride, uint8_t* resultData, int32_t channelStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data); @@ -114,10 +114,10 @@ protected: static void DoUnpremultiplicationCalculation_SSE2(const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride, uint8_t* aSourceData, int32_t aSourceStride); - static TemporaryRef + static already_AddRefed RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect); - static TemporaryRef + static already_AddRefed ApplyArithmeticCombine_SSE2(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4); #endif }; diff --git a/gfx/2d/FilterProcessingSIMD-inl.h b/gfx/2d/FilterProcessingSIMD-inl.h index 48646b40e4..40d8189260 100644 --- a/gfx/2d/FilterProcessingSIMD-inl.h +++ b/gfx/2d/FilterProcessingSIMD-inl.h @@ -12,7 +12,7 @@ namespace mozilla { namespace gfx { template -inline TemporaryRef +inline already_AddRefed ConvertToB8G8R8A8_SIMD(SourceSurface* aSurface) { IntSize size = aSurface->GetSize(); @@ -284,7 +284,7 @@ ShuffleAndPackComponents(i32x4_t bbbb1234, i32x4_t gggg1234, } template -inline TemporaryRef +inline already_AddRefed ApplyBlending_SIMD(DataSourceSurface* aInput1, DataSourceSurface* aInput2) { IntSize size = aInput1->GetSize(); @@ -338,7 +338,7 @@ ApplyBlending_SIMD(DataSourceSurface* aInput1, DataSourceSurface* aInput2) } template -static TemporaryRef +static already_AddRefed ApplyBlending_SIMD(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode) { @@ -509,7 +509,7 @@ ColorMatrixMultiply(i16x8_t p, i16x8_t rows_bg, i16x8_t rows_ra, const i32x4_t& } template -static TemporaryRef +static already_AddRefed ApplyColorMatrix_SIMD(DataSourceSurface* aInput, const Matrix5x4 &aMatrix) { IntSize size = aInput->GetSize(); @@ -953,7 +953,7 @@ DoUnpremultiplicationCalculation_SIMD(const IntSize& aSize, } template -static TemporaryRef +static already_AddRefed RenderTurbulence_SIMD(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) { @@ -1013,7 +1013,7 @@ ArithmeticCombineTwoPixels(i16x8_t in1, i16x8_t in2, } template -static TemporaryRef +static already_AddRefed ApplyArithmeticCombine_SIMD(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4) { diff --git a/gfx/2d/FilterProcessingSSE2.cpp b/gfx/2d/FilterProcessingSSE2.cpp index ca1d2dbef7..9cd0e7bc7d 100644 --- a/gfx/2d/FilterProcessingSSE2.cpp +++ b/gfx/2d/FilterProcessingSSE2.cpp @@ -20,13 +20,13 @@ FilterProcessing::ExtractAlpha_SSE2(const IntSize& size, uint8_t* sourceData, in ExtractAlpha_SIMD<__m128i>(size, sourceData, sourceStride, alphaData, alphaStride); } -TemporaryRef +already_AddRefed FilterProcessing::ConvertToB8G8R8A8_SSE2(SourceSurface* aSurface) { return ConvertToB8G8R8A8_SIMD<__m128i>(aSurface); } -TemporaryRef +already_AddRefed FilterProcessing::ApplyBlending_SSE2(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode) { @@ -53,7 +53,7 @@ FilterProcessing::ApplyMorphologyVertical_SSE2(uint8_t* aSourceData, int32_t aSo aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius, aOp); } -TemporaryRef +already_AddRefed FilterProcessing::ApplyColorMatrix_SSE2(DataSourceSurface* aInput, const Matrix5x4 &aMatrix) { return ApplyColorMatrix_SIMD<__m128i,__m128i,__m128i>(aInput, aMatrix); @@ -95,14 +95,14 @@ FilterProcessing::DoUnpremultiplicationCalculation_SSE2( DoUnpremultiplicationCalculation_SIMD<__m128i,__m128i>(aSize, aTargetData, aTargetStride, aSourceData, aSourceStride); } -TemporaryRef +already_AddRefed FilterProcessing::RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) { return RenderTurbulence_SIMD<__m128,__m128i,__m128i>(aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect); } -TemporaryRef +already_AddRefed FilterProcessing::ApplyArithmeticCombine_SSE2(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4) { return ApplyArithmeticCombine_SIMD<__m128i,__m128i,__m128i>(aInput1, aInput2, aK1, aK2, aK3, aK4); diff --git a/gfx/2d/FilterProcessingScalar.cpp b/gfx/2d/FilterProcessingScalar.cpp index 3a38118eed..ca8074bd94 100644 --- a/gfx/2d/FilterProcessingScalar.cpp +++ b/gfx/2d/FilterProcessingScalar.cpp @@ -23,7 +23,7 @@ FilterProcessing::ExtractAlpha_Scalar(const IntSize& size, uint8_t* sourceData, } } -TemporaryRef +already_AddRefed FilterProcessing::ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface) { return ConvertToB8G8R8A8_SIMD(aSurface); @@ -134,7 +134,7 @@ FilterProcessing::ApplyMorphologyVertical_Scalar(uint8_t* aSourceData, int32_t a } } -TemporaryRef +already_AddRefed FilterProcessing::ApplyColorMatrix_Scalar(DataSourceSurface* aInput, const Matrix5x4 &aMatrix) { return ApplyColorMatrix_SIMD(aInput, aMatrix); @@ -226,7 +226,7 @@ FilterProcessing::DoUnpremultiplicationCalculation_Scalar( } } -TemporaryRef +already_AddRefed FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) { @@ -234,7 +234,7 @@ FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOf aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect); } -TemporaryRef +already_AddRefed FilterProcessing::ApplyArithmeticCombine_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4) { return ApplyArithmeticCombine_SIMD(aInput1, aInput2, aK1, aK2, aK3, aK4); diff --git a/gfx/2d/HelpersD2D.h b/gfx/2d/HelpersD2D.h index a25f2cf2f5..80fa8c3e21 100644 --- a/gfx/2d/HelpersD2D.h +++ b/gfx/2d/HelpersD2D.h @@ -385,7 +385,7 @@ DWriteGlyphRunFromGlyphs(const GlyphBuffer &aGlyphs, ScaledFontDWrite *aFont, Au run->isSideways = FALSE; } -static inline TemporaryRef +static inline already_AddRefed ConvertRectToGeometry(const D2D1_RECT_F& aRect) { RefPtr rectGeom; @@ -393,7 +393,7 @@ ConvertRectToGeometry(const D2D1_RECT_F& aRect) return rectGeom.forget(); } -static inline TemporaryRef +static inline already_AddRefed GetTransformedGeometry(ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform) { RefPtr tmpGeometry; @@ -406,7 +406,7 @@ GetTransformedGeometry(ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTrans return tmpGeometry.forget(); } -static inline TemporaryRef +static inline already_AddRefed IntersectGeometry(ID2D1Geometry *aGeometryA, ID2D1Geometry *aGeometryB) { RefPtr pathGeom; @@ -419,7 +419,7 @@ IntersectGeometry(ID2D1Geometry *aGeometryA, ID2D1Geometry *aGeometryB) return pathGeom.forget(); } -static inline TemporaryRef +static inline already_AddRefed CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions) { RefPtr style; @@ -499,7 +499,7 @@ CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions) // This creates a (partially) uploaded bitmap for a DataSourceSurface. It // uploads the minimum requirement and possibly downscales. It adjusts the // input Matrix to compensate. -static inline TemporaryRef +static inline already_AddRefed CreatePartialBitmapForSurface(DataSourceSurface *aSurface, const Matrix &aDestinationTransform, const IntSize &aDestinationSize, ExtendMode aExtendMode, Matrix &aSourceTransform, ID2D1RenderTarget *aRT, diff --git a/gfx/2d/MacIOSurface.cpp b/gfx/2d/MacIOSurface.cpp index 8d0696685c..8badcf6e35 100644 --- a/gfx/2d/MacIOSurface.cpp +++ b/gfx/2d/MacIOSurface.cpp @@ -285,7 +285,7 @@ MacIOSurface::~MacIOSurface() { CFRelease(mIOSurfacePtr); } -TemporaryRef MacIOSurface::CreateIOSurface(int aWidth, int aHeight, +already_AddRefed MacIOSurface::CreateIOSurface(int aWidth, int aHeight, double aContentsScaleFactor, bool aHasAlpha) { if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0) @@ -338,7 +338,7 @@ TemporaryRef MacIOSurface::CreateIOSurface(int aWidth, int aHeight return ioSurface.forget(); } -TemporaryRef MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID, +already_AddRefed MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID, double aContentsScaleFactor, bool aHasAlpha) { if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0) @@ -435,7 +435,7 @@ using mozilla::gfx::SourceSurfaceRawData; using mozilla::gfx::IntSize; using mozilla::gfx::SurfaceFormat; -TemporaryRef +already_AddRefed MacIOSurface::GetAsSurface() { Lock(); size_t bytesPerRow = GetBytesPerRow(); @@ -499,7 +499,7 @@ CGImageRef MacIOSurface::CreateImageFromIOSurfaceContext(CGContextRef aContext) return MacIOSurfaceLib::IOSurfaceContextCreateImage(aContext); } -TemporaryRef MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext, +already_AddRefed MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext, double aContentsScaleFactor, bool aHasAlpha) { if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0) diff --git a/gfx/2d/MacIOSurface.h b/gfx/2d/MacIOSurface.h index 8cf35872ee..ee3d32b470 100644 --- a/gfx/2d/MacIOSurface.h +++ b/gfx/2d/MacIOSurface.h @@ -70,11 +70,11 @@ public: // of the MacIOSurface instance. // MacIOSurface holds a reference to the corresponding IOSurface. - static mozilla::TemporaryRef CreateIOSurface(int aWidth, int aHeight, + static already_AddRefed CreateIOSurface(int aWidth, int aHeight, double aContentsScaleFactor = 1.0, bool aHasAlpha = true); static void ReleaseIOSurface(MacIOSurface *aIOSurface); - static mozilla::TemporaryRef LookupSurface(IOSurfaceID aSurfaceID, + static already_AddRefed LookupSurface(IOSurfaceID aSurfaceID, double aContentsScaleFactor = 1.0, bool aHasAlpha = true); @@ -104,12 +104,12 @@ public: // We would like to forward declare NSOpenGLContext, but it is an @interface // and this file is also used from c++, so we use a void *. CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt); - mozilla::TemporaryRef GetAsSurface(); + already_AddRefed GetAsSurface(); CGContextRef CreateIOSurfaceContext(); // FIXME This doesn't really belong here static CGImageRef CreateImageFromIOSurfaceContext(CGContextRef aContext); - static mozilla::TemporaryRef IOSurfaceContextGetSurface(CGContextRef aContext, + static already_AddRefed IOSurfaceContextGetSurface(CGContextRef aContext, double aContentsScaleFactor = 1.0, bool aHasAlpha = true); static size_t GetMaxWidth(); diff --git a/gfx/2d/PathCG.cpp b/gfx/2d/PathCG.cpp index 6d5dfa36e6..aec62c7416 100644 --- a/gfx/2d/PathCG.cpp +++ b/gfx/2d/PathCG.cpp @@ -9,6 +9,10 @@ #include "Logging.h" #include "PathHelpers.h" +#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5) +CGPathRef CGContextCopyPath(CGContextRef c); +#endif + namespace mozilla { namespace gfx { @@ -127,13 +131,13 @@ PathBuilderCG::EnsureActive(const Point &aPoint) { } -TemporaryRef +already_AddRefed PathBuilderCG::Finish() { return MakeAndAddRef(mCGPath, mFillRule); } -TemporaryRef +already_AddRefed PathCG::CopyToBuilder(FillRule aFillRule) const { CGMutablePathRef path = CGPathCreateMutableCopy(mPath); @@ -142,7 +146,7 @@ PathCG::CopyToBuilder(FillRule aFillRule) const -TemporaryRef +already_AddRefed PathCG::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const { // 10.7 adds CGPathCreateMutableCopyByTransformingPath it might be faster than doing diff --git a/gfx/2d/PathCG.h b/gfx/2d/PathCG.h index 9598edb875..fc0ce7b725 100644 --- a/gfx/2d/PathCG.h +++ b/gfx/2d/PathCG.h @@ -45,7 +45,7 @@ public: Float aEndAngle, bool aAntiClockwise = false); virtual Point CurrentPoint() const; - virtual TemporaryRef Finish(); + virtual already_AddRefed Finish(); virtual BackendType GetBackendType() const { return BackendType::COREGRAPHICS; } @@ -77,8 +77,8 @@ public: // are compatible with BackendType::COREGRAPHICS_ACCELERATED backend. virtual BackendType GetBackendType() const { return BackendType::COREGRAPHICS; } - virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, + virtual already_AddRefed CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule = FillRule::FILL_WINDING) const; virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const; diff --git a/gfx/2d/PathCairo.cpp b/gfx/2d/PathCairo.cpp index b0c9f8b41b..d85119f684 100644 --- a/gfx/2d/PathCairo.cpp +++ b/gfx/2d/PathCairo.cpp @@ -122,7 +122,7 @@ PathBuilderCairo::CurrentPoint() const return mCurrentPoint; } -TemporaryRef +already_AddRefed PathBuilderCairo::Finish() { return MakeAndAddRef(mFillRule, mPathData, mCurrentPoint); @@ -159,7 +159,7 @@ PathCairo::~PathCairo() } } -TemporaryRef +already_AddRefed PathCairo::CopyToBuilder(FillRule aFillRule) const { RefPtr builder = new PathBuilderCairo(aFillRule); @@ -170,7 +170,7 @@ PathCairo::CopyToBuilder(FillRule aFillRule) const return builder.forget(); } -TemporaryRef +already_AddRefed PathCairo::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const { RefPtr builder = new PathBuilderCairo(aFillRule); diff --git a/gfx/2d/PathCairo.h b/gfx/2d/PathCairo.h index 898181242c..099f076fea 100644 --- a/gfx/2d/PathCairo.h +++ b/gfx/2d/PathCairo.h @@ -33,7 +33,7 @@ public: virtual void Arc(const Point &aOrigin, float aRadius, float aStartAngle, float aEndAngle, bool aAntiClockwise = false); virtual Point CurrentPoint() const; - virtual TemporaryRef Finish(); + virtual already_AddRefed Finish(); virtual BackendType GetBackendType() const { return BackendType::CAIRO; } @@ -58,8 +58,8 @@ public: virtual BackendType GetBackendType() const { return BackendType::CAIRO; } - virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, + virtual already_AddRefed CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule = FillRule::FILL_WINDING) const; virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const; diff --git a/gfx/2d/PathD2D.cpp b/gfx/2d/PathD2D.cpp index bd20d31899..8cb802b391 100644 --- a/gfx/2d/PathD2D.cpp +++ b/gfx/2d/PathD2D.cpp @@ -290,7 +290,7 @@ PathBuilderD2D::EnsureActive(const Point &aPoint) } } -TemporaryRef +already_AddRefed PathBuilderD2D::Finish() { if (mFigureActive) { @@ -306,13 +306,13 @@ PathBuilderD2D::Finish() return MakeAndAddRef(mGeometry, mFigureActive, mCurrentPoint, mFillRule, mBackendType); } -TemporaryRef +already_AddRefed PathD2D::CopyToBuilder(FillRule aFillRule) const { return TransformedCopyToBuilder(Matrix(), aFillRule); } -TemporaryRef +already_AddRefed PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const { RefPtr path; diff --git a/gfx/2d/PathD2D.h b/gfx/2d/PathD2D.h index 3afd82783a..31977bc50b 100644 --- a/gfx/2d/PathD2D.h +++ b/gfx/2d/PathD2D.h @@ -41,7 +41,7 @@ public: Float aEndAngle, bool aAntiClockwise = false); virtual Point CurrentPoint() const; - virtual TemporaryRef Finish(); + virtual already_AddRefed Finish(); virtual BackendType GetBackendType() const { return mBackendType; } @@ -77,8 +77,8 @@ public: virtual BackendType GetBackendType() const { return mBackendType; } - virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, + virtual already_AddRefed CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule = FillRule::FILL_WINDING) const; virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const; diff --git a/gfx/2d/PathHelpers.h b/gfx/2d/PathHelpers.h index f3376c09fb..e55049d732 100644 --- a/gfx/2d/PathHelpers.h +++ b/gfx/2d/PathHelpers.h @@ -167,7 +167,7 @@ GFX2D_API void AppendRectToPath(PathBuilder* aPathBuilder, const Rect& aRect, bool aDrawClockwise = true); -inline TemporaryRef MakePathForRect(const DrawTarget& aDrawTarget, +inline already_AddRefed MakePathForRect(const DrawTarget& aDrawTarget, const Rect& aRect, bool aDrawClockwise = true) { @@ -252,7 +252,7 @@ GFX2D_API void AppendRoundedRectToPath(PathBuilder* aPathBuilder, const RectCornerRadii& aRadii, bool aDrawClockwise = true); -inline TemporaryRef MakePathForRoundedRect(const DrawTarget& aDrawTarget, +inline already_AddRefed MakePathForRoundedRect(const DrawTarget& aDrawTarget, const Rect& aRect, const RectCornerRadii& aRadii, bool aDrawClockwise = true) @@ -273,7 +273,7 @@ GFX2D_API void AppendEllipseToPath(PathBuilder* aPathBuilder, const Point& aCenter, const Size& aDimensions); -inline TemporaryRef MakePathForEllipse(const DrawTarget& aDrawTarget, +inline already_AddRefed MakePathForEllipse(const DrawTarget& aDrawTarget, const Point& aCenter, const Size& aDimensions) { diff --git a/gfx/2d/PathRecording.cpp b/gfx/2d/PathRecording.cpp index ad6700db33..243941be39 100644 --- a/gfx/2d/PathRecording.cpp +++ b/gfx/2d/PathRecording.cpp @@ -69,7 +69,7 @@ PathBuilderRecording::CurrentPoint() const return mPathBuilder->CurrentPoint(); } -TemporaryRef +already_AddRefed PathBuilderRecording::Finish() { RefPtr path = mPathBuilder->Finish(); @@ -84,7 +84,7 @@ PathRecording::~PathRecording() } } -TemporaryRef +already_AddRefed PathRecording::CopyToBuilder(FillRule aFillRule) const { RefPtr pathBuilder = mPath->CopyToBuilder(aFillRule); @@ -93,7 +93,7 @@ PathRecording::CopyToBuilder(FillRule aFillRule) const return recording.forget(); } -TemporaryRef +already_AddRefed PathRecording::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const { RefPtr pathBuilder = mPath->TransformedCopyToBuilder(aTransform, aFillRule); diff --git a/gfx/2d/PathRecording.h b/gfx/2d/PathRecording.h index 7fde43ea96..7df80399f9 100644 --- a/gfx/2d/PathRecording.h +++ b/gfx/2d/PathRecording.h @@ -70,7 +70,7 @@ public: */ virtual Point CurrentPoint() const; - virtual TemporaryRef Finish(); + virtual already_AddRefed Finish(); virtual BackendType GetBackendType() const { return BackendType::RECORDING; } @@ -94,8 +94,8 @@ public: ~PathRecording(); virtual BackendType GetBackendType() const { return BackendType::RECORDING; } - virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, + virtual already_AddRefed CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule = FillRule::FILL_WINDING) const; virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const { return mPath->ContainsPoint(aPoint, aTransform); } diff --git a/gfx/2d/PathSkia.cpp b/gfx/2d/PathSkia.cpp index a3345881a7..e01d452a4b 100644 --- a/gfx/2d/PathSkia.cpp +++ b/gfx/2d/PathSkia.cpp @@ -102,7 +102,7 @@ PathBuilderSkia::CurrentPoint() const return Point(SkScalarToFloat(point.fX), SkScalarToFloat(point.fY)); } -TemporaryRef +already_AddRefed PathBuilderSkia::Finish() { return MakeAndAddRef(mPath, mFillRule); @@ -114,13 +114,13 @@ PathBuilderSkia::AppendPath(const SkPath &aPath) mPath.addPath(aPath); } -TemporaryRef +already_AddRefed PathSkia::CopyToBuilder(FillRule aFillRule) const { return TransformedCopyToBuilder(Matrix(), aFillRule); } -TemporaryRef +already_AddRefed PathSkia::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const { return MakeAndAddRef(aTransform, mPath, aFillRule); diff --git a/gfx/2d/PathSkia.h b/gfx/2d/PathSkia.h index 8881658605..8b49da0de9 100644 --- a/gfx/2d/PathSkia.h +++ b/gfx/2d/PathSkia.h @@ -32,7 +32,7 @@ public: virtual void Arc(const Point &aOrigin, float aRadius, float aStartAngle, float aEndAngle, bool aAntiClockwise = false); virtual Point CurrentPoint() const; - virtual TemporaryRef Finish(); + virtual already_AddRefed Finish(); void AppendPath(const SkPath &aPath); @@ -58,8 +58,8 @@ public: virtual BackendType GetBackendType() const { return BackendType::SKIA; } - virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, + virtual already_AddRefed CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual already_AddRefed TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule = FillRule::FILL_WINDING) const; virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const; diff --git a/gfx/2d/QuartzSupport.mm b/gfx/2d/QuartzSupport.mm index cdefa0557c..74589d93d3 100644 --- a/gfx/2d/QuartzSupport.mm +++ b/gfx/2d/QuartzSupport.mm @@ -26,7 +26,6 @@ @end using mozilla::RefPtr; -using mozilla::TemporaryRef; CGColorSpaceRef CreateSystemColorSpace() { CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID()); diff --git a/gfx/2d/RadialGradientEffectD2D1.cpp b/gfx/2d/RadialGradientEffectD2D1.cpp index e53a3f8554..5301be3442 100644 --- a/gfx/2d/RadialGradientEffectD2D1.cpp +++ b/gfx/2d/RadialGradientEffectD2D1.cpp @@ -309,7 +309,7 @@ RadialGradientEffectD2D1::SetStopCollection(IUnknown *aStopCollection) return E_INVALIDARG; } -TemporaryRef +already_AddRefed RadialGradientEffectD2D1::CreateGradientTexture() { std::vector rawStops; diff --git a/gfx/2d/RadialGradientEffectD2D1.h b/gfx/2d/RadialGradientEffectD2D1.h index ac8d433dcd..a0099bd249 100644 --- a/gfx/2d/RadialGradientEffectD2D1.h +++ b/gfx/2d/RadialGradientEffectD2D1.h @@ -79,7 +79,7 @@ public: IUnknown *GetStopCollection() const { return mStopCollection; } private: - TemporaryRef CreateGradientTexture(); + already_AddRefed CreateGradientTexture(); RadialGradientEffectD2D1(); diff --git a/gfx/2d/SVGTurbulenceRenderer-inl.h b/gfx/2d/SVGTurbulenceRenderer-inl.h index 2ea92c6019..7b18903e86 100644 --- a/gfx/2d/SVGTurbulenceRenderer-inl.h +++ b/gfx/2d/SVGTurbulenceRenderer-inl.h @@ -17,7 +17,7 @@ public: SVGTurbulenceRenderer(const Size &aBaseFrequency, int32_t aSeed, int aNumOctaves, const Rect &aTileRect); - TemporaryRef Render(const IntSize &aSize, const Point &aOffset) const; + already_AddRefed Render(const IntSize &aSize, const Point &aOffset) const; private: /* The turbulence calculation code is an adapted version of what @@ -327,7 +327,7 @@ SVGTurbulenceRenderer::EquivalentNonNegativ } template -TemporaryRef +already_AddRefed SVGTurbulenceRenderer::Render(const IntSize &aSize, const Point &aOffset) const { RefPtr target = diff --git a/gfx/2d/ScaledFontBase.cpp b/gfx/2d/ScaledFontBase.cpp index dc00cb629b..228bd3ad1e 100644 --- a/gfx/2d/ScaledFontBase.cpp +++ b/gfx/2d/ScaledFontBase.cpp @@ -74,7 +74,7 @@ ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer) } #endif -TemporaryRef +already_AddRefed ScaledFontBase::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) { #ifdef USE_SKIA diff --git a/gfx/2d/ScaledFontBase.h b/gfx/2d/ScaledFontBase.h index 985101ca42..0cecd2fc2a 100644 --- a/gfx/2d/ScaledFontBase.h +++ b/gfx/2d/ScaledFontBase.h @@ -33,7 +33,7 @@ public: explicit ScaledFontBase(Float aSize); virtual ~ScaledFontBase(); - virtual TemporaryRef GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); + virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint); diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index e1e1b7137f..85873da933 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -306,7 +306,7 @@ ScaledFontDWrite::ScaledFontDWrite(uint8_t *aData, uint32_t aSize, } } -TemporaryRef +already_AddRefed ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) { if (aTarget->GetBackendType() != BackendType::DIRECT2D && aTarget->GetBackendType() != BackendType::DIRECT2D1_1) { diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index 941babed17..a517ab55db 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -26,7 +26,7 @@ public: virtual FontType GetType() const { return FontType::DWRITE; } - virtual TemporaryRef GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); + virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint); void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink); diff --git a/gfx/2d/ScaledFontMac.cpp b/gfx/2d/ScaledFontMac.cpp index f53895d52f..24f2fa8c0e 100644 --- a/gfx/2d/ScaledFontMac.cpp +++ b/gfx/2d/ScaledFontMac.cpp @@ -76,7 +76,7 @@ SkTypeface* ScaledFontMac::GetSkTypeface() // Note: cairo dlsyms it. We could do that but maybe it's // safe just to use? -TemporaryRef +already_AddRefed ScaledFontMac::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) { if (aTarget->GetBackendType() == BackendType::COREGRAPHICS || diff --git a/gfx/2d/ScaledFontMac.h b/gfx/2d/ScaledFontMac.h index 03c68add66..98fd2c1d49 100644 --- a/gfx/2d/ScaledFontMac.h +++ b/gfx/2d/ScaledFontMac.h @@ -25,7 +25,7 @@ public: #ifdef USE_SKIA virtual SkTypeface* GetSkTypeface(); #endif - virtual TemporaryRef GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); + virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint); virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton); diff --git a/gfx/2d/SourceSurfaceCG.cpp b/gfx/2d/SourceSurfaceCG.cpp index d2f785ab57..2a2c73402f 100644 --- a/gfx/2d/SourceSurfaceCG.cpp +++ b/gfx/2d/SourceSurfaceCG.cpp @@ -36,7 +36,7 @@ SourceSurfaceCG::GetFormat() const return mFormat; } -TemporaryRef +already_AddRefed SourceSurfaceCG::GetDataSurface() { //XXX: we should be more disciplined about who takes a reference and where diff --git a/gfx/2d/SourceSurfaceCG.h b/gfx/2d/SourceSurfaceCG.h index fccf57c383..f9b2a658ef 100644 --- a/gfx/2d/SourceSurfaceCG.h +++ b/gfx/2d/SourceSurfaceCG.h @@ -43,7 +43,7 @@ public: virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_IMAGE; } virtual IntSize GetSize() const; virtual SurfaceFormat GetFormat() const; - virtual TemporaryRef GetDataSurface(); + virtual already_AddRefed GetDataSurface(); CGImageRef GetImage() { return mImage; } @@ -115,7 +115,7 @@ public: virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_CGCONTEXT; } virtual IntSize GetSize() const; virtual SurfaceFormat GetFormat() const { return mFormat; } - virtual TemporaryRef GetDataSurface() + virtual already_AddRefed GetDataSurface() { // This call to DrawTargetWillChange() is needed to make a local copy of // the data from mDrawTarget. If we don't do that, the data can end up diff --git a/gfx/2d/SourceSurfaceCairo.cpp b/gfx/2d/SourceSurfaceCairo.cpp index 93bdc9f27b..2afae57ad0 100644 --- a/gfx/2d/SourceSurfaceCairo.cpp +++ b/gfx/2d/SourceSurfaceCairo.cpp @@ -58,7 +58,7 @@ SourceSurfaceCairo::GetFormat() const return mFormat; } -TemporaryRef +already_AddRefed SourceSurfaceCairo::GetDataSurface() { RefPtr dataSurf; diff --git a/gfx/2d/SourceSurfaceCairo.h b/gfx/2d/SourceSurfaceCairo.h index a9390e7598..1466e9ac81 100644 --- a/gfx/2d/SourceSurfaceCairo.h +++ b/gfx/2d/SourceSurfaceCairo.h @@ -30,7 +30,7 @@ public: virtual SurfaceType GetType() const { return SurfaceType::CAIRO; } virtual IntSize GetSize() const; virtual SurfaceFormat GetFormat() const; - virtual TemporaryRef GetDataSurface(); + virtual already_AddRefed GetDataSurface(); cairo_surface_t* GetSurface() const; diff --git a/gfx/2d/SourceSurfaceD2D.cpp b/gfx/2d/SourceSurfaceD2D.cpp index 538f0d2bd8..438cdace2c 100644 --- a/gfx/2d/SourceSurfaceD2D.cpp +++ b/gfx/2d/SourceSurfaceD2D.cpp @@ -40,7 +40,7 @@ SourceSurfaceD2D::IsValid() const return mDevice == Factory::GetDirect3D10Device(); } -TemporaryRef +already_AddRefed SourceSurfaceD2D::GetDataSurface() { RefPtr result = new DataSourceSurfaceD2D(this); diff --git a/gfx/2d/SourceSurfaceD2D.h b/gfx/2d/SourceSurfaceD2D.h index c2622d76c3..22ee5f125f 100644 --- a/gfx/2d/SourceSurfaceD2D.h +++ b/gfx/2d/SourceSurfaceD2D.h @@ -27,7 +27,7 @@ public: virtual SurfaceFormat GetFormat() const; virtual bool IsValid() const; - virtual TemporaryRef GetDataSurface(); + virtual already_AddRefed GetDataSurface(); ID2D1Bitmap *GetBitmap() { return mBitmap; } diff --git a/gfx/2d/SourceSurfaceD2D1.cpp b/gfx/2d/SourceSurfaceD2D1.cpp index 1f26d26b75..f8f108c217 100644 --- a/gfx/2d/SourceSurfaceD2D1.cpp +++ b/gfx/2d/SourceSurfaceD2D1.cpp @@ -34,7 +34,7 @@ SourceSurfaceD2D1::IsValid() const return mDevice == Factory::GetD2D1Device(); } -TemporaryRef +already_AddRefed SourceSurfaceD2D1::GetDataSurface() { HRESULT hr; diff --git a/gfx/2d/SourceSurfaceD2D1.h b/gfx/2d/SourceSurfaceD2D1.h index 1ecf314499..8cb4c7c878 100644 --- a/gfx/2d/SourceSurfaceD2D1.h +++ b/gfx/2d/SourceSurfaceD2D1.h @@ -30,7 +30,7 @@ public: virtual IntSize GetSize() const { return mSize; } virtual SurfaceFormat GetFormat() const { return mFormat; } virtual bool IsValid() const; - virtual TemporaryRef GetDataSurface(); + virtual already_AddRefed GetDataSurface(); ID2D1Image *GetImage() { return mImage; } diff --git a/gfx/2d/SourceSurfaceD2DTarget.cpp b/gfx/2d/SourceSurfaceD2DTarget.cpp index 3cc3bbecbc..b2145747cd 100644 --- a/gfx/2d/SourceSurfaceD2DTarget.cpp +++ b/gfx/2d/SourceSurfaceD2DTarget.cpp @@ -50,7 +50,7 @@ SourceSurfaceD2DTarget::GetFormat() const return mFormat; } -TemporaryRef +already_AddRefed SourceSurfaceD2DTarget::GetDataSurface() { RefPtr dataSurf = diff --git a/gfx/2d/SourceSurfaceD2DTarget.h b/gfx/2d/SourceSurfaceD2DTarget.h index a66505047a..82b5b20778 100644 --- a/gfx/2d/SourceSurfaceD2DTarget.h +++ b/gfx/2d/SourceSurfaceD2DTarget.h @@ -27,7 +27,7 @@ public: virtual SurfaceType GetType() const { return SurfaceType::D2D1_DRAWTARGET; } virtual IntSize GetSize() const; virtual SurfaceFormat GetFormat() const; - virtual TemporaryRef GetDataSurface(); + virtual already_AddRefed GetDataSurface(); virtual void *GetNativeSurface(NativeSurfaceType aType); DrawTargetD2D* GetDT() { return mDrawTarget; } diff --git a/gfx/2d/SourceSurfaceDual.h b/gfx/2d/SourceSurfaceDual.h index aaa85dcc86..7c44bbc0b6 100644 --- a/gfx/2d/SourceSurfaceDual.h +++ b/gfx/2d/SourceSurfaceDual.h @@ -28,7 +28,7 @@ public: virtual SurfaceFormat GetFormat() const { return mA->GetFormat(); } /* Readback from this surface type is not supported! */ - virtual TemporaryRef GetDataSurface() { return nullptr; } + virtual already_AddRefed GetDataSurface() { return nullptr; } private: friend class DualSurface; friend class DualPattern; diff --git a/gfx/gl/AndroidSurfaceTexture.cpp b/gfx/gl/AndroidSurfaceTexture.cpp index bd612c7474..0cae4a9195 100644 --- a/gfx/gl/AndroidSurfaceTexture.cpp +++ b/gfx/gl/AndroidSurfaceTexture.cpp @@ -36,13 +36,13 @@ IsSTSupported() return AndroidBridge::Bridge()->GetAPIVersion() >= 14; /* ICS */ } -TemporaryRef +already_AddRefed AndroidSurfaceTexture::Create() { return Create(nullptr, 0); } -TemporaryRef +already_AddRefed AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture) { if (!IsSTSupported()) { diff --git a/gfx/gl/AndroidSurfaceTexture.h b/gfx/gl/AndroidSurfaceTexture.h index 00e73571f8..ffda4325a5 100644 --- a/gfx/gl/AndroidSurfaceTexture.h +++ b/gfx/gl/AndroidSurfaceTexture.h @@ -43,13 +43,13 @@ public: // The SurfaceTexture is created in an attached state. This method requires // Android Ice Cream Sandwich. - static TemporaryRef Create(GLContext* aGLContext, GLuint aTexture); + static already_AddRefed Create(GLContext* aGLContext, GLuint aTexture); // Here the SurfaceTexture will be created in a detached state. You must call // Attach() with the GLContext you wish to composite with. It must be done // on the thread where that GLContext is current. This method requires // Android Jelly Bean. - static TemporaryRef Create(); + static already_AddRefed Create(); static AndroidSurfaceTexture* Find(int id); diff --git a/gfx/gl/GLReadTexImageHelper.cpp b/gfx/gl/GLReadTexImageHelper.cpp index 48705a5949..31fe011a65 100644 --- a/gfx/gl/GLReadTexImageHelper.cpp +++ b/gfx/gl/GLReadTexImageHelper.cpp @@ -532,7 +532,7 @@ ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest) #endif } -static TemporaryRef +static already_AddRefed YInvertImageSurface(DataSourceSurface* aSurf) { RefPtr temp = @@ -568,7 +568,7 @@ YInvertImageSurface(DataSourceSurface* aSurf) return temp.forget(); } -TemporaryRef +already_AddRefed ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFormat) { gl->MakeCurrent(); @@ -617,7 +617,7 @@ ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFo break; \ } -TemporaryRef +already_AddRefed GLReadTexImageHelper::ReadTexImage(GLuint aTextureId, GLenum aTextureTarget, const gfx::IntSize& aSize, diff --git a/gfx/gl/GLReadTexImageHelper.h b/gfx/gl/GLReadTexImageHelper.h index 53ce411893..12f8fe7cba 100644 --- a/gfx/gl/GLReadTexImageHelper.h +++ b/gfx/gl/GLReadTexImageHelper.h @@ -31,7 +31,7 @@ bool GetActualReadFormats(GLContext* gl, void ReadPixelsIntoDataSurface(GLContext* aGL, gfx::DataSourceSurface* aSurface); -TemporaryRef +already_AddRefed ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat); class GLReadTexImageHelper final @@ -64,7 +64,7 @@ public: * NOTE: aShaderProgram is really mozilla::layers::ShaderProgramType. It is * passed as int to eliminate including LayerManagerOGLProgram.h here. */ - TemporaryRef ReadTexImage(GLuint aTextureId, + already_AddRefed ReadTexImage(GLuint aTextureId, GLenum aTextureTarget, const gfx::IntSize& aSize, /* ShaderProgramType */ int aShaderProgram, diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp index 8dd8f2f5a3..740f4d492b 100644 --- a/gfx/gl/GLTextureImage.cpp +++ b/gfx/gl/GLTextureImage.cpp @@ -184,7 +184,7 @@ BasicTextureImage::BindTexture(GLenum aTextureUnit) mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); } -TemporaryRef +already_AddRefed BasicTextureImage::GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt) { return gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO, aSize, aFmt); diff --git a/gfx/gl/GLTextureImage.h b/gfx/gl/GLTextureImage.h index d313c5dcc7..5458b2c4ad 100644 --- a/gfx/gl/GLTextureImage.h +++ b/gfx/gl/GLTextureImage.h @@ -279,7 +279,7 @@ public: virtual void EndUpdate(); virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0)); virtual GLuint GetTextureID() { return mTexture; } - virtual TemporaryRef + virtual already_AddRefed GetDrawTargetForUpdate(const gfx::IntSize& aSize, gfx::SurfaceFormat aFmt); virtual void MarkValid() { mTextureState = Valid; } diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp index b6725cd370..d3e9e7cb6e 100644 --- a/gfx/gl/SharedSurface.cpp +++ b/gfx/gl/SharedSurface.cpp @@ -336,7 +336,7 @@ SurfaceFactory::NewSharedSurface(const gfx::IntSize& size) return CreateShared(size); } -TemporaryRef +already_AddRefed SurfaceFactory::NewShSurfHandle(const gfx::IntSize& size) { auto surf = NewSharedSurface(size); diff --git a/gfx/gl/SharedSurface.h b/gfx/gl/SharedSurface.h index eb3fcc4158..bf62d41fcc 100644 --- a/gfx/gl/SharedSurface.h +++ b/gfx/gl/SharedSurface.h @@ -238,7 +238,7 @@ protected: public: UniquePtr NewSharedSurface(const gfx::IntSize& size); - TemporaryRef NewShSurfHandle(const gfx::IntSize& size); + already_AddRefed NewShSurfHandle(const gfx::IntSize& size); // Auto-deletes surfs of the wrong type. void Recycle(UniquePtr surf); diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 9ad5ea22bf..6b207ecf92 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -8,7 +8,7 @@ #include "Units.h" // for ScreenPoint #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted +#include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted #include "mozilla/gfx/Point.h" // for IntSize, Point #include "mozilla/gfx/Rect.h" // for Rect, IntRect #include "mozilla/gfx/Types.h" // for Float @@ -193,7 +193,7 @@ public: { } - virtual TemporaryRef CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0; + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0; virtual bool Initialize() = 0; virtual void Destroy() = 0; @@ -255,7 +255,7 @@ public: * Creates a Surface that can be used as a rendering target by this * compositor. */ - virtual TemporaryRef + virtual already_AddRefed CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0; /** @@ -265,7 +265,7 @@ public: * * aSourcePoint specifies the point in aSource to copy data from. */ - virtual TemporaryRef + virtual already_AddRefed CreateRenderTargetFromSource(const gfx::IntRect& aRect, const CompositingRenderTarget* aSource, const gfx::IntPoint& aSourcePoint) = 0; diff --git a/gfx/layers/D3D11ShareHandleImage.cpp b/gfx/layers/D3D11ShareHandleImage.cpp index fc8e694539..bfc342acc1 100644 --- a/gfx/layers/D3D11ShareHandleImage.cpp +++ b/gfx/layers/D3D11ShareHandleImage.cpp @@ -52,7 +52,7 @@ D3D11ShareHandleImage::GetTextureClient(CompositableClient* aClient) return mTextureClient; } -TemporaryRef +already_AddRefed D3D11ShareHandleImage::GetAsSourceSurface() { if (!mTexture) { diff --git a/gfx/layers/D3D11ShareHandleImage.h b/gfx/layers/D3D11ShareHandleImage.h index 005a65a815..ef60106e68 100644 --- a/gfx/layers/D3D11ShareHandleImage.h +++ b/gfx/layers/D3D11ShareHandleImage.h @@ -46,7 +46,7 @@ public: gfx::IntSize GetSize() override; - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; virtual TextureClient* GetTextureClient(CompositableClient* aClient) override; diff --git a/gfx/layers/D3D9SurfaceImage.cpp b/gfx/layers/D3D9SurfaceImage.cpp index 9381aa5e9d..faf74def3d 100644 --- a/gfx/layers/D3D9SurfaceImage.cpp +++ b/gfx/layers/D3D9SurfaceImage.cpp @@ -212,7 +212,7 @@ D3D9SurfaceImage::GetTextureClient(CompositableClient* aClient) return mTextureClient; } -TemporaryRef +already_AddRefed D3D9SurfaceImage::GetAsSourceSurface() { NS_ENSURE_TRUE(mTexture, nullptr); diff --git a/gfx/layers/D3D9SurfaceImage.h b/gfx/layers/D3D9SurfaceImage.h index 7d09e68f78..d47b0e7696 100644 --- a/gfx/layers/D3D9SurfaceImage.h +++ b/gfx/layers/D3D9SurfaceImage.h @@ -40,7 +40,7 @@ public: gfx::IntSize GetSize() override; - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; virtual TextureClient* GetTextureClient(CompositableClient* aClient) override; diff --git a/gfx/layers/Effects.h b/gfx/layers/Effects.h index f32098d9a3..626c9739a7 100644 --- a/gfx/layers/Effects.h +++ b/gfx/layers/Effects.h @@ -7,7 +7,7 @@ #define MOZILLA_LAYERS_EFFECTS_H #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef, etc +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc #include "mozilla/gfx/Matrix.h" // for Matrix4x4 #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Rect.h" // for Rect @@ -244,7 +244,7 @@ struct EffectChain * where aFormat would be FOMRAT_YCBCR and each texture source would be * a one-channel A8 texture) */ -inline TemporaryRef +inline already_AddRefed CreateTexturedEffect(gfx::SurfaceFormat aFormat, TextureSource* aSource, const gfx::Filter& aFilter, @@ -277,7 +277,7 @@ CreateTexturedEffect(gfx::SurfaceFormat aFormat, * * aSourceOnWhite can be null. */ -inline TemporaryRef +inline already_AddRefed CreateTexturedEffect(TextureSource* aSource, TextureSource* aSourceOnWhite, const gfx::Filter& aFilter, @@ -301,7 +301,7 @@ CreateTexturedEffect(TextureSource* aSource, * * This version excudes the possibility of component alpha. */ -inline TemporaryRef +inline already_AddRefed CreateTexturedEffect(TextureSource *aTexture, const gfx::Filter& aFilter) { diff --git a/gfx/layers/GLImages.cpp b/gfx/layers/GLImages.cpp index 7525eefd40..e286b9e898 100644 --- a/gfx/layers/GLImages.cpp +++ b/gfx/layers/GLImages.cpp @@ -33,7 +33,7 @@ EGLImageImage::~EGLImageImage() } } -TemporaryRef +already_AddRefed GLImage::GetAsSourceSurface() { MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread"); diff --git a/gfx/layers/GLImages.h b/gfx/layers/GLImages.h index e0a6c67057..c47d0f1322 100644 --- a/gfx/layers/GLImages.h +++ b/gfx/layers/GLImages.h @@ -23,7 +23,7 @@ class GLImage : public Image { public: explicit GLImage(ImageFormat aFormat) : Image(nullptr, aFormat){} - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; }; class EGLImageImage : public GLImage { diff --git a/gfx/layers/GrallocImages.cpp b/gfx/layers/GrallocImages.cpp index d072a095a7..ab67be169c 100644 --- a/gfx/layers/GrallocImages.cpp +++ b/gfx/layers/GrallocImages.cpp @@ -380,7 +380,7 @@ ConvertOmxYUVFormatToRGB565(android::sp& aBuffer, return OK; } -TemporaryRef +already_AddRefed GrallocImage::GetAsSourceSurface() { if (!mTextureClient) { diff --git a/gfx/layers/GrallocImages.h b/gfx/layers/GrallocImages.h index b0614a5a0f..14b52e8d8c 100644 --- a/gfx/layers/GrallocImages.h +++ b/gfx/layers/GrallocImages.h @@ -84,7 +84,7 @@ public: GRALLOC_SW_UAGE = android::GraphicBuffer::USAGE_SOFTWARE_MASK, }; - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; android::sp GetGraphicBuffer() const; diff --git a/gfx/layers/IMFYCbCrImage.cpp b/gfx/layers/IMFYCbCrImage.cpp index 80deb251f0..862271cf2a 100644 --- a/gfx/layers/IMFYCbCrImage.cpp +++ b/gfx/layers/IMFYCbCrImage.cpp @@ -56,7 +56,7 @@ struct AutoLockTexture RefPtr mMutex; }; -static TemporaryRef +static already_AddRefed InitTextures(IDirect3DDevice9* aDevice, const IntSize &aSize, _D3DFORMAT aFormat, diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index 38f1d0c182..8713bd654e 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -10,7 +10,7 @@ #include "gfx2DGlue.h" #include "gfxPlatform.h" // for gfxPlatform #include "gfxUtils.h" // for gfxUtils -#include "mozilla/RefPtr.h" // for TemporaryRef +#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/ipc/CrossProcessMutex.h" // for CrossProcessMutex, etc #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild @@ -281,7 +281,7 @@ ImageContainer::LockCurrentImage() return retval.forget(); } -TemporaryRef +already_AddRefed ImageContainer::LockCurrentAsSourceSurface(gfx::IntSize *aSize, Image** aCurrentImage) { ReentrantMonitorAutoEnter mon(mReentrantMonitor); @@ -304,7 +304,7 @@ ImageContainer::UnlockCurrentImage() { } -TemporaryRef +already_AddRefed ImageContainer::GetCurrentAsSourceSurface(gfx::IntSize *aSize) { ReentrantMonitorAutoEnter mon(mReentrantMonitor); @@ -465,7 +465,7 @@ PlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize) return mBuffer; } -TemporaryRef +already_AddRefed PlanarYCbCrImage::GetAsSourceSurface() { if (mSourceSurface) { diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index ea9cec2ee9..f46d7ad7a9 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -152,7 +152,7 @@ public: void MarkSent() { mSent = true; } bool IsSentToCompositor() { return mSent; } - virtual TemporaryRef GetAsSourceSurface() = 0; + virtual already_AddRefed GetAsSourceSurface() = 0; virtual GrallocImage* AsGrallocImage() { @@ -427,12 +427,12 @@ public: * the lock methods should be used to avoid the copy, however this should be * avoided if the surface is required for a long period of time. */ - TemporaryRef GetCurrentAsSourceSurface(gfx::IntSize* aSizeResult); + already_AddRefed GetCurrentAsSourceSurface(gfx::IntSize* aSizeResult); /** * Same as LockCurrentAsSurface but for Moz2D */ - TemporaryRef LockCurrentAsSourceSurface(gfx::IntSize* aSizeResult, + already_AddRefed LockCurrentAsSourceSurface(gfx::IntSize* aSizeResult, Image** aCurrentImage = nullptr); /** @@ -768,7 +768,7 @@ protected: */ virtual uint8_t* AllocateBuffer(uint32_t aSize); - TemporaryRef GetAsSourceSurface(); + already_AddRefed GetAsSourceSurface(); void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; } gfxImageFormat GetOffscreenFormat(); @@ -805,7 +805,7 @@ public: mSourceSurface = aData.mSourceSurface; } - virtual TemporaryRef GetAsSourceSurface() override + virtual already_AddRefed GetAsSourceSurface() override { RefPtr surface(mSourceSurface); return surface.forget(); @@ -846,7 +846,7 @@ public: mSize = aData.mSize; } - TemporaryRef GetAsSourceSurface() { return nullptr; } ; + already_AddRefed GetAsSourceSurface() { return nullptr; } ; int32_t GetOverlayId() { return mOverlayId; } gfx::IntSize GetSize() { return mSize; } diff --git a/gfx/layers/ImageDataSerializer.cpp b/gfx/layers/ImageDataSerializer.cpp index 331dd048dd..3d47a6e086 100644 --- a/gfx/layers/ImageDataSerializer.cpp +++ b/gfx/layers/ImageDataSerializer.cpp @@ -150,7 +150,7 @@ ImageDataSerializerBase::GetFormat() const return GetBufferInfo(mData, mDataSize)->format; } -TemporaryRef +already_AddRefed ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend) { MOZ_ASSERT(IsValid()); @@ -159,7 +159,7 @@ ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend) GetStride(), GetFormat()); } -TemporaryRef +already_AddRefed ImageDataSerializerBase::GetAsSurface() { MOZ_ASSERT(IsValid()); diff --git a/gfx/layers/ImageDataSerializer.h b/gfx/layers/ImageDataSerializer.h index 33f8e26167..e2752f2573 100644 --- a/gfx/layers/ImageDataSerializer.h +++ b/gfx/layers/ImageDataSerializer.h @@ -10,7 +10,7 @@ #include // for uint8_t, uint32_t #include "mozilla/Attributes.h" // for MOZ_STACK_CLASS -#include "mozilla/RefPtr.h" // for TemporaryRef +#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Types.h" // for SurfaceFormat @@ -33,8 +33,8 @@ public: uint32_t GetStride() const; gfx::IntSize GetSize() const; gfx::SurfaceFormat GetFormat() const; - TemporaryRef GetAsSurface(); - TemporaryRef GetAsDrawTarget(gfx::BackendType aBackend); + already_AddRefed GetAsSurface(); + already_AddRefed GetAsDrawTarget(gfx::BackendType aBackend); static uint32_t ComputeMinBufferSize(gfx::IntSize aSize, gfx::SurfaceFormat aFormat); diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index f5356dfab6..1a2bd36257 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -136,7 +136,7 @@ LayerManager::GetScrollableLayers(nsTArray& aArray) } } -TemporaryRef +already_AddRefed LayerManager::CreateOptimalDrawTarget(const gfx::IntSize &aSize, SurfaceFormat aFormat) { @@ -144,13 +144,13 @@ LayerManager::CreateOptimalDrawTarget(const gfx::IntSize &aSize, aFormat); } -TemporaryRef +already_AddRefed LayerManager::CreateOptimalMaskDrawTarget(const gfx::IntSize &aSize) { return CreateOptimalDrawTarget(aSize, SurfaceFormat::A8); } -TemporaryRef +already_AddRefed LayerManager::CreateDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) { diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 9e5df74b01..2b4366fa56 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -21,7 +21,7 @@ #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2, etc #include "mozilla/DebugOnly.h" // for DebugOnly #include "mozilla/EventForwards.h" // for nsPaintEvent -#include "mozilla/RefPtr.h" // for TemporaryRef +#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/StyleAnimationValue.h" // for StyleAnimationValue, etc #include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration #include "mozilla/gfx/BaseMargin.h" // for BaseMargin @@ -472,7 +472,7 @@ public: * Creates a DrawTarget which is optimized for inter-operating with this * layer manager. */ - virtual TemporaryRef + virtual already_AddRefed CreateOptimalDrawTarget(const IntSize &aSize, SurfaceFormat imageFormat); @@ -482,14 +482,14 @@ public: * this surface is optimised for drawing alpha only and we assume that * drawing the mask is fairly simple. */ - virtual TemporaryRef + virtual already_AddRefed CreateOptimalMaskDrawTarget(const IntSize &aSize); /** * Creates a DrawTarget for use with canvas which is optimized for * inter-operating with this layermanager. */ - virtual TemporaryRef + virtual already_AddRefed CreateDrawTarget(const mozilla::gfx::IntSize &aSize, mozilla::gfx::SurfaceFormat aFormat); diff --git a/gfx/layers/MacIOSurfaceImage.cpp b/gfx/layers/MacIOSurfaceImage.cpp index c6559dbf3c..c7b8c0ee8f 100644 --- a/gfx/layers/MacIOSurfaceImage.cpp +++ b/gfx/layers/MacIOSurfaceImage.cpp @@ -22,7 +22,7 @@ MacIOSurfaceImage::GetTextureClient(CompositableClient* aClient) return mTextureClient; } -TemporaryRef +already_AddRefed MacIOSurfaceImage::GetAsSourceSurface() { mSurface->Lock(); diff --git a/gfx/layers/MacIOSurfaceImage.h b/gfx/layers/MacIOSurfaceImage.h index 74c0042989..53569ba936 100644 --- a/gfx/layers/MacIOSurfaceImage.h +++ b/gfx/layers/MacIOSurfaceImage.h @@ -24,7 +24,7 @@ public: return gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight()); } - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; virtual TextureClient* GetTextureClient(CompositableClient* aClient) override; diff --git a/gfx/layers/RotatedBuffer.cpp b/gfx/layers/RotatedBuffer.cpp index dfd81e6c10..8199db9a6c 100644 --- a/gfx/layers/RotatedBuffer.cpp +++ b/gfx/layers/RotatedBuffer.cpp @@ -179,7 +179,7 @@ RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, ContextSource aS DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aOperator,aMask, aMaskTransform); } -TemporaryRef +already_AddRefed SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const { RefPtr surf; @@ -778,7 +778,7 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState, return result; } -TemporaryRef +already_AddRefed RotatedContentBuffer::GetSourceSurface(ContextSource aSource) const { MOZ_ASSERT(mDTBuffer); diff --git a/gfx/layers/RotatedBuffer.h b/gfx/layers/RotatedBuffer.h index 9f72806fa0..f6e8de0f9c 100644 --- a/gfx/layers/RotatedBuffer.h +++ b/gfx/layers/RotatedBuffer.h @@ -9,7 +9,7 @@ #include "gfxTypes.h" #include // for uint32_t #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/2D.h" // for DrawTarget, etc #include "mozilla/mozalloc.h" // for operator delete #include "nsAutoPtr.h" // for nsRefPtr @@ -89,7 +89,7 @@ public: virtual bool HaveBuffer() const = 0; virtual bool HaveBufferOnWhite() const = 0; - virtual TemporaryRef GetSourceSurface(ContextSource aSource) const = 0; + virtual already_AddRefed GetSourceSurface(ContextSource aSource) const = 0; protected: @@ -144,7 +144,7 @@ public: , mSourceOnWhite(aSourceOnWhite) { } - virtual TemporaryRef GetSourceSurface(ContextSource aSource) const; + virtual already_AddRefed GetSourceSurface(ContextSource aSource) const; virtual bool HaveBuffer() const { return !!mSource; } virtual bool HaveBufferOnWhite() const { return !!mSourceOnWhite; } @@ -324,7 +324,7 @@ public: gfx::DrawTarget* GetDTBuffer() { return mDTBuffer; } gfx::DrawTarget* GetDTBufferOnWhite() { return mDTBufferOnWhite; } - virtual TemporaryRef GetSourceSurface(ContextSource aSource) const; + virtual already_AddRefed GetSourceSurface(ContextSource aSource) const; /** * Complete the drawing operation. The region to draw must have been diff --git a/gfx/layers/TextureDIB.cpp b/gfx/layers/TextureDIB.cpp index 3e283db775..a6740a407e 100644 --- a/gfx/layers/TextureDIB.cpp +++ b/gfx/layers/TextureDIB.cpp @@ -27,7 +27,7 @@ DIBTextureClient::~DIBTextureClient() MOZ_COUNT_DTOR(DIBTextureClient); } -TemporaryRef +already_AddRefed DIBTextureClient::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { diff --git a/gfx/layers/TextureDIB.h b/gfx/layers/TextureDIB.h index 900f31fc52..28c93e4328 100644 --- a/gfx/layers/TextureDIB.h +++ b/gfx/layers/TextureDIB.h @@ -54,7 +54,7 @@ public: virtual bool HasInternalBuffer() const override { return true; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; @@ -88,7 +88,7 @@ public: virtual void Updated(const nsIntRegion* aRegion = nullptr) override; - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // TODO: cf bug 872568 } diff --git a/gfx/layers/YCbCrImageDataSerializer.cpp b/gfx/layers/YCbCrImageDataSerializer.cpp index 05f5ab2bd6..2c6bcb6e13 100644 --- a/gfx/layers/YCbCrImageDataSerializer.cpp +++ b/gfx/layers/YCbCrImageDataSerializer.cpp @@ -284,7 +284,7 @@ YCbCrImageDataSerializer::CopyData(const uint8_t* aYData, return true; } -TemporaryRef +already_AddRefed YCbCrImageDataDeserializer::ToDataSourceSurface() { RefPtr result = diff --git a/gfx/layers/YCbCrImageDataSerializer.h b/gfx/layers/YCbCrImageDataSerializer.h index 5534251e5f..0fd7b507eb 100644 --- a/gfx/layers/YCbCrImageDataSerializer.h +++ b/gfx/layers/YCbCrImageDataSerializer.h @@ -10,7 +10,7 @@ #include // for uint8_t, uint32_t #include "ImageTypes.h" // for StereoMode #include "mozilla/Attributes.h" // for MOZ_STACK_CLASS -#include "mozilla/RefPtr.h" // for TemporaryRef +#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/gfx/Point.h" // for IntSize namespace mozilla { @@ -177,7 +177,7 @@ public: * This is a costly operation, so use it only when YCbCr compositing is * not supported. */ - TemporaryRef ToDataSourceSurface(); + already_AddRefed ToDataSourceSurface(); }; } // namespace diff --git a/gfx/layers/apz/public/GoannaContentController.h b/gfx/layers/apz/public/GoannaContentController.h index 54fdce4827..f41f6e6a14 100644 --- a/gfx/layers/apz/public/GoannaContentController.h +++ b/gfx/layers/apz/public/GoannaContentController.h @@ -29,6 +29,14 @@ public: */ virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0; + /** + * Requests handling of a scroll snapping at the end of a fling gesture for + * the scrollable frame with the given scroll id. aDestination specifies the + * expected landing position of the fling if no snapping were to be performed. + */ + virtual void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) = 0; + /** * Acknowledges the recipt of a scroll offset update for the scrollable * frame with the given scroll id. This is used to maintain consistency diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 0351b0557c..9210364614 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2034,9 +2034,37 @@ void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity, mX.SetVelocity(mX.GetVelocity() + aVelocity.x); mY.SetVelocity(mY.GetVelocity() + aVelocity.y); SetState(FLING); - StartAnimation(new FlingAnimation(*this, + FlingAnimation *fling = new FlingAnimation(*this, aOverscrollHandoffChain, - !aHandoff)); // only apply acceleration if this is an initial fling + !aHandoff); // only apply acceleration if this is an initial fling + + float friction = gfxPrefs::APZFlingFriction(); + ParentLayerPoint velocity(mX.GetVelocity(), mY.GetVelocity()); + ParentLayerPoint predictedDelta; + // "-velocity / log(1.0 - friction)" is the integral of the deceleration + // curve modeled for flings in the "Axis" class. + if (velocity.x != 0.0f) { + predictedDelta.x = -velocity.x / log(1.0 - friction); + } + if (velocity.y != 0.0f) { + predictedDelta.y = -velocity.y / log(1.0 - friction); + } + CSSPoint predictedDestination = mFrameMetrics.GetScrollOffset() + predictedDelta / mFrameMetrics.GetZoom(); + + nsRefPtr controller = GetGoannaContentController(); + if (controller) { + APZC_LOG("%p fling snapping. friction: %f velocity: %f, %f " + "predictedDelta: %f, %f position: %f, %f " + "predictedDestination: %f, %f\n", + this, friction, velocity.x, velocity.y, (float)predictedDelta.x, + (float)predictedDelta.y, (float)mFrameMetrics.GetScrollOffset().x, + (float)mFrameMetrics.GetScrollOffset().y, + (float)predictedDestination.x, (float)predictedDestination.y); + controller->RequestFlingSnap(mFrameMetrics.GetScrollId(), + predictedDestination); + } + + StartAnimation(fling); } bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity, diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 65f5063c6a..12418c28ed 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -264,6 +264,46 @@ APZCCallbackHelper::GetOrCreateScrollIdentifiers(nsIContent* aContent, return utils && (utils->GetPresShellId(aPresShellIdOut) == NS_OK); } +class FlingSnapEvent : public nsRunnable +{ + typedef mozilla::layers::FrameMetrics::ViewID ViewID; + +public: + FlingSnapEvent(const ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) + : mScrollId(aScrollId) + , mDestination(aDestination) + { + } + + NS_IMETHOD Run() { + MOZ_ASSERT(NS_IsMainThread()); + + nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(mScrollId); + if (sf) { + sf->FlingSnap(mDestination); + } + + return NS_OK; + } + +protected: + ViewID mScrollId; + mozilla::CSSPoint mDestination; +}; + +void +APZCCallbackHelper::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) +{ + nsCOMPtr r1 = new FlingSnapEvent(aScrollId, aDestination); + if (!NS_IsMainThread()) { + NS_DispatchToMainThread(r1); + } else { + r1->Run(); + } +} + class AcknowledgeScrollUpdateEvent : public nsRunnable { typedef mozilla::layers::FrameMetrics::ViewID ViewID; diff --git a/gfx/layers/apz/util/APZCCallbackHelper.h b/gfx/layers/apz/util/APZCCallbackHelper.h index fd74300e35..ab7c256319 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.h +++ b/gfx/layers/apz/util/APZCCallbackHelper.h @@ -81,6 +81,14 @@ public: uint32_t* aPresShellIdOut, FrameMetrics::ViewID* aViewIdOut); + /* Tell layout to perform scroll snapping for the scrollable frame with the + * given scroll id. aDestination specifies the expected landing position of + * a current fling or scrolling animation that should be used to select + * the scroll snap point. + */ + static void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination); + /* Tell layout that we received the scroll offset update for the given view ID, so that it accepts future scroll offset updates from APZ. */ static void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, diff --git a/gfx/layers/apz/util/ChromeProcessController.cpp b/gfx/layers/apz/util/ChromeProcessController.cpp index 8b1e5cec2d..c1d7c437e2 100644 --- a/gfx/layers/apz/util/ChromeProcessController.cpp +++ b/gfx/layers/apz/util/ChromeProcessController.cpp @@ -86,6 +86,13 @@ ChromeProcessController::PostDelayedTask(Task* aTask, int aDelayMs) MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs); } +void +ChromeProcessController::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) +{ + APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination); +} + void ChromeProcessController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, const uint32_t& aScrollGeneration) diff --git a/gfx/layers/apz/util/ChromeProcessController.h b/gfx/layers/apz/util/ChromeProcessController.h index 618bbf7263..a29c528416 100644 --- a/gfx/layers/apz/util/ChromeProcessController.h +++ b/gfx/layers/apz/util/ChromeProcessController.h @@ -33,28 +33,30 @@ class ChromeProcessController : public mozilla::layers::GoannaContentController public: explicit ChromeProcessController(nsIWidget* aWidget, APZEventState* aAPZEventState); - virtual void Destroy() override; + virtual void Destroy() MOZ_OVERRIDE; // GoannaContentController interface - virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override; - virtual void PostDelayedTask(Task* aTask, int aDelayMs) override; + virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE; + virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE; + virtual void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) MOZ_OVERRIDE; virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, - const uint32_t& aScrollGeneration) override; + const uint32_t& aScrollGeneration) MOZ_OVERRIDE; virtual void HandleDoubleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid) override {} virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) override; + const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId) override; + uint64_t aInputBlockId) MOZ_OVERRIDE; virtual void HandleLongTapUp(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) override; + const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual void SendAsyncScrollDOMEvent(bool aIsRoot, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize) override {} virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, - int aArg) override; + int aArg) MOZ_OVERRIDE; private: nsCOMPtr mWidget; nsRefPtr mAPZEventState; diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 06799010a5..9f404c719f 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -105,7 +105,7 @@ void BasicCompositor::Destroy() mWidget = nullptr; } -TemporaryRef +already_AddRefed BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit) { MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size"); @@ -125,7 +125,7 @@ BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit) return rt.forget(); } -TemporaryRef +already_AddRefed BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect, const CompositingRenderTarget *aSource, const IntPoint &aSourcePoint) @@ -134,7 +134,7 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect, return nullptr; } -TemporaryRef +already_AddRefed BasicCompositor::CreateDataTextureSource(TextureFlags aFlags) { RefPtr result = new DataTextureSourceBasic(); diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index 07b0061ad8..71c4271bf7 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -59,15 +59,15 @@ public: GetMaxTextureSize()); } - virtual TemporaryRef + virtual already_AddRefed CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override; - virtual TemporaryRef + virtual already_AddRefed CreateRenderTargetFromSource(const gfx::IntRect &aRect, const CompositingRenderTarget *aSource, const gfx::IntPoint &aSourcePoint) override; - virtual TemporaryRef + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; virtual bool SupportsEffect(EffectTypes aEffect) override; diff --git a/gfx/layers/basic/BasicImageLayer.cpp b/gfx/layers/basic/BasicImageLayer.cpp index 25588c6207..89027def93 100644 --- a/gfx/layers/basic/BasicImageLayer.cpp +++ b/gfx/layers/basic/BasicImageLayer.cpp @@ -49,7 +49,7 @@ public: const gfx::Point& aDeviceOffset, Layer* aMaskLayer) override; - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; protected: BasicLayerManager* BasicManager() @@ -91,7 +91,7 @@ BasicImageLayer::Paint(DrawTarget* aDT, GetContainer()->NotifyPaintedImage(image); } -TemporaryRef +already_AddRefed BasicImageLayer::GetAsSourceSurface() { if (!mContainer) { diff --git a/gfx/layers/basic/BasicImages.cpp b/gfx/layers/basic/BasicImages.cpp index 2d7019d6d1..05fa18694a 100644 --- a/gfx/layers/basic/BasicImages.cpp +++ b/gfx/layers/basic/BasicImages.cpp @@ -52,7 +52,7 @@ public: virtual void SetData(const Data& aData) override; virtual void SetDelayedConversion(bool aDelayed) override { mDelayedConversion = aDelayed; } - TemporaryRef GetAsSourceSurface() override; + already_AddRefed GetAsSourceSurface() override; virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override { @@ -137,7 +137,7 @@ BasicPlanarYCbCrImage::SetData(const Data& aData) mSize = size; } -TemporaryRef +already_AddRefed BasicPlanarYCbCrImage::GetAsSourceSurface() { NS_ASSERTION(NS_IsMainThread(), "Must be main thread"); diff --git a/gfx/layers/basic/BasicImplData.h b/gfx/layers/basic/BasicImplData.h index 6e73da76dc..db342b8db0 100644 --- a/gfx/layers/basic/BasicImplData.h +++ b/gfx/layers/basic/BasicImplData.h @@ -117,7 +117,7 @@ public: * return false if a surface cannot be created. If true is * returned, only one of |aSurface| or |aDescriptor| is valid. */ - virtual TemporaryRef GetAsSourceSurface() { return nullptr; } + virtual already_AddRefed GetAsSourceSurface() { return nullptr; } bool GetClipToVisibleRegion() { return mClipToVisibleRegion; } void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; } diff --git a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h index 93db2e7784..f5f0292f75 100644 --- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h +++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h @@ -69,7 +69,7 @@ public: return mTextureSource; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/basic/TextureClientX11.cpp b/gfx/layers/basic/TextureClientX11.cpp index dc23923264..a5bb5b85fd 100644 --- a/gfx/layers/basic/TextureClientX11.cpp +++ b/gfx/layers/basic/TextureClientX11.cpp @@ -34,7 +34,7 @@ TextureClientX11::~TextureClientX11() MOZ_COUNT_DTOR(TextureClientX11); } -TemporaryRef +already_AddRefed TextureClientX11::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { diff --git a/gfx/layers/basic/TextureClientX11.h b/gfx/layers/basic/TextureClientX11.h index e3499e6f4a..30b4d528c5 100644 --- a/gfx/layers/basic/TextureClientX11.h +++ b/gfx/layers/basic/TextureClientX11.h @@ -47,7 +47,7 @@ class TextureClientX11 : public TextureClient virtual bool HasInternalBuffer() const override { return false; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; diff --git a/gfx/layers/basic/TextureHostBasic.cpp b/gfx/layers/basic/TextureHostBasic.cpp index b5aeab5d14..b75ad83d73 100644 --- a/gfx/layers/basic/TextureHostBasic.cpp +++ b/gfx/layers/basic/TextureHostBasic.cpp @@ -14,7 +14,7 @@ using namespace mozilla::gfx; namespace mozilla { namespace layers { -TemporaryRef +already_AddRefed CreateTextureHostBasic(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) diff --git a/gfx/layers/basic/X11BasicCompositor.cpp b/gfx/layers/basic/X11BasicCompositor.cpp index d825e36acb..c063a65c9f 100644 --- a/gfx/layers/basic/X11BasicCompositor.cpp +++ b/gfx/layers/basic/X11BasicCompositor.cpp @@ -117,7 +117,7 @@ X11DataTextureSourceBasic::DeallocateDeviceData() mBufferDrawTarget = nullptr; } -TemporaryRef +already_AddRefed X11BasicCompositor::CreateDataTextureSource(TextureFlags aFlags) { RefPtr result = diff --git a/gfx/layers/basic/X11BasicCompositor.h b/gfx/layers/basic/X11BasicCompositor.h index f76822083b..f897ce04e0 100644 --- a/gfx/layers/basic/X11BasicCompositor.h +++ b/gfx/layers/basic/X11BasicCompositor.h @@ -47,7 +47,7 @@ public: explicit X11BasicCompositor(nsIWidget *aWidget) : BasicCompositor(aWidget) {} - virtual TemporaryRef + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; }; diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index df7e395345..2a5b2ef0ac 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -32,7 +32,7 @@ using namespace mozilla::gl; namespace mozilla { namespace layers { -/* static */ TemporaryRef +/* static */ already_AddRefed CanvasClient::CreateCanvasClient(CanvasClientType aType, CompositableForwarder* aForwarder, TextureFlags aFlags) @@ -118,7 +118,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) } } -TemporaryRef +already_AddRefed CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, TextureFlags aFlags, @@ -156,7 +156,7 @@ CanvasClientSharedSurface::CanvasClientSharedSurface(CompositableForwarder* aLay //////////////////////////////////////// // Accelerated backends -static TemporaryRef +static already_AddRefed TexClientFromShSurf(ISurfaceAllocator* aAllocator, SharedSurface* surf, TextureFlags flags) { @@ -206,20 +206,20 @@ public: } protected: - TemporaryRef Create(gfx::SurfaceFormat format) { + already_AddRefed Create(gfx::SurfaceFormat format) { return TextureClient::CreateForRawBufferAccess(mAllocator, format, mSize, mBackendType, mBaseTexFlags); } public: - TemporaryRef CreateB8G8R8AX8() { + already_AddRefed CreateB8G8R8AX8() { gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::B8G8R8X8; return Create(format); } - TemporaryRef CreateR8G8B8AX8() { + already_AddRefed CreateR8G8B8AX8() { RefPtr ret; bool areRGBAFormatsBroken = mLayersBackend == LayersBackend::LAYERS_BASIC; @@ -240,7 +240,7 @@ public: } }; -static TemporaryRef +static already_AddRefed TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator, TextureFlags baseFlags, LayersBackend layersBackend) { @@ -331,7 +331,7 @@ TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator, //////////////////////////////////////// -static TemporaryRef +static already_AddRefed CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory) { RefPtr dest = factory->NewShSurfHandle(src->mSize); diff --git a/gfx/layers/client/CanvasClient.h b/gfx/layers/client/CanvasClient.h index 3b3bb3fe0b..364ab7e3dd 100644 --- a/gfx/layers/client/CanvasClient.h +++ b/gfx/layers/client/CanvasClient.h @@ -8,7 +8,7 @@ #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/layers/CompositableClient.h" // for CompositableClient #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor @@ -47,7 +47,7 @@ public: CanvasClientGLContext, CanvasClientTypeShSurf, }; - static TemporaryRef CreateCanvasClient(CanvasClientType aType, + static already_AddRefed CreateCanvasClient(CanvasClientType aType, CompositableForwarder* aFwd, TextureFlags aFlags); @@ -100,7 +100,7 @@ public: } private: - TemporaryRef + already_AddRefed CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, TextureFlags aFlags, diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index 6506185d31..d6ea0fa202 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -190,7 +190,7 @@ CompositableClient::GetAsyncID() const return 0; // zero is always an invalid async ID } -TemporaryRef +already_AddRefed CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2DBackend, @@ -201,7 +201,7 @@ CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, aTextureFlags | mTextureFlags); } -TemporaryRef +already_AddRefed CompositableClient::CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2DBackend, diff --git a/gfx/layers/client/CompositableClient.h b/gfx/layers/client/CompositableClient.h index 518d4634f3..6bf851451d 100644 --- a/gfx/layers/client/CompositableClient.h +++ b/gfx/layers/client/CompositableClient.h @@ -10,7 +10,7 @@ #include // for vector #include // for map #include "mozilla/Assertions.h" // for MOZ_CRASH -#include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted +#include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted #include "mozilla/gfx/Types.h" // for SurfaceFormat #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker #include "mozilla/layers/CompositorTypes.h" @@ -130,13 +130,13 @@ public: LayersBackend GetCompositorBackendType() const; - TemporaryRef + already_AddRefed CreateBufferTextureClient(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2dBackend = gfx::BackendType::NONE, TextureFlags aFlags = TextureFlags::DEFAULT); - TemporaryRef + already_AddRefed CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2DBackend, diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 3db4f9d8e7..1ac23e3bfd 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -59,7 +59,7 @@ static TextureFlags TextureFlagsForRotatedContentBufferFlags(uint32_t aBufferFla return result; } -/* static */ TemporaryRef +/* static */ already_AddRefed ContentClient::CreateContentClient(CompositableForwarder* aForwarder) { LayersBackend backend = aForwarder->GetCompositorBackendType(); @@ -1000,7 +1000,7 @@ ContentClientIncremental::Updated(const nsIntRegion& aRegionToDraw, } -TemporaryRef +already_AddRefed ContentClientIncremental::GetUpdateSurface(BufferType aType, const nsIntRegion& aUpdateRegion) { diff --git a/gfx/layers/client/ContentClient.h b/gfx/layers/client/ContentClient.h index 9db5591c7e..5373cac42b 100644 --- a/gfx/layers/client/ContentClient.h +++ b/gfx/layers/client/ContentClient.h @@ -12,7 +12,7 @@ #include "gfxPlatform.h" // for gfxPlatform #include "mozilla/Assertions.h" // for MOZ_CRASH #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/layers/CompositableClient.h" // for CompositableClient #include "mozilla/layers/CompositableForwarder.h" @@ -81,7 +81,7 @@ public: * message will be sent to the compositor to create a corresponding content * host. */ - static TemporaryRef CreateContentClient(CompositableForwarder* aFwd); + static already_AddRefed CreateContentClient(CompositableForwarder* aFwd); explicit ContentClient(CompositableForwarder* aForwarder) : CompositableClient(aForwarder) @@ -464,7 +464,7 @@ private: void NotifyBufferCreated(ContentType aType, TextureFlags aFlags); - TemporaryRef GetUpdateSurface(BufferType aType, + already_AddRefed GetUpdateSurface(BufferType aType, const nsIntRegion& aUpdateRegion); TextureInfo mTextureInfo; diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index c787a025a2..dee2154533 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -11,7 +11,7 @@ #include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat #include "gfxPlatform.h" // for gfxPlatform #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Types.h" // for SurfaceFormat, etc @@ -41,7 +41,7 @@ namespace layers { using namespace mozilla::gfx; -/* static */ TemporaryRef +/* static */ already_AddRefed ImageClient::CreateImageClient(CompositableType aCompositableHostType, CompositableForwarder* aForwarder, TextureFlags aFlags) @@ -117,7 +117,7 @@ TextureInfo ImageClientSingle::GetTextureInfo() const return TextureInfo(CompositableType::IMAGE); } -TemporaryRef +already_AddRefed ImageClientSingle::PrepareFlushAllImages() { return MakeAndAddRef(); diff --git a/gfx/layers/client/ImageClient.h b/gfx/layers/client/ImageClient.h index 546f888f37..c97aa03d59 100644 --- a/gfx/layers/client/ImageClient.h +++ b/gfx/layers/client/ImageClient.h @@ -9,7 +9,7 @@ #include // for uint32_t, uint64_t #include // for int32_t #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/Types.h" // for SurfaceFormat #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker #include "mozilla/layers/CompositableClient.h" // for CompositableClient @@ -42,7 +42,7 @@ public: * message will be sent to the compositor to create a corresponding image * host. */ - static TemporaryRef CreateImageClient(CompositableType aImageHostType, + static already_AddRefed CreateImageClient(CompositableType aImageHostType, CompositableForwarder* aFwd, TextureFlags aFlags); @@ -66,7 +66,7 @@ public: /** * Create AsyncTransactionTracker that is used for FlushAllImagesAsync(). */ - virtual TemporaryRef PrepareFlushAllImages() { return nullptr; } + virtual already_AddRefed PrepareFlushAllImages() { return nullptr; } /** * asynchronously remove all the textures used by the image client. @@ -109,7 +109,7 @@ public: virtual already_AddRefed CreateImage(ImageFormat aFormat) override; - virtual TemporaryRef PrepareFlushAllImages() override; + virtual already_AddRefed PrepareFlushAllImages() override; virtual void FlushAllImages(bool aExceptFront, AsyncTransactionTracker* aAsyncTransactionTracker) override; diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index ecc28b6346..cfed40c603 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -284,7 +284,7 @@ DisableGralloc(SurfaceFormat aFormat, const gfx::IntSize& aSizeHint) #endif static -TemporaryRef +already_AddRefed CreateBufferTextureClient(ISurfaceAllocator* aAllocator, SurfaceFormat aFormat, TextureFlags aTextureFlags, @@ -303,7 +303,7 @@ CreateBufferTextureClient(ISurfaceAllocator* aAllocator, } // static -TemporaryRef +already_AddRefed TextureClient::CreateForDrawing(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, @@ -411,7 +411,7 @@ TextureClient::CreateForDrawing(ISurfaceAllocator* aAllocator, } // static -TemporaryRef +already_AddRefed TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, @@ -435,7 +435,7 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, } // static -TemporaryRef +already_AddRefed TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, @@ -465,7 +465,7 @@ TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator, } // static -TemporaryRef +already_AddRefed TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, size_t aSize, @@ -731,7 +731,7 @@ BufferTextureClient::BufferTextureClient(ISurfaceAllocator* aAllocator, BufferTextureClient::~BufferTextureClient() {} -TemporaryRef +already_AddRefed BufferTextureClient::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -919,7 +919,7 @@ SharedSurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescripto return true; } -TemporaryRef +already_AddRefed SyncObject::CreateSyncObject(SyncHandle aHandle) { if (!aHandle) { diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index c7f54b8d54..7660da7d97 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -87,7 +87,7 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObject) virtual ~SyncObject() { } - static TemporaryRef CreateSyncObject(SyncHandle aHandle); + static already_AddRefed CreateSyncObject(SyncHandle aHandle); enum class SyncType { D3D11, @@ -178,7 +178,7 @@ public: virtual ~TextureClient(); // Creates and allocates a TextureClient usable with Moz2D. - static TemporaryRef + static already_AddRefed CreateForDrawing(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, @@ -187,7 +187,7 @@ public: TextureAllocationFlags flags = ALLOC_DEFAULT); // Creates and allocates a BufferTextureClient supporting the YCbCr format. - static TemporaryRef + static already_AddRefed CreateForYCbCr(ISurfaceAllocator* aAllocator, gfx::IntSize aYSize, gfx::IntSize aCbCrSize, @@ -196,7 +196,7 @@ public: // Creates and allocates a BufferTextureClient (can beaccessed through raw // pointers). - static TemporaryRef + static already_AddRefed CreateForRawBufferAccess(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, @@ -207,14 +207,14 @@ public: // Creates and allocates a BufferTextureClient (can beaccessed through raw // pointers) with a certain buffer size. It's unfortunate that we need this. // providing format and sizes could let us do more optimization. - static TemporaryRef + static already_AddRefed CreateWithBufferSize(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, size_t aSize, TextureFlags aTextureFlags); // Creates and allocates a TextureClient of the same type. - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const = 0; @@ -286,7 +286,7 @@ public: * This method is strictly for debugging. It causes locking and * needless copies. */ - virtual TemporaryRef GetAsSurface() { + virtual already_AddRefed GetAsSurface() { Lock(OpenMode::OPEN_READ); RefPtr surf = BorrowDrawTarget()->Snapshot(); RefPtr data = surf->GetDataSurface(); @@ -613,7 +613,7 @@ public: virtual bool HasInternalBuffer() const override { return true; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; @@ -731,7 +731,7 @@ public: // This TextureClient should not be used in a context where we use CreateSimilar // (ex. component alpha) because the underlying texture data is always created by // an external producer. - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags, TextureAllocationFlags) const override { return nullptr; } diff --git a/gfx/layers/client/TextureClientPool.cpp b/gfx/layers/client/TextureClientPool.cpp index 1ca3399fb1..16308eb0be 100644 --- a/gfx/layers/client/TextureClientPool.cpp +++ b/gfx/layers/client/TextureClientPool.cpp @@ -81,7 +81,7 @@ static bool TestClientPool(const char* what, } #endif -TemporaryRef +already_AddRefed TextureClientPool::GetTextureClient() { // Try to fetch a client from the pool diff --git a/gfx/layers/client/TextureClientPool.h b/gfx/layers/client/TextureClientPool.h index b491b45c88..23fcbe861c 100644 --- a/gfx/layers/client/TextureClientPool.h +++ b/gfx/layers/client/TextureClientPool.h @@ -39,7 +39,7 @@ public: * All clients retrieved by this method should be returned using the return * functions, or reported lost so that the pool can manage its size correctly. */ - TemporaryRef GetTextureClient(); + already_AddRefed GetTextureClient(); /** * Return a TextureClient that is no longer being used and is ready for diff --git a/gfx/layers/client/TextureClientRecycleAllocator.cpp b/gfx/layers/client/TextureClientRecycleAllocator.cpp index f15dad955d..b251518a62 100644 --- a/gfx/layers/client/TextureClientRecycleAllocator.cpp +++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp @@ -31,7 +31,7 @@ public: } // Creates and allocates a TextureClient. - TemporaryRef + already_AddRefed CreateOrRecycleForDrawing(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2dBackend, @@ -132,7 +132,7 @@ TextureClientRecycleAllocatorImp::~TextureClientRecycleAllocatorImp() MOZ_ASSERT(mInUseClients.empty()); } -TemporaryRef +already_AddRefed TextureClientRecycleAllocatorImp::CreateOrRecycleForDrawing( gfx::SurfaceFormat aFormat, gfx::IntSize aSize, @@ -251,7 +251,7 @@ TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax) mAllocator->SetMaxPoolSize(aMax); } -TemporaryRef +already_AddRefed TextureClientRecycleAllocator::CreateOrRecycleForDrawing( gfx::SurfaceFormat aFormat, gfx::IntSize aSize, diff --git a/gfx/layers/client/TextureClientRecycleAllocator.h b/gfx/layers/client/TextureClientRecycleAllocator.h index 41747e98d4..59e252e989 100644 --- a/gfx/layers/client/TextureClientRecycleAllocator.h +++ b/gfx/layers/client/TextureClientRecycleAllocator.h @@ -35,7 +35,7 @@ public: void SetMaxPoolSize(uint32_t aMax); // Creates and allocates a TextureClient. - TemporaryRef + already_AddRefed CreateOrRecycleForDrawing(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::BackendType aMoz2dBackend, diff --git a/gfx/layers/composite/CompositableHost.cpp b/gfx/layers/composite/CompositableHost.cpp index 0d5f932883..5b7c70c62f 100644 --- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -173,7 +173,7 @@ CompositableHost::RemoveMaskEffect() } } -/* static */ TemporaryRef +/* static */ already_AddRefed CompositableHost::Create(const TextureInfo& aTextureInfo) { RefPtr result; diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index c8d11b2211..1af02dee22 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -72,7 +72,7 @@ public: NS_INLINE_DECL_REFCOUNTING(CompositableHost) explicit CompositableHost(const TextureInfo& aTextureInfo); - static TemporaryRef Create(const TextureInfo& aTextureInfo); + static already_AddRefed Create(const TextureInfo& aTextureInfo); virtual CompositableType GetType() = 0; @@ -221,7 +221,7 @@ public: bool aDumpHtml=false) { } static void DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture); - virtual TemporaryRef GetAsSurface() { return nullptr; } + virtual already_AddRefed GetAsSurface() { return nullptr; } virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0; @@ -259,7 +259,7 @@ public: virtual void Unlock() { } - virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) { + virtual already_AddRefed GenEffect(const gfx::Filter& aFilter) { return nullptr; } diff --git a/gfx/layers/composite/ContentHost.cpp b/gfx/layers/composite/ContentHost.cpp index 4b1ba212bc..939fa9498e 100644 --- a/gfx/layers/composite/ContentHost.cpp +++ b/gfx/layers/composite/ContentHost.cpp @@ -849,7 +849,7 @@ ContentHostTexture::GetRenderState() return result; } -TemporaryRef +already_AddRefed ContentHostTexture::GenEffect(const gfx::Filter& aFilter) { if (!mTextureHost) { @@ -869,7 +869,7 @@ ContentHostTexture::GenEffect(const gfx::Filter& aFilter) aFilter, true); } -TemporaryRef +already_AddRefed ContentHostIncremental::GenEffect(const gfx::Filter& aFilter) { if (!mSource) { @@ -878,7 +878,7 @@ ContentHostIncremental::GenEffect(const gfx::Filter& aFilter) return CreateTexturedEffect(mSource, mSourceOnWhite, aFilter, true); } -TemporaryRef +already_AddRefed ContentHostTexture::GetAsSurface() { if (!mTextureHost) { diff --git a/gfx/layers/composite/ContentHost.h b/gfx/layers/composite/ContentHost.h index e3b99a36b4..c7fb7745ae 100644 --- a/gfx/layers/composite/ContentHost.h +++ b/gfx/layers/composite/ContentHost.h @@ -129,7 +129,7 @@ public: virtual void SetCompositor(Compositor* aCompositor) override; - virtual TemporaryRef GetAsSurface() override; + virtual already_AddRefed GetAsSurface() override; virtual void Dump(std::stringstream& aStream, const char* aPrefix="", @@ -168,7 +168,7 @@ public: LayerRenderState GetRenderState() override; - virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) override; + virtual already_AddRefed GenEffect(const gfx::Filter& aFilter) override; protected: CompositableTextureHostRef mTextureHost; @@ -283,7 +283,7 @@ public: mLocked = false; } - virtual TemporaryRef + virtual already_AddRefed GenEffect(const gfx::Filter& aFilter) override; private: diff --git a/gfx/layers/composite/FPSCounter.h b/gfx/layers/composite/FPSCounter.h index 2a493d3e4f..422d18eb67 100644 --- a/gfx/layers/composite/FPSCounter.h +++ b/gfx/layers/composite/FPSCounter.h @@ -10,7 +10,7 @@ #include // for size_t #include // for std::map #include "GLDefs.h" // for GLuint -#include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted +#include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted #include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration #include "nsTArray.h" // for nsAutoTArray, nsTArray_Impl, etc #include "prio.h" // for NSPR file i/o diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index aea78e07fb..b806637f73 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -240,7 +240,7 @@ ImageHost::GetRenderState() return LayerRenderState(); } -TemporaryRef +already_AddRefed ImageHost::GetAsSurface() { return mFrontBuffer->GetAsSurface(); @@ -284,7 +284,7 @@ ImageHost::GetImageSize() const return IntSize(); } -TemporaryRef +already_AddRefed ImageHost::GenEffect(const gfx::Filter& aFilter) { if (!mFrontBuffer->BindTextureSource(mTextureSource)) { diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index 5bd4930a5b..1a5f378d0a 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -76,13 +76,13 @@ public: const char* aPrefix = "", bool aDumpHtml = false) override; - virtual TemporaryRef GetAsSurface() override; + virtual already_AddRefed GetAsSurface() override; virtual bool Lock() override; virtual void Unlock() override; - virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) override; + virtual already_AddRefed GenEffect(const gfx::Filter& aFilter) override; protected: diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 6c6633c94b..b4893c79bf 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -29,7 +29,7 @@ #include "gfxRect.h" // for gfxRect #include "gfxUtils.h" // for frame color util #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/2D.h" // for DrawTarget #include "mozilla/gfx/Matrix.h" // for Matrix4x4 #include "mozilla/gfx/Point.h" // for IntSize, Point @@ -323,7 +323,7 @@ LayerManagerComposite::EndTransaction(DrawPaintedLayerCallback aCallback, #endif } -TemporaryRef +already_AddRefed LayerManagerComposite::CreateOptimalMaskDrawTarget(const IntSize &aSize) { NS_RUNTIMEABORT("Should only be called on the drawing side"); @@ -1074,7 +1074,7 @@ LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect() mCompositable->RemoveMaskEffect(); } -TemporaryRef +already_AddRefed LayerManagerComposite::CreateDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) { diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index a9c416bca4..d3a3f58909 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -11,7 +11,7 @@ #include "Layers.h" #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Rect.h" // for Rect @@ -158,7 +158,7 @@ public: virtual bool AreComponentAlphaLayersEnabled() override; - virtual TemporaryRef + virtual already_AddRefed CreateOptimalMaskDrawTarget(const IntSize &aSize) override; virtual const char* Name() const override { return ""; } @@ -192,7 +192,7 @@ public: * Creates a DrawTarget which is optimized for inter-operating with this * layermanager. */ - virtual TemporaryRef + virtual already_AddRefed CreateDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat) override; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 6d7529bdf2..2e4938813d 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -173,27 +173,27 @@ TextureHost::GetAndResetReleaseFenceHandle() } // implemented in TextureHostOGL.cpp -TemporaryRef CreateTextureHostOGL(const SurfaceDescriptor& aDesc, +already_AddRefed CreateTextureHostOGL(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); // implemented in TextureHostBasic.cpp -TemporaryRef CreateTextureHostBasic(const SurfaceDescriptor& aDesc, +already_AddRefed CreateTextureHostBasic(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); // implemented in TextureD3D11.cpp -TemporaryRef CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, +already_AddRefed CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); // implemented in TextureD3D9.cpp -TemporaryRef CreateTextureHostD3D9(const SurfaceDescriptor& aDesc, +already_AddRefed CreateTextureHostD3D9(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); // static -TemporaryRef +already_AddRefed TextureHost::Create(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) @@ -243,7 +243,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc, } } -TemporaryRef +already_AddRefed CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) @@ -599,7 +599,7 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) return true; } -TemporaryRef +already_AddRefed BufferTextureHost::GetAsSurface() { RefPtr result; diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 8a7dc3bc8a..7615d1bcfd 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -11,7 +11,7 @@ #include "gfxTypes.h" #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef, etc +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc #include "mozilla/gfx/2D.h" // for DataSourceSurface #include "mozilla/gfx/Point.h" // for IntSize, IntPoint #include "mozilla/gfx/Types.h" // for SurfaceFormat, etc @@ -204,7 +204,7 @@ public: return *this; } - CompositableTextureRef& operator=(const TemporaryRef& aOther) + CompositableTextureRef& operator=(const already_AddRefed& aOther) { RefPtr temp = aOther; if (temp) { @@ -290,7 +290,7 @@ public: * This is expected to be very slow and should be used for mostly debugging. * XXX - implement everywhere and make it pure virtual. */ - virtual TemporaryRef ReadBack() { return nullptr; }; + virtual already_AddRefed ReadBack() { return nullptr; }; #endif private: @@ -347,7 +347,7 @@ public: /** * Factory method. */ - static TemporaryRef Create(const SurfaceDescriptor& aDesc, + static already_AddRefed Create(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); @@ -452,7 +452,7 @@ public: * Debug facility. * XXX - cool kids use Moz2D. See bug 882113. */ - virtual TemporaryRef GetAsSurface() = 0; + virtual already_AddRefed GetAsSurface() = 0; /** * XXX - Flags should only be set at creation time, this will be removed. @@ -603,7 +603,7 @@ public: virtual gfx::IntSize GetSize() const override { return mSize; } - virtual TemporaryRef GetAsSurface() override; + virtual already_AddRefed GetAsSurface() override; virtual bool HasInternalBuffer() const override { return true; } @@ -704,7 +704,7 @@ public: virtual void DeallocateDeviceData() override {}; - virtual TemporaryRef GetAsSurface() override { + virtual already_AddRefed GetAsSurface() override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } @@ -784,7 +784,7 @@ public: virtual ~CompositingRenderTarget() {} #ifdef MOZ_DUMP_PAINTING - virtual TemporaryRef Dump(Compositor* aCompositor) { return nullptr; } + virtual already_AddRefed Dump(Compositor* aCompositor) { return nullptr; } #endif /** @@ -809,7 +809,7 @@ private: * Creates a TextureHost that can be used with any of the existing backends * Not all SurfaceDescriptor types are supported */ -TemporaryRef +already_AddRefed CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); diff --git a/gfx/layers/composite/X11TextureHost.h b/gfx/layers/composite/X11TextureHost.h index 87da8d01bb..37a177517e 100644 --- a/gfx/layers/composite/X11TextureHost.h +++ b/gfx/layers/composite/X11TextureHost.h @@ -35,7 +35,7 @@ public: return mTextureSource; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index 1f9e055017..c8f0065279 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -384,7 +384,7 @@ CompositorD3D11::Initialize() return true; } -TemporaryRef +already_AddRefed CompositorD3D11::CreateDataTextureSource(TextureFlags aFlags) { RefPtr result = new DataTextureSourceD3D11(gfx::SurfaceFormat::UNKNOWN, @@ -427,7 +427,7 @@ CompositorD3D11::GetMaxTextureSize() const return GetMaxTextureSizeForFeatureLevel(mFeatureLevel); } -TemporaryRef +already_AddRefed CompositorD3D11::CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) { @@ -457,7 +457,7 @@ CompositorD3D11::CreateRenderTarget(const gfx::IntRect& aRect, return rt.forget(); } -TemporaryRef +already_AddRefed CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect, const CompositingRenderTarget* aSource, const gfx::IntPoint &aSourcePoint) diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h index 31fa25a9e7..0f06b14616 100644 --- a/gfx/layers/d3d11/CompositorD3D11.h +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -51,7 +51,7 @@ public: virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override; - virtual TemporaryRef + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) override; @@ -59,11 +59,11 @@ public: virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override {} - virtual TemporaryRef + virtual already_AddRefed CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override; - virtual TemporaryRef + virtual already_AddRefed CreateRenderTargetFromSource(const gfx::IntRect& aRect, const CompositingRenderTarget* aSource, const gfx::IntPoint& aSourcePoint) override; diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 07cc79f79e..1f9157f02e 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -141,7 +141,7 @@ static void UnlockD3DTexture(T* aTexture) } } -TemporaryRef +already_AddRefed CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) @@ -213,7 +213,7 @@ TextureClientD3D11::~TextureClientD3D11() } // static -TemporaryRef +already_AddRefed TextureClientD3D11::Create(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, TextureFlags aFlags, @@ -228,7 +228,7 @@ TextureClientD3D11::Create(ISurfaceAllocator* aAllocator, return texture.forget(); } -TemporaryRef +already_AddRefed TextureClientD3D11::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -548,7 +548,7 @@ DXGIYCbCrTextureClient::~DXGIYCbCrTextureClient() } // static -TemporaryRef +already_AddRefed DXGIYCbCrTextureClient::Create(ISurfaceAllocator* aAllocator, TextureFlags aFlags, IUnknown* aTextureY, diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 235f919db0..1a87dafc5e 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -64,7 +64,7 @@ public: // This TextureClient should not be used in a context where we use CreateSimilar // (ex. component alpha) because the underlying texture data is always created by // an external producer. - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE{ return nullptr; } private: @@ -88,7 +88,7 @@ public: virtual ~TextureClientD3D11(); // Creates a TextureClient and init width. - static TemporaryRef + static already_AddRefed Create(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, TextureFlags aFlags, @@ -122,7 +122,7 @@ public: virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags = ALLOC_DEFAULT) override; - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; @@ -148,7 +148,7 @@ public: virtual ~DXGIYCbCrTextureClient(); // Creates a TextureClient and init width. - static TemporaryRef + static already_AddRefed Create(ISurfaceAllocator* aAllocator, TextureFlags aFlags, IUnknown* aTextureY, @@ -183,7 +183,7 @@ public: // This TextureClient should not be used in a context where we use CreateSimilar // (ex. component alpha) because the underlying texture data is always created by // an external producer. - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE{ return nullptr; } private: @@ -312,7 +312,7 @@ public: virtual gfx::IntSize GetSize() const override { return mSize; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; } @@ -351,7 +351,7 @@ public: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE{ return mSize; } - virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE + virtual already_AddRefed GetAsSurface() MOZ_OVERRIDE { return nullptr; } diff --git a/gfx/layers/d3d9/CompositorD3D9.cpp b/gfx/layers/d3d9/CompositorD3D9.cpp index 523eccf148..f20448c4cb 100644 --- a/gfx/layers/d3d9/CompositorD3D9.cpp +++ b/gfx/layers/d3d9/CompositorD3D9.cpp @@ -89,13 +89,13 @@ CompositorD3D9::GetMaxTextureSize() const return mDeviceManager ? mDeviceManager->GetMaxTextureSize() : INT32_MAX; } -TemporaryRef +already_AddRefed CompositorD3D9::CreateDataTextureSource(TextureFlags aFlags) { return MakeAndAddRef(SurfaceFormat::UNKNOWN, this, aFlags); } -TemporaryRef +already_AddRefed CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) { @@ -123,7 +123,7 @@ CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect, return MakeAndAddRef(texture, aInit, aRect); } -TemporaryRef +already_AddRefed CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect, const CompositingRenderTarget *aSource, const gfx::IntPoint &aSourcePoint) diff --git a/gfx/layers/d3d9/CompositorD3D9.h b/gfx/layers/d3d9/CompositorD3D9.h index 2f8a6bf298..e73645575a 100644 --- a/gfx/layers/d3d9/CompositorD3D9.h +++ b/gfx/layers/d3d9/CompositorD3D9.h @@ -34,11 +34,11 @@ public: virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override {} - virtual TemporaryRef + virtual already_AddRefed CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override; - virtual TemporaryRef + virtual already_AddRefed CreateRenderTargetFromSource(const gfx::IntRect &aRect, const CompositingRenderTarget *aSource, const gfx::IntPoint &aSourcePoint) override; @@ -116,7 +116,7 @@ public: // If the offset is 0, 0 that's okay. } - virtual TemporaryRef + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; private: // ensure mSize is up to date with respect to mWidget diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.cpp b/gfx/layers/d3d9/DeviceManagerD3D9.cpp index 297c9fc275..5a4fa2885e 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp +++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp @@ -821,7 +821,7 @@ DeviceManagerD3D9::CreateVertexBuffer() return true; } -TemporaryRef +already_AddRefed DeviceManagerD3D9::CreateTexture(const IntSize &aSize, _D3DFORMAT aFormat, D3DPOOL aPool, diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.h b/gfx/layers/d3d9/DeviceManagerD3D9.h index a29f96d798..d5662ae5f2 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.h +++ b/gfx/layers/d3d9/DeviceManagerD3D9.h @@ -196,7 +196,7 @@ public: * If needed, we keep a record of the new texture, so the texture can be * released. In this case, aTextureHostIDirect3DTexture9 must be non-null. */ - TemporaryRef CreateTexture(const gfx::IntSize &aSize, + already_AddRefed CreateTexture(const gfx::IntSize &aSize, _D3DFORMAT aFormat, D3DPOOL aPool, TextureSourceD3D9* aTextureHostIDirect3DTexture9); diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index 544210a8ec..d800133752 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -46,7 +46,7 @@ TextureSourceD3D9::~TextureSourceD3D9() } } -TemporaryRef +already_AddRefed CreateTextureHostD3D9(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) @@ -165,7 +165,7 @@ CompositingRenderTargetD3D9::GetSize() const * The last three params are out params. * Returns the created texture, or null if we fail. */ -TemporaryRef +already_AddRefed TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager, const IntSize &aSize, _D3DFORMAT aFormat, @@ -221,7 +221,7 @@ FinishTextures(DeviceManagerD3D9* aDeviceManager, nullptr); } -TemporaryRef +already_AddRefed TextureSourceD3D9::DataToTexture(DeviceManagerD3D9* aDeviceManager, unsigned char *aData, int aStride, @@ -250,7 +250,7 @@ TextureSourceD3D9::DataToTexture(DeviceManagerD3D9* aDeviceManager, return texture.forget(); } -TemporaryRef +already_AddRefed TextureSourceD3D9::TextureToTexture(DeviceManagerD3D9* aDeviceManager, IDirect3DTexture9* aTexture, const IntSize& aSize, @@ -274,7 +274,7 @@ TextureSourceD3D9::TextureToTexture(DeviceManagerD3D9* aDeviceManager, return texture.forget(); } -TemporaryRef +already_AddRefed TextureSourceD3D9::SurfaceToTexture(DeviceManagerD3D9* aDeviceManager, gfxWindowsSurface* aSurface, const IntSize& aSize, @@ -573,7 +573,7 @@ CairoTextureClientD3D9::~CairoTextureClientD3D9() MOZ_COUNT_DTOR(CairoTextureClientD3D9); } -TemporaryRef +already_AddRefed CairoTextureClientD3D9::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { RefPtr tex = new CairoTextureClientD3D9(mAllocator, mFormat, @@ -757,7 +757,7 @@ SharedTextureClientD3D9::~SharedTextureClientD3D9() } // static -TemporaryRef +already_AddRefed SharedTextureClientD3D9::Create(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, TextureFlags aFlags, diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h index d63f545da8..d9a01dec9b 100644 --- a/gfx/layers/d3d9/TextureD3D9.h +++ b/gfx/layers/d3d9/TextureD3D9.h @@ -53,14 +53,14 @@ protected: void SetSize(const gfx::IntSize& aSize) { mSize = aSize; } // Helper methods for creating and copying textures. - TemporaryRef InitTextures( + already_AddRefed InitTextures( DeviceManagerD3D9* aDeviceManager, const gfx::IntSize &aSize, _D3DFORMAT aFormat, RefPtr& aSurface, D3DLOCKED_RECT& aLockedRect); - TemporaryRef DataToTexture( + already_AddRefed DataToTexture( DeviceManagerD3D9* aDeviceManager, unsigned char *aData, int aStride, @@ -70,13 +70,13 @@ protected: // aTexture should be in SYSTEMMEM, returns a texture in the default // pool (that is, in video memory). - TemporaryRef TextureToTexture( + already_AddRefed TextureToTexture( DeviceManagerD3D9* aDeviceManager, IDirect3DTexture9* aTexture, const gfx::IntSize& aSize, _D3DFORMAT aFormat); - TemporaryRef SurfaceToTexture( + already_AddRefed SurfaceToTexture( DeviceManagerD3D9* aDeviceManager, gfxWindowsSurface* aSurface, const gfx::IntSize& aSize, @@ -217,7 +217,7 @@ public: virtual bool HasInternalBuffer() const override { return true; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; @@ -249,7 +249,7 @@ public: virtual ~SharedTextureClientD3D9(); // Creates a TextureClient and init width. - static TemporaryRef + static already_AddRefed Create(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, TextureFlags aFlags, @@ -279,7 +279,7 @@ public: // This TextureClient should not be used in a context where we use CreateSimilar // (ex. component alpha) because the underlying texture data is always created by // an external producer. - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags, TextureAllocationFlags) const override { return nullptr; } private: @@ -312,7 +312,7 @@ public: virtual gfx::IntSize GetSize() const override { return mSize; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; } @@ -351,7 +351,7 @@ public: virtual void Unlock() override; - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // TODO: cf bug 872568 } @@ -386,7 +386,7 @@ public: virtual void Unlock() override; virtual gfx::IntSize GetSize() const override { return mSize; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; } diff --git a/gfx/layers/ipc/CompositorBench.cpp b/gfx/layers/ipc/CompositorBench.cpp index ef74ff6b50..22acc07f4a 100644 --- a/gfx/layers/ipc/CompositorBench.cpp +++ b/gfx/layers/ipc/CompositorBench.cpp @@ -129,7 +129,7 @@ public: DrawFrameTrivialQuad(aCompositor, aScreenRect, aStep, effects); } - TemporaryRef CreateEffect(size_t i) { + already_AddRefed CreateEffect(size_t i) { float red; float tmp; red = modf(i * 0.03f, &tmp); @@ -155,7 +155,7 @@ public: DrawFrameStressQuad(aCompositor, aScreenRect, aStep, effects); } - TemporaryRef CreateEffect(size_t i) { + already_AddRefed CreateEffect(size_t i) { float red; float tmp; red = modf(i * 0.03f, &tmp); @@ -240,7 +240,7 @@ public: free(mBuf); } - TemporaryRef CreateEffect(size_t i) { + already_AddRefed CreateEffect(size_t i) { return CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mTexture, Filter::POINT, true); } }; @@ -283,7 +283,7 @@ public: free(mBuf); } - virtual TemporaryRef CreateEffect(size_t i) { + virtual already_AddRefed CreateEffect(size_t i) { return CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mTexture, Filter::POINT, true); } }; @@ -325,7 +325,7 @@ public: free(mBuf); } - virtual TemporaryRef CreateEffect(size_t i) { + virtual already_AddRefed CreateEffect(size_t i) { return CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mTexture, Filter::POINT); } }; @@ -366,7 +366,7 @@ public: free(mBuf); } - virtual TemporaryRef CreateEffect(size_t i) { + virtual already_AddRefed CreateEffect(size_t i) { return CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mTexture, Filter::POINT); } }; diff --git a/gfx/layers/ipc/ISurfaceAllocator.cpp b/gfx/layers/ipc/ISurfaceAllocator.cpp index c6cabea0bb..dbc07fbd8a 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.cpp +++ b/gfx/layers/ipc/ISurfaceAllocator.cpp @@ -76,7 +76,7 @@ GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor, size_t& aSize) } } -TemporaryRef +already_AddRefed GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend) { size_t size; @@ -85,7 +85,7 @@ GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendTyp return image.GetAsDrawTarget(aBackend); } -TemporaryRef +already_AddRefed GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor) { size_t size; diff --git a/gfx/layers/ipc/ISurfaceAllocator.h b/gfx/layers/ipc/ISurfaceAllocator.h index 306b6234e1..cdd86e933b 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.h +++ b/gfx/layers/ipc/ISurfaceAllocator.h @@ -70,8 +70,8 @@ bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface); bool IsSurfaceDescriptorOwned(const SurfaceDescriptor& aDescriptor); bool ReleaseOwnedSurfaceDescriptor(const SurfaceDescriptor& aDescriptor); -TemporaryRef GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend); -TemporaryRef GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor); +already_AddRefed GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend); +already_AddRefed GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor); /** * An interface used to create and destroy surfaces that are shared with the * Compositor process (using shmem, or gralloc, or other platform specific memory) diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index e149f84a1f..cd2e2b76b0 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -681,7 +681,7 @@ ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& } } -TemporaryRef +already_AddRefed ImageBridgeChild::CreateImageClient(CompositableType aType) { if (InImageBridgeChildThread()) { @@ -702,7 +702,7 @@ ImageBridgeChild::CreateImageClient(CompositableType aType) return result.forget(); } -TemporaryRef +already_AddRefed ImageBridgeChild::CreateImageClientNow(CompositableType aType) { MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown); diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index 4c7d9494d5..93fb0511ff 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -9,7 +9,7 @@ #include // for size_t #include // for uint32_t, uint64_t #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for TemporaryRef +#include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTrackerHolder #include "mozilla/layers/CompositableForwarder.h" @@ -191,8 +191,8 @@ public: virtual bool RecvParentAsyncMessages(InfallibleTArray&& aMessages) override; - TemporaryRef CreateImageClient(CompositableType aType); - TemporaryRef CreateImageClientNow(CompositableType aType); + already_AddRefed CreateImageClient(CompositableType aType); + already_AddRefed CreateImageClientNow(CompositableType aType); static void DispatchReleaseImageClient(ImageClient* aClient); static void DispatchReleaseTextureClient(TextureClient* aClient); diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index 69acfc78b6..15945ed1db 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -65,7 +65,7 @@ SharedPlanarYCbCrImage::GetBuffer() return mTextureClient->GetBuffer(); } -TemporaryRef +already_AddRefed SharedPlanarYCbCrImage::GetAsSourceSurface() { if (!mTextureClient) { diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.h b/gfx/layers/ipc/SharedPlanarYCbCrImage.h index 7fa277bd1d..30efcf4f2f 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.h +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.h @@ -36,7 +36,7 @@ public: virtual TextureClient* GetTextureClient(CompositableClient* aClient) override; virtual uint8_t* GetBuffer() override; - virtual TemporaryRef GetAsSourceSurface() override; + virtual already_AddRefed GetAsSourceSurface() override; virtual void SetData(const PlanarYCbCrData& aData) override; virtual void SetDataNoCopy(const Data &aData) override; diff --git a/gfx/layers/ipc/SharedRGBImage.cpp b/gfx/layers/ipc/SharedRGBImage.cpp index 1ff20eac8e..719019b262 100644 --- a/gfx/layers/ipc/SharedRGBImage.cpp +++ b/gfx/layers/ipc/SharedRGBImage.cpp @@ -115,7 +115,7 @@ SharedRGBImage::GetTextureClient(CompositableClient* aClient) return mTextureClient.get(); } -TemporaryRef +already_AddRefed SharedRGBImage::GetAsSourceSurface() { return nullptr; diff --git a/gfx/layers/ipc/SharedRGBImage.h b/gfx/layers/ipc/SharedRGBImage.h index 255fcda3bd..2e871a24c0 100644 --- a/gfx/layers/ipc/SharedRGBImage.h +++ b/gfx/layers/ipc/SharedRGBImage.h @@ -53,7 +53,7 @@ public: size_t GetBufferSize(); - TemporaryRef GetAsSourceSurface() override; + already_AddRefed GetAsSourceSurface() override; bool Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat); private: diff --git a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp index 0bca6b5b47..09cd4d181e 100644 --- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp +++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp @@ -69,7 +69,7 @@ CompositingRenderTargetOGL::BindRenderTarget() } #ifdef MOZ_DUMP_PAINTING -TemporaryRef +already_AddRefed CompositingRenderTargetOGL::Dump(Compositor* aCompositor) { MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED); diff --git a/gfx/layers/opengl/CompositingRenderTargetOGL.h b/gfx/layers/opengl/CompositingRenderTargetOGL.h index bc6f9190fc..e293d076a3 100644 --- a/gfx/layers/opengl/CompositingRenderTargetOGL.h +++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h @@ -10,7 +10,7 @@ #include "GLDefs.h" // for GLenum, LOCAL_GL_FRAMEBUFFER, etc #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef +#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed #include "mozilla/gfx/Point.h" // for IntSize, IntSizeTyped #include "mozilla/gfx/Types.h" // for SurfaceFormat, etc #include "mozilla/layers/Compositor.h" // for SurfaceInitMode, etc @@ -79,7 +79,7 @@ public: * Create a render target around the default FBO, for rendering straight to * the window. */ - static TemporaryRef + static already_AddRefed RenderTargetForWindow(CompositorOGL* aCompositor, const gfx::IntSize& aSize) { @@ -146,7 +146,7 @@ public: } #ifdef MOZ_DUMP_PAINTING - virtual TemporaryRef Dump(Compositor* aCompositor) override; + virtual already_AddRefed Dump(Compositor* aCompositor) override; #endif const gfx::IntSize& GetInitSize() const { diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 2c8bd6430f..525794a1fa 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -465,7 +465,7 @@ CompositorOGL::PrepareViewport(const gfx::IntSize& aSize) mProjMatrix = matrix3d; } -TemporaryRef +already_AddRefed CompositorOGL::CreateRenderTarget(const IntRect &aRect, SurfaceInitMode aInit) { MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size"); @@ -483,7 +483,7 @@ CompositorOGL::CreateRenderTarget(const IntRect &aRect, SurfaceInitMode aInit) return surface.forget(); } -TemporaryRef +already_AddRefed CompositorOGL::CreateRenderTargetFromSource(const IntRect &aRect, const CompositingRenderTarget *aSource, const IntPoint &aSourcePoint) @@ -1410,7 +1410,7 @@ CompositorOGL::Resume() return true; } -TemporaryRef +already_AddRefed CompositorOGL::CreateDataTextureSource(TextureFlags aFlags) { return MakeAndAddRef(this, aFlags); diff --git a/gfx/layers/opengl/CompositorOGL.h b/gfx/layers/opengl/CompositorOGL.h index 8998441f58..c0f686c2b0 100644 --- a/gfx/layers/opengl/CompositorOGL.h +++ b/gfx/layers/opengl/CompositorOGL.h @@ -14,7 +14,7 @@ #include "Units.h" // for ScreenPoint #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Attributes.h" // for override, final -#include "mozilla/RefPtr.h" // for TemporaryRef, RefPtr +#include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr #include "mozilla/gfx/2D.h" // for DrawTarget #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Point.h" // for IntSize, Point @@ -197,7 +197,7 @@ protected: virtual ~CompositorOGL(); public: - virtual TemporaryRef + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; virtual bool Initialize() override; @@ -218,10 +218,10 @@ public: return result; } - virtual TemporaryRef + virtual already_AddRefed CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override; - virtual TemporaryRef + virtual already_AddRefed CreateRenderTargetFromSource(const gfx::IntRect &aRect, const CompositingRenderTarget *aSource, const gfx::IntPoint &aSourcePoint) override; diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp index 98fae523bf..5c0a22bfe1 100644 --- a/gfx/layers/opengl/GrallocTextureClient.cpp +++ b/gfx/layers/opengl/GrallocTextureClient.cpp @@ -44,7 +44,7 @@ GrallocTextureClientOGL::~GrallocTextureClientOGL() } } -TemporaryRef +already_AddRefed GrallocTextureClientOGL::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const { @@ -350,7 +350,7 @@ GrallocTextureClientOGL::GetBufferSize() const return 0; } -/*static*/ TemporaryRef +/*static*/ already_AddRefed GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf, TextureFlags flags) { diff --git a/gfx/layers/opengl/GrallocTextureClient.h b/gfx/layers/opengl/GrallocTextureClient.h index a352d51d48..7849782c0c 100644 --- a/gfx/layers/opengl/GrallocTextureClient.h +++ b/gfx/layers/opengl/GrallocTextureClient.h @@ -110,11 +110,11 @@ public: return mMediaBuffer; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; - static TemporaryRef FromSharedSurface(gl::SharedSurface* surf, + static already_AddRefed FromSharedSurface(gl::SharedSurface* surf, TextureFlags flags); protected: diff --git a/gfx/layers/opengl/GrallocTextureHost.cpp b/gfx/layers/opengl/GrallocTextureHost.cpp index e6e80a0eb0..8565b6287b 100644 --- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -227,7 +227,7 @@ GrallocTextureHostOGL::GetRenderState() return LayerRenderState(); } -TemporaryRef +already_AddRefed GrallocTextureHostOGL::GetAsSurface() { android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); uint8_t* grallocData; diff --git a/gfx/layers/opengl/GrallocTextureHost.h b/gfx/layers/opengl/GrallocTextureHost.h index c99514e6a3..4bd2994aca 100644 --- a/gfx/layers/opengl/GrallocTextureHost.h +++ b/gfx/layers/opengl/GrallocTextureHost.h @@ -62,7 +62,7 @@ public: } #endif - virtual TemporaryRef GetAsSurface() override; + virtual already_AddRefed GetAsSurface() override; bool IsValid() const; diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp index 344df16755..a2b41d9ccd 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp @@ -23,7 +23,7 @@ MacIOSurfaceTextureClientOGL::~MacIOSurfaceTextureClientOGL() } // static -TemporaryRef +already_AddRefed MacIOSurfaceTextureClientOGL::Create(ISurfaceAllocator* aAllocator, TextureFlags aFlags, MacIOSurface* aSurface) @@ -76,7 +76,7 @@ MacIOSurfaceTextureClientOGL::GetSize() const return gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight()); } -TemporaryRef +already_AddRefed MacIOSurfaceTextureClientOGL::GetAsSurface() { RefPtr surf = mSurface->GetAsSurface(); diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h index b7e2fa0550..e7ab59a00a 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h @@ -22,7 +22,7 @@ public: virtual ~MacIOSurfaceTextureClientOGL(); // Creates a TextureClient and init width. - static TemporaryRef + static already_AddRefed Create(ISurfaceAllocator* aAllocator, TextureFlags aFlags, MacIOSurface* aSurface); @@ -41,12 +41,12 @@ public: virtual bool HasInternalBuffer() const override { return false; } - virtual TemporaryRef GetAsSurface() override; + virtual already_AddRefed GetAsSurface() override; // This TextureClient should not be used in a context where we use CreateSimilar // (ex. component alpha) because the underlying texture data is always created by // an external producer. - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags, TextureAllocationFlags) const override { return nullptr; } protected: diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index 4ae1453ea5..6951633ab9 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -79,7 +79,7 @@ public: return mTextureSource; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/opengl/TextureClientOGL.h b/gfx/layers/opengl/TextureClientOGL.h index 9631d15b6c..46cdca3b49 100644 --- a/gfx/layers/opengl/TextureClientOGL.h +++ b/gfx/layers/opengl/TextureClientOGL.h @@ -50,7 +50,7 @@ public: return gfx::SurfaceFormat::UNKNOWN; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override { @@ -101,7 +101,7 @@ public: return gfx::SurfaceFormat::UNKNOWN; } - virtual TemporaryRef + virtual already_AddRefed CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT, TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override { diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index 37fced4d49..8dfa6239c8 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -41,7 +41,7 @@ namespace layers { class Compositor; -TemporaryRef +already_AddRefed CreateTextureHostOGL(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags) diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 19592a6ebb..abd727e3db 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -405,7 +405,7 @@ public: return mTextureSource; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } @@ -497,7 +497,7 @@ public: return mTextureSource; } - virtual TemporaryRef GetAsSurface() override + virtual already_AddRefed GetAsSurface() override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/src/FilterSupport.cpp b/gfx/src/FilterSupport.cpp index acdffb6a7b..06121afa01 100644 --- a/gfx/src/FilterSupport.cpp +++ b/gfx/src/FilterSupport.cpp @@ -98,7 +98,7 @@ namespace gfx { namespace FilterWrappers { - static TemporaryRef + static already_AddRefed Unpremultiply(DrawTarget* aDT, FilterNode* aInput) { RefPtr filter = aDT->CreateFilter(FilterType::UNPREMULTIPLY); @@ -106,7 +106,7 @@ namespace FilterWrappers { return filter.forget(); } - static TemporaryRef + static already_AddRefed Premultiply(DrawTarget* aDT, FilterNode* aInput) { RefPtr filter = aDT->CreateFilter(FilterType::PREMULTIPLY); @@ -114,7 +114,7 @@ namespace FilterWrappers { return filter.forget(); } - static TemporaryRef + static already_AddRefed LinearRGBToSRGB(DrawTarget* aDT, FilterNode* aInput) { RefPtr transfer = aDT->CreateFilter(FilterType::DISCRETE_TRANSFER); @@ -129,7 +129,7 @@ namespace FilterWrappers { return transfer.forget(); } - static TemporaryRef + static already_AddRefed SRGBToLinearRGB(DrawTarget* aDT, FilterNode* aInput) { RefPtr transfer = aDT->CreateFilter(FilterType::DISCRETE_TRANSFER); @@ -144,7 +144,7 @@ namespace FilterWrappers { return transfer.forget(); } - static TemporaryRef + static already_AddRefed Crop(DrawTarget* aDT, FilterNode* aInputFilter, const IntRect& aRect) { RefPtr filter = aDT->CreateFilter(FilterType::CROP); @@ -153,7 +153,7 @@ namespace FilterWrappers { return filter.forget(); } - static TemporaryRef + static already_AddRefed Offset(DrawTarget* aDT, FilterNode* aInputFilter, const IntPoint& aOffset) { RefPtr filter = aDT->CreateFilter(FilterType::TRANSFORM); @@ -162,7 +162,7 @@ namespace FilterWrappers { return filter.forget(); } - static TemporaryRef + static already_AddRefed GaussianBlur(DrawTarget* aDT, FilterNode* aInputFilter, const Size& aStdDeviation) { float stdX = float(std::min(aStdDeviation.width, kMaxStdDeviation)); @@ -184,7 +184,7 @@ namespace FilterWrappers { return filterV.forget(); } - static TemporaryRef + static already_AddRefed Clear(DrawTarget* aDT) { RefPtr filter = aDT->CreateFilter(FilterType::FLOOD); @@ -192,7 +192,7 @@ namespace FilterWrappers { return filter.forget(); } - static TemporaryRef + static already_AddRefed ForSurface(DrawTarget* aDT, SourceSurface* aSurface, const IntPoint& aSurfacePosition) { @@ -203,7 +203,7 @@ namespace FilterWrappers { return filter.forget(); } - static TemporaryRef + static already_AddRefed ToAlpha(DrawTarget* aDT, FilterNode* aInput) { float zero = 0.0f; @@ -240,13 +240,13 @@ public: ColorModel aOriginalColorModel); // Get a FilterNode for the specified color model, guaranteed to be non-null. - TemporaryRef ForColorModel(ColorModel aColorModel); + already_AddRefed ForColorModel(ColorModel aColorModel); AlphaModel OriginalAlphaModel() const { return mOriginalColorModel.mAlphaModel; } private: // Create the required FilterNode that will be cached by ForColorModel. - TemporaryRef WrapForColorModel(ColorModel aColorModel); + already_AddRefed WrapForColorModel(ColorModel aColorModel); RefPtr mDT; ColorModel mOriginalColorModel; @@ -274,7 +274,7 @@ FilterCachedColorModels::FilterCachedColorModels(DrawTarget* aDT, } } -TemporaryRef +already_AddRefed FilterCachedColorModels::ForColorModel(ColorModel aColorModel) { if (!mFilterForColorModel[aColorModel.ToIndex()]) { @@ -284,7 +284,7 @@ FilterCachedColorModels::ForColorModel(ColorModel aColorModel) return filter.forget(); } -TemporaryRef +already_AddRefed FilterCachedColorModels::WrapForColorModel(ColorModel aColorModel) { // Convert one aspect at a time and recurse. @@ -650,7 +650,7 @@ const int32_t kMorphologyMaxRadius = 100000; // aSourceRegions contains the filter primitive subregions of the source // primitives; only needed for eTile primitives. // aInputImages carries additional surfaces that are used by eImage primitives. -static TemporaryRef +static already_AddRefed FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescription, DrawTarget* aDT, nsTArray >& aSources, @@ -1121,7 +1121,7 @@ OutputAlphaModelForPrimitive(const FilterPrimitiveDescription& aDescr, } // Returns the output FilterNode, in premultiplied sRGB space. -static TemporaryRef +static already_AddRefed FilterNodeGraphFromDescription(DrawTarget* aDT, const FilterDescription& aFilter, const Rect& aResultNeededRect, diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 7c44b154ec..52b0bc9ffa 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -61,6 +61,7 @@ private: class MockContentController : public GoannaContentController { public: MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&)); + MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination)); MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration)); MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&)); MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&)); diff --git a/gfx/tests/gtest/TestCompositor.cpp b/gfx/tests/gtest/TestCompositor.cpp index cd5251a4e1..ec52331231 100644 --- a/gfx/tests/gtest/TestCompositor.cpp +++ b/gfx/tests/gtest/TestCompositor.cpp @@ -96,7 +96,7 @@ struct LayerManagerData { {} }; -static TemporaryRef CreateTestCompositor(LayersBackend backend, MockWidget* widget) +static already_AddRefed CreateTestCompositor(LayersBackend backend, MockWidget* widget) { gfxPrefs::GetSingleton(); @@ -170,7 +170,7 @@ static std::vector GetPlatformBackends() return backends; } -static TemporaryRef CreateDT() +static already_AddRefed CreateDT() { return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( IntSize(gCompWidth, gCompHeight), SurfaceFormat::B8G8R8A8); diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp index 284676eb49..d0afbc3710 100644 --- a/gfx/thebes/gfxAndroidPlatform.cpp +++ b/gfx/thebes/gfxAndroidPlatform.cpp @@ -341,7 +341,7 @@ gfxAndroidPlatform::MakePlatformFont(const nsAString& aFontName, aLength); } -TemporaryRef +already_AddRefed gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { return GetScaledFontForFontWithCairoSkia(aTarget, aFont); diff --git a/gfx/thebes/gfxAndroidPlatform.h b/gfx/thebes/gfxAndroidPlatform.h index b63462ba3e..f7c145c28b 100644 --- a/gfx/thebes/gfxAndroidPlatform.h +++ b/gfx/thebes/gfxAndroidPlatform.h @@ -38,7 +38,7 @@ public: virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; } - mozilla::TemporaryRef + already_AddRefed GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont); // to support IPC font list (sharing between chrome and content) diff --git a/gfx/thebes/gfxBlur.cpp b/gfx/thebes/gfxBlur.cpp index 67e6e22015..78c40596c8 100644 --- a/gfx/thebes/gfxBlur.cpp +++ b/gfx/thebes/gfxBlur.cpp @@ -115,7 +115,7 @@ DrawBlur(gfxContext* aDestinationCtx, } } -TemporaryRef +already_AddRefed gfxAlphaBoxBlur::DoBlur(DrawTarget* aDT, IntPoint* aTopLeft) { mBlur->Blur(mData); diff --git a/gfx/thebes/gfxBlur.h b/gfx/thebes/gfxBlur.h index bac188ba13..187187bf3d 100644 --- a/gfx/thebes/gfxBlur.h +++ b/gfx/thebes/gfxBlur.h @@ -89,7 +89,7 @@ public: return mContext; } - mozilla::TemporaryRef DoBlur(mozilla::gfx::DrawTarget* aDT, mozilla::gfx::IntPoint* aTopLeft); + already_AddRefed DoBlur(mozilla::gfx::DrawTarget* aDT, mozilla::gfx::IntPoint* aTopLeft); /** * Does the actual blurring/spreading and mask applying. Users of this diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 8a6a2173b0..15e12ff1cd 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -201,7 +201,7 @@ gfxContext::ClosePath() mPathBuilder->Close(); } -TemporaryRef gfxContext::GetPath() +already_AddRefed gfxContext::GetPath() { EnsurePath(); RefPtr path(mPath); @@ -918,7 +918,7 @@ gfxContext::PopGroup() return pat.forget(); } -TemporaryRef +already_AddRefed gfxContext::PopGroupToSurface(Matrix* aTransform) { RefPtr src = mDT->Snapshot(); diff --git a/gfx/thebes/gfxContext.h b/gfx/thebes/gfxContext.h index 7e2af9bc05..12113ffe80 100644 --- a/gfx/thebes/gfxContext.h +++ b/gfx/thebes/gfxContext.h @@ -123,7 +123,7 @@ public: /** * Returns the current path. */ - mozilla::TemporaryRef GetPath(); + already_AddRefed GetPath(); /** * Sets the given path as the current path. @@ -471,7 +471,7 @@ public: already_AddRefed PopGroup(); void PopGroupToSource(); - mozilla::TemporaryRef + already_AddRefed PopGroupToSurface(mozilla::gfx::Matrix* aMatrix); mozilla::gfx::Point GetDeviceOffset() const; diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index 519a8f98e1..4797b3b2b2 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -597,7 +597,7 @@ gfxDWriteFont::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) return width; } -TemporaryRef +already_AddRefed gfxDWriteFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams) { if (UsingClearType()) { @@ -669,7 +669,7 @@ gfxDWriteFont::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, AddSizeOfExcludingThis(aMallocSizeOf, aSizes); } -TemporaryRef +already_AddRefed gfxDWriteFont::GetScaledFont(mozilla::gfx::DrawTarget *aTarget) { bool wantCairo = aTarget->GetBackendType() == BackendType::CAIRO; diff --git a/gfx/thebes/gfxDWriteFonts.h b/gfx/thebes/gfxDWriteFonts.h index 2d45c4ed77..834913548f 100644 --- a/gfx/thebes/gfxDWriteFonts.h +++ b/gfx/thebes/gfxDWriteFonts.h @@ -59,7 +59,7 @@ public: virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) override; virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, @@ -69,7 +69,7 @@ public: virtual FontType GetType() const { return FONT_TYPE_DWRITE; } - virtual mozilla::TemporaryRef + virtual already_AddRefed GetScaledFont(mozilla::gfx::DrawTarget *aTarget) override; virtual cairo_scaled_font_t *GetCairoScaledFont() override; diff --git a/gfx/thebes/gfxFT2Fonts.cpp b/gfx/thebes/gfxFT2Fonts.cpp index 26ae52e9ef..3d694069ec 100644 --- a/gfx/thebes/gfxFT2Fonts.cpp +++ b/gfx/thebes/gfxFT2Fonts.cpp @@ -230,7 +230,7 @@ gfxFT2Font::AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, } #ifdef USE_SKIA -mozilla::TemporaryRef +already_AddRefed gfxFT2Font::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams) { mozilla::gfx::FontHinting hinting; diff --git a/gfx/thebes/gfxFT2Fonts.h b/gfx/thebes/gfxFT2Fonts.h index 7309d6c5cc..ca00bf44e6 100644 --- a/gfx/thebes/gfxFT2Fonts.h +++ b/gfx/thebes/gfxFT2Fonts.h @@ -60,7 +60,7 @@ public: // new functions FontCacheSizes* aSizes) const; #ifdef USE_SKIA - virtual mozilla::TemporaryRef + virtual already_AddRefed GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) override; #endif diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index a9a91c0d87..025b7bf5ff 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -1453,7 +1453,7 @@ public: gfxFloat GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID); // Return Azure GlyphRenderingOptions for drawing this font. - virtual mozilla::TemporaryRef + virtual already_AddRefed GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) { return nullptr; } @@ -1742,7 +1742,7 @@ public: virtual FontType GetType() const = 0; - virtual mozilla::TemporaryRef GetScaledFont(DrawTarget* aTarget) + virtual already_AddRefed GetScaledFont(DrawTarget* aTarget) { return gfxPlatform::GetPlatform()->GetScaledFontForFont(aTarget, this); } bool KerningDisabled() { diff --git a/gfx/thebes/gfxImageSurface.cpp b/gfx/thebes/gfxImageSurface.cpp index 5c17039757..d9a3ce892b 100644 --- a/gfx/thebes/gfxImageSurface.cpp +++ b/gfx/thebes/gfxImageSurface.cpp @@ -318,7 +318,7 @@ gfxImageSurface::CopyTo(SourceSurface *aSurface) { return true; } -TemporaryRef +already_AddRefed gfxImageSurface::CopyToB8G8R8A8DataSourceSurface() { RefPtr dataSurface = diff --git a/gfx/thebes/gfxImageSurface.h b/gfx/thebes/gfxImageSurface.h index ac8111bb16..cdc17f995e 100644 --- a/gfx/thebes/gfxImageSurface.h +++ b/gfx/thebes/gfxImageSurface.h @@ -114,7 +114,7 @@ public: * Copy to a Moz2D DataSourceSurface. * Marked as virtual so that browsercomps can access this method. */ - virtual mozilla::TemporaryRef CopyToB8G8R8A8DataSourceSurface(); + virtual already_AddRefed CopyToB8G8R8A8DataSourceSurface(); /* return new Subimage with pointing to original image starting from aRect.pos * and size of aRect.size. New subimage keeping current image reference diff --git a/gfx/thebes/gfxMacFont.cpp b/gfx/thebes/gfxMacFont.cpp index 3163960fc4..7519dadba8 100644 --- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -427,7 +427,7 @@ gfxMacFont::InitMetricsFromPlatform() mIsValid = true; } -TemporaryRef +already_AddRefed gfxMacFont::GetScaledFont(DrawTarget *aTarget) { if (!mAzureScaledFont) { @@ -441,7 +441,7 @@ gfxMacFont::GetScaledFont(DrawTarget *aTarget) return scaledFont.forget(); } -TemporaryRef +already_AddRefed gfxMacFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams) { if (aRunParams) { diff --git a/gfx/thebes/gfxMacFont.h b/gfx/thebes/gfxMacFont.h index a05f65bc8a..62e0ded27e 100644 --- a/gfx/thebes/gfxMacFont.h +++ b/gfx/thebes/gfxMacFont.h @@ -48,10 +48,10 @@ public: virtual int32_t GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed GetScaledFont(mozilla::gfx::DrawTarget *aTarget) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) override; virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, diff --git a/gfx/thebes/gfxPangoFonts.cpp b/gfx/thebes/gfxPangoFonts.cpp index 64aaf71611..44820d5893 100644 --- a/gfx/thebes/gfxPangoFonts.cpp +++ b/gfx/thebes/gfxPangoFonts.cpp @@ -665,7 +665,7 @@ public: const gfxFontStyle *aFontStyle); #ifdef USE_SKIA - virtual mozilla::TemporaryRef + virtual already_AddRefed GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) override; #endif @@ -2131,7 +2131,7 @@ ApplyGdkScreenFontOptions(FcPattern *aPattern) #endif // MOZ_WIDGET_GTK2 #ifdef USE_SKIA -mozilla::TemporaryRef +already_AddRefed gfxFcFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams) { cairo_scaled_font_t *scaled_font = CairoScaledFont(); diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index efc391fde0..30894baff8 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -724,7 +724,7 @@ gfxPlatform::~gfxPlatform() cairo_user_data_key_t kDrawTarget; -TemporaryRef +already_AddRefed gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize) { SurfaceFormat format = Optimal2DFormatForContent(aSurface->GetContentType()); @@ -736,7 +736,7 @@ gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aS // This is a temporary function used by ContentClient to build a DrawTarget // around the gfxASurface. This should eventually be replaced by plumbing // the DrawTarget through directly -TemporaryRef +already_AddRefed gfxPlatform::CreateDrawTargetForUpdateSurface(gfxASurface *aSurface, const IntSize& aSize) { #ifdef XP_MACOSX @@ -789,7 +789,7 @@ gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface) aSurface->SetData(&kSourceSurface, nullptr, nullptr); } -/* static */ TemporaryRef +/* static */ already_AddRefed gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface) { if (!aSurface->CairoSurface() || aSurface->CairoStatus()) { @@ -941,7 +941,7 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa return srcBuffer.forget(); } -TemporaryRef +already_AddRefed gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface) { nsRefPtr image = aSurface->GetAsImageSurface(); @@ -967,7 +967,7 @@ gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface) return result.forget(); } -TemporaryRef +already_AddRefed gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { NativeFont nativeFont; @@ -1140,7 +1140,7 @@ gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL() return true; } -TemporaryRef +already_AddRefed gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat) { // There is a bunch of knowledge in the gfxPlatform heirarchy about how to @@ -1164,7 +1164,7 @@ gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSi } } -TemporaryRef +already_AddRefed gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize& aSize, SurfaceFormat aFormat) { NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend."); @@ -1182,14 +1182,14 @@ gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize& aSize, SurfaceFormat #endif } -TemporaryRef +already_AddRefed gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceFormat aFormat) { NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend."); return CreateDrawTargetForBackend(mContentBackend, aSize, aFormat); } -TemporaryRef +already_AddRefed gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat) { NS_ASSERTION(mContentBackend != BackendType::NONE, "No backend."); @@ -2277,7 +2277,7 @@ gfxPlatform::DisableBufferRotation() sBufferRotationCheckPref = false; } -TemporaryRef +already_AddRefed gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont) { NativeFont nativeFont; diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 3fca457fb7..cbcef87e8e 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -212,10 +212,10 @@ public: * support the DrawTarget we get back. * See SupportsAzureContentForDrawTarget. */ - virtual mozilla::TemporaryRef + virtual already_AddRefed CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize); - virtual mozilla::TemporaryRef + virtual already_AddRefed CreateDrawTargetForUpdateSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize); /* @@ -230,24 +230,24 @@ public: * PluginInstanceChild (where we can't call gfxPlatform::GetPlatform() * because the prefs service can only be accessed from the main process). */ - static mozilla::TemporaryRef + static already_AddRefed GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface); static void ClearSourceSurfaceForSurface(gfxASurface *aSurface); - static mozilla::TemporaryRef + static already_AddRefed GetWrappedDataSourceSurface(gfxASurface *aSurface); - virtual mozilla::TemporaryRef + virtual already_AddRefed GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont); - mozilla::TemporaryRef + already_AddRefed CreateOffscreenContentDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat); - mozilla::TemporaryRef + already_AddRefed CreateOffscreenCanvasDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat); - virtual mozilla::TemporaryRef + virtual already_AddRefed CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize, int32_t aStride, mozilla::gfx::SurfaceFormat aFormat); @@ -625,7 +625,7 @@ protected: * Helper method, creates a draw target for a specific Azure backend. * Used by CreateOffscreenDrawTarget. */ - mozilla::TemporaryRef + already_AddRefed CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend, const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat); @@ -664,7 +664,7 @@ protected: */ static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName); - static mozilla::TemporaryRef + static already_AddRefed GetScaledFontForFontWithCairoSkia(mozilla::gfx::DrawTarget* aTarget, gfxFont* aFont); int8_t mAllowDownloadableFonts; diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 84d127d57b..0a6c0e6010 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -440,7 +440,7 @@ gfxPlatformGtk::GetGdkDrawable(cairo_surface_t *target) } #endif -TemporaryRef +already_AddRefed gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { return GetScaledFontForFontWithCairoSkia(aTarget, aFont); diff --git a/gfx/thebes/gfxPlatformGtk.h b/gfx/thebes/gfxPlatformGtk.h index bbf12f2fc2..14df8a40d0 100644 --- a/gfx/thebes/gfxPlatformGtk.h +++ b/gfx/thebes/gfxPlatformGtk.h @@ -32,7 +32,7 @@ public: CreateOffscreenSurface(const IntSize& size, gfxContentType contentType) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont) override; virtual nsresult GetFontList(nsIAtom *aLangGroup, diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp index b9fc252921..53422f8b74 100644 --- a/gfx/thebes/gfxPlatformMac.cpp +++ b/gfx/thebes/gfxPlatformMac.cpp @@ -121,7 +121,7 @@ gfxPlatformMac::CreateOffscreenSurface(const IntSize& size, return newSurface.forget(); } -TemporaryRef +already_AddRefed gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { gfxMacFont *font = static_cast(aFont); diff --git a/gfx/thebes/gfxPlatformMac.h b/gfx/thebes/gfxPlatformMac.h index 943e6c4d5b..b70f991ef8 100644 --- a/gfx/thebes/gfxPlatformMac.h +++ b/gfx/thebes/gfxPlatformMac.h @@ -29,7 +29,7 @@ public: CreateOffscreenSurface(const IntSize& size, gfxContentType contentType) override; - mozilla::TemporaryRef + already_AddRefed GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont) override; nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) override; diff --git a/gfx/thebes/gfxQtPlatform.cpp b/gfx/thebes/gfxQtPlatform.cpp index 61046abc0f..2ad787ca27 100644 --- a/gfx/thebes/gfxQtPlatform.cpp +++ b/gfx/thebes/gfxQtPlatform.cpp @@ -202,7 +202,7 @@ gfxQtPlatform::GetScreenDepth() const return mScreenDepth; } -TemporaryRef +already_AddRefed gfxQtPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont* aFont) { return GetScaledFontForFontWithCairoSkia(aTarget, aFont); diff --git a/gfx/thebes/gfxQtPlatform.h b/gfx/thebes/gfxQtPlatform.h index 27d0ea474e..4322bf228b 100644 --- a/gfx/thebes/gfxQtPlatform.h +++ b/gfx/thebes/gfxQtPlatform.h @@ -30,7 +30,7 @@ public: CreateOffscreenSurface(const IntSize& size, gfxContentType contentType) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont) override; virtual nsresult GetFontList(nsIAtom *aLangGroup, diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index a4015ea373..2f387cd1f6 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -322,7 +322,7 @@ MapSrcAndCreateMappedDest(DataSourceSurface* srcSurf, return true; } -TemporaryRef +already_AddRefed gfxUtils::CreatePremultipliedDataSurface(DataSourceSurface* srcSurf) { RefPtr destSurf; @@ -343,7 +343,7 @@ gfxUtils::CreatePremultipliedDataSurface(DataSourceSurface* srcSurf) return destSurf.forget(); } -TemporaryRef +already_AddRefed gfxUtils::CreateUnpremultipliedDataSurface(DataSourceSurface* srcSurf) { RefPtr destSurf; @@ -705,7 +705,7 @@ ClipToRegionInternal(gfxContext* aContext, const nsIntRegion& aRegion) aContext->Clip(); } -static TemporaryRef +static already_AddRefed PathFromRegionInternal(DrawTarget* aTarget, const nsIntRegion& aRegion) { RefPtr pb = aTarget->CreatePathBuilder(); @@ -1020,7 +1020,7 @@ gfxUtils::ConvertYCbCrToRGB(const PlanarYCbCrData& aData, cairo_destroy(ctx); } -/* static */ TemporaryRef +/* static */ already_AddRefed gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface, SurfaceFormat aFormat) { diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h index d3d06c6856..b7acb3f969 100644 --- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -56,9 +56,9 @@ public: static bool UnpremultiplyDataSurface(DataSourceSurface* srcSurf, DataSourceSurface* destSurf); - static mozilla::TemporaryRef + static already_AddRefed CreatePremultipliedDataSurface(DataSourceSurface* srcSurf); - static mozilla::TemporaryRef + static already_AddRefed CreateUnpremultipliedDataSurface(DataSourceSurface* srcSurf); static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength); @@ -207,7 +207,7 @@ public: * realize format conversion may involve expensive copying/uploading/ * readback.) */ - static mozilla::TemporaryRef + static already_AddRefed CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface, SurfaceFormat aFormat); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index bcf90ad5c2..906763459e 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -776,7 +776,7 @@ gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& size, return surf.forget(); } -TemporaryRef +already_AddRefed gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) { @@ -1982,7 +1982,7 @@ gfxWindowsPlatform::InitD3D11Devices() d3d11Module.disown(); } -TemporaryRef +already_AddRefed gfxWindowsPlatform::CreateD3D11DecoderDevice() { nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll")); diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 404ed372c1..74874758de 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -120,7 +120,7 @@ public: CreateOffscreenSurface(const IntSize& size, gfxContentType contentType) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont); enum RenderMode { @@ -249,7 +249,7 @@ public: ID3D11Device *GetD3D11MediaDevice(); // Create a D3D11 device to be used for DXVA decoding. - mozilla::TemporaryRef CreateD3D11DecoderDevice(); + already_AddRefed CreateD3D11DecoderDevice(); mozilla::layers::ReadbackManagerD3D11* GetReadbackManager(); diff --git a/image/ClippedImage.cpp b/image/ClippedImage.cpp index 57195b9acf..a1a9a8cf20 100644 --- a/image/ClippedImage.cpp +++ b/image/ClippedImage.cpp @@ -33,7 +33,7 @@ namespace image { class ClippedImageCachedSurface { public: - ClippedImageCachedSurface(TemporaryRef aSurface, + ClippedImageCachedSurface(already_AddRefed aSurface, const nsIntSize& aSize, const Maybe& aSVGContext, float aFrame, @@ -60,7 +60,7 @@ public: mFlags == aFlags; } - TemporaryRef Surface() { + already_AddRefed Surface() { RefPtr surf(mSurface); return surf.forget(); } @@ -211,14 +211,14 @@ ClippedImage::GetIntrinsicRatio(nsSize* aRatio) return NS_OK; } -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) ClippedImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { return GetFrameInternal(mClip.Size(), Nothing(), aWhichFrame, aFlags); } -TemporaryRef +already_AddRefed ClippedImage::GetFrameInternal(const nsIntSize& aSize, const Maybe& aSVGContext, uint32_t aWhichFrame, diff --git a/image/ClippedImage.h b/image/ClippedImage.h index 76ff57da00..2165ba3c5d 100644 --- a/image/ClippedImage.h +++ b/image/ClippedImage.h @@ -35,7 +35,7 @@ public: NS_IMETHOD GetHeight(int32_t* aHeight) override; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override; NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override; - NS_IMETHOD_(TemporaryRef) + NS_IMETHOD_(already_AddRefed) GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override; NS_IMETHOD GetImageContainer(layers::LayerManager* aManager, layers::ImageContainer** _retval) override; @@ -60,7 +60,7 @@ protected: virtual ~ClippedImage(); private: - TemporaryRef + already_AddRefed GetFrameInternal(const nsIntSize& aSize, const Maybe& aSVGContext, uint32_t aWhichFrame, diff --git a/image/DynamicImage.cpp b/image/DynamicImage.cpp index 19ec5de991..a967762ca5 100644 --- a/image/DynamicImage.cpp +++ b/image/DynamicImage.cpp @@ -175,7 +175,7 @@ DynamicImage::GetAnimated(bool* aAnimated) return NS_OK; } -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) DynamicImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { diff --git a/image/FrozenImage.cpp b/image/FrozenImage.cpp index 5da2a109ad..fc76f192a4 100644 --- a/image/FrozenImage.cpp +++ b/image/FrozenImage.cpp @@ -37,7 +37,7 @@ FrozenImage::GetAnimated(bool* aAnimated) return rv; } -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) FrozenImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { diff --git a/image/FrozenImage.h b/image/FrozenImage.h index 4e7ae769ec..48d08226c2 100644 --- a/image/FrozenImage.h +++ b/image/FrozenImage.h @@ -35,7 +35,7 @@ public: virtual void DecrementAnimationConsumers() override; NS_IMETHOD GetAnimated(bool* aAnimated) override; - NS_IMETHOD_(TemporaryRef) + NS_IMETHOD_(already_AddRefed) GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override; NS_IMETHOD GetImageContainer(layers::LayerManager* aManager, layers::ImageContainer** _retval) override; diff --git a/image/ImageWrapper.cpp b/image/ImageWrapper.cpp index 96f9aa8114..2aeb7249a6 100644 --- a/image/ImageWrapper.cpp +++ b/image/ImageWrapper.cpp @@ -179,7 +179,7 @@ ImageWrapper::GetAnimated(bool* aAnimated) return mInnerImage->GetAnimated(aAnimated); } -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) ImageWrapper::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { diff --git a/image/OrientedImage.cpp b/image/OrientedImage.cpp index 7fea526ca6..28b0ac835f 100644 --- a/image/OrientedImage.cpp +++ b/image/OrientedImage.cpp @@ -70,7 +70,7 @@ OrientedImage::GetIntrinsicRatio(nsSize* aRatio) return rv; } -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) OrientedImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { diff --git a/image/OrientedImage.h b/image/OrientedImage.h index ac739884d3..c6c19eea8b 100644 --- a/image/OrientedImage.h +++ b/image/OrientedImage.h @@ -32,7 +32,7 @@ public: NS_IMETHOD GetHeight(int32_t* aHeight) override; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override; NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override; - NS_IMETHOD_(TemporaryRef) + NS_IMETHOD_(already_AddRefed) GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override; NS_IMETHOD GetImageContainer(layers::LayerManager* aManager, layers::ImageContainer** _retval) override; diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 26efbd1f66..111209bfe9 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -668,7 +668,7 @@ RasterImage::GetFirstFrameDelay() return mAnim->GetTimeoutForFrame(0); } -TemporaryRef +already_AddRefed RasterImage::CopyFrame(uint32_t aWhichFrame, uint32_t aFlags) { if (aWhichFrame > FRAME_MAX_VALUE) @@ -737,14 +737,14 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, uint32_t aFlags) //****************************************************************************** /* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame, * in uint32_t aFlags); */ -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) RasterImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { return GetFrameInternal(aWhichFrame, aFlags); } -TemporaryRef +already_AddRefed RasterImage::GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags) { MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE); diff --git a/image/RasterImage.h b/image/RasterImage.h index 3ed760d174..7d2bdc10f1 100644 --- a/image/RasterImage.h +++ b/image/RasterImage.h @@ -296,9 +296,9 @@ private: GraphicsFilter aFilter, uint32_t aFlags); - TemporaryRef CopyFrame(uint32_t aWhichFrame, + already_AddRefed CopyFrame(uint32_t aWhichFrame, uint32_t aFlags); - TemporaryRef GetFrameInternal(uint32_t aWhichFrame, + already_AddRefed GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags); DrawableFrameRef LookupFrameInternal(uint32_t aFrameNum, diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index 19a4a63385..8e9bdf9f8d 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -649,7 +649,7 @@ VectorImage::IsOpaque() //****************************************************************************** /* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame, * in uint32_t aFlags; */ -NS_IMETHODIMP_(TemporaryRef) +NS_IMETHODIMP_(already_AddRefed) VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { diff --git a/image/imgFrame.cpp b/image/imgFrame.cpp index 84e7d6abd2..1175f9977c 100644 --- a/image/imgFrame.cpp +++ b/image/imgFrame.cpp @@ -48,7 +48,7 @@ VolatileSurfaceStride(const IntSize& size, SurfaceFormat format) return (size.width * BytesPerPixel(format) + 0x3) & ~0x3; } -static TemporaryRef +static already_AddRefed CreateLockedSurface(VolatileBuffer *vbuf, const IntSize& size, SurfaceFormat format) @@ -69,7 +69,7 @@ CreateLockedSurface(VolatileBuffer *vbuf, return surf.forget(); } -static TemporaryRef +static already_AddRefed AllocateBufferForImage(const IntSize& size, SurfaceFormat format) { int32_t stride = VolatileSurfaceStride(size, format); @@ -1007,14 +1007,14 @@ imgFrame::IsSinglePixel() const return mSinglePixel; } -TemporaryRef +already_AddRefed imgFrame::GetSurface() { MonitorAutoLock lock(mMonitor); return GetSurfaceInternal(); } -TemporaryRef +already_AddRefed imgFrame::GetSurfaceInternal() { mMonitor.AssertCurrentThreadOwns(); @@ -1043,7 +1043,7 @@ imgFrame::GetSurfaceInternal() return CreateLockedSurface(mVBuf, mSize, mFormat); } -TemporaryRef +already_AddRefed imgFrame::GetDrawTarget() { MonitorAutoLock lock(mMonitor); diff --git a/image/imgFrame.h b/image/imgFrame.h index bb9f2d0f16..d5c87d1b70 100644 --- a/image/imgFrame.h +++ b/image/imgFrame.h @@ -275,8 +275,8 @@ public: Color SinglePixelColor() const; bool IsSinglePixel() const; - TemporaryRef GetSurface(); - TemporaryRef GetDrawTarget(); + already_AddRefed GetSurface(); + already_AddRefed GetDrawTarget(); size_t SizeOfExcludingThis(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const; @@ -298,7 +298,7 @@ private: // methods uint32_t GetImageBytesPerRow() const; uint32_t GetImageDataLength() const; int32_t GetStride() const; - TemporaryRef GetSurfaceInternal(); + already_AddRefed GetSurfaceInternal(); uint32_t PaletteDataLength() const { diff --git a/image/imgIContainer.idl b/image/imgIContainer.idl index 538f5f8cd0..84c579d8cd 100644 --- a/image/imgIContainer.idl +++ b/image/imgIContainer.idl @@ -104,7 +104,7 @@ native nsSize(nsSize); native Orientation(mozilla::image::Orientation); [ref] native TimeStamp(mozilla::TimeStamp); [ref] native MaybeSVGImageContext(mozilla::Maybe); -native TempRefSourceSurface(mozilla::TemporaryRef); +native TempRefSourceSurface(already_AddRefed); native TempRefImgIContainer(already_AddRefed); native nsIntSizeByVal(nsIntSize); diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index c29f9b76e1..e7d16d9bb8 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -9,6 +9,7 @@ #include "FileDescriptorSetChild.h" #include "mozilla/Assertions.h" #include "mozilla/dom/PBlobChild.h" +#include "mozilla/dom/cache/ActorUtils.h" #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/ipc/PBackgroundTestChild.h" @@ -46,6 +47,10 @@ public: namespace mozilla { namespace ipc { +using mozilla::dom::cache::PCacheChild; +using mozilla::dom::cache::PCacheStorageChild; +using mozilla::dom::cache::PCacheStreamControlChild; + // ----------------------------------------------------------------------------- // BackgroundChildImpl::ThreadLocal // ----------------------------------------------------------------------------- @@ -232,6 +237,51 @@ BackgroundChildImpl::DeallocPBroadcastChannelChild( return true; } +// ----------------------------------------------------------------------------- +// Cache API +// ----------------------------------------------------------------------------- + +PCacheStorageChild* +BackgroundChildImpl::AllocPCacheStorageChild(const Namespace& aNamespace, + const PrincipalInfo& aPrincipalInfo) +{ + MOZ_CRASH("CacheStorageChild actor must be provided to PBackground manager"); + return nullptr; +} + +bool +BackgroundChildImpl::DeallocPCacheStorageChild(PCacheStorageChild* aActor) +{ + dom::cache::DeallocPCacheStorageChild(aActor); + return true; +} + +PCacheChild* +BackgroundChildImpl::AllocPCacheChild() +{ + return dom::cache::AllocPCacheChild(); +} + +bool +BackgroundChildImpl::DeallocPCacheChild(PCacheChild* aActor) +{ + dom::cache::DeallocPCacheChild(aActor); + return true; +} + +PCacheStreamControlChild* +BackgroundChildImpl::AllocPCacheStreamControlChild() +{ + return dom::cache::AllocPCacheStreamControlChild(); +} + +bool +BackgroundChildImpl::DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor) +{ + dom::cache::DeallocPCacheStreamControlChild(aActor); + return true; +} + } // namespace ipc } // namespace mozilla diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index 9a22673132..bf7d4ee00c 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -85,6 +85,24 @@ protected: virtual bool DeallocPBroadcastChannelChild(PBroadcastChannelChild* aActor) MOZ_OVERRIDE; + + virtual dom::cache::PCacheStorageChild* + AllocPCacheStorageChild(const dom::cache::Namespace& aNamespace, + const PrincipalInfo& aPrincipalInfo) MOZ_OVERRIDE; + + virtual bool + DeallocPCacheStorageChild(dom::cache::PCacheStorageChild* aActor) MOZ_OVERRIDE; + + virtual dom::cache::PCacheChild* AllocPCacheChild() MOZ_OVERRIDE; + + virtual bool + DeallocPCacheChild(dom::cache::PCacheChild* aActor) MOZ_OVERRIDE; + + virtual dom::cache::PCacheStreamControlChild* + AllocPCacheStreamControlChild() MOZ_OVERRIDE; + + virtual bool + DeallocPCacheStreamControlChild(dom::cache::PCacheStreamControlChild* aActor) MOZ_OVERRIDE; }; class BackgroundChildImpl::ThreadLocal final diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index e37e2f14d4..ffdaf9eb15 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/PBlobParent.h" #include "mozilla/dom/ServiceWorkerRegistrar.h" +#include "mozilla/dom/cache/ActorUtils.h" #include "mozilla/dom/indexedDB/ActorsParent.h" #include "mozilla/dom/ipc/BlobParent.h" #include "mozilla/ipc/BackgroundParent.h" @@ -31,6 +32,9 @@ #endif using mozilla::ipc::AssertIsOnBackgroundThread; +using mozilla::dom::cache::PCacheParent; +using mozilla::dom::cache::PCacheStorageParent; +using mozilla::dom::cache::PCacheStreamControlParent; namespace { @@ -549,6 +553,48 @@ BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar() return true; } +PCacheStorageParent* +BackgroundParentImpl::AllocPCacheStorageParent(const Namespace& aNamespace, + const PrincipalInfo& aPrincipalInfo) +{ + return dom::cache::AllocPCacheStorageParent(this, aNamespace, aPrincipalInfo); +} + +bool +BackgroundParentImpl::DeallocPCacheStorageParent(PCacheStorageParent* aActor) +{ + dom::cache::DeallocPCacheStorageParent(aActor); + return true; +} + +PCacheParent* +BackgroundParentImpl::AllocPCacheParent() +{ + MOZ_CRASH("CacheParent actor must be provided to PBackground manager"); + return nullptr; +} + +bool +BackgroundParentImpl::DeallocPCacheParent(PCacheParent* aActor) +{ + dom::cache::DeallocPCacheParent(aActor); + return true; +} + +PCacheStreamControlParent* +BackgroundParentImpl::AllocPCacheStreamControlParent() +{ + MOZ_CRASH("CacheStreamControlParent actor must be provided to PBackground manager"); + return nullptr; +} + +bool +BackgroundParentImpl::DeallocPCacheStreamControlParent(PCacheStreamControlParent* aActor) +{ + dom::cache::DeallocPCacheStreamControlParent(aActor); + return true; +} + } // namespace ipc } // namespace mozilla diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index 6215328e6a..5f96c18ba7 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -96,6 +96,24 @@ protected: virtual bool RecvShutdownServiceWorkerRegistrar() MOZ_OVERRIDE; + + virtual dom::cache::PCacheStorageParent* + AllocPCacheStorageParent(const dom::cache::Namespace& aNamespace, + const PrincipalInfo& aPrincipalInfo) MOZ_OVERRIDE; + + virtual bool + DeallocPCacheStorageParent(dom::cache::PCacheStorageParent* aActor) MOZ_OVERRIDE; + + virtual dom::cache::PCacheParent* AllocPCacheParent() MOZ_OVERRIDE; + + virtual bool + DeallocPCacheParent(dom::cache::PCacheParent* aActor) MOZ_OVERRIDE; + + virtual dom::cache::PCacheStreamControlParent* + AllocPCacheStreamControlParent() MOZ_OVERRIDE; + + virtual bool + DeallocPCacheStreamControlParent(dom::cache::PCacheStreamControlParent* aActor) MOZ_OVERRIDE; }; } // namespace ipc diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 6533290e3c..eacd454e42 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -6,6 +6,9 @@ include protocol PBackgroundIDBFactory; include protocol PBackgroundTest; include protocol PBlob; include protocol PBroadcastChannel; +include protocol PCache; +include protocol PCacheStorage; +include protocol PCacheStreamControl; include protocol PFileDescriptorSet; include protocol PVsync; @@ -14,6 +17,9 @@ include PBackgroundSharedTypes; include PBackgroundIDBSharedTypes; include ServiceWorkerRegistrarTypes; +using mozilla::dom::cache::Namespace from "mozilla/dom/cache/Types.h"; +include "mozilla/dom/cache/IPCUtils.h"; + namespace mozilla { namespace ipc { @@ -23,6 +29,9 @@ sync protocol PBackground manages PBackgroundTest; manages PBlob; manages PBroadcastChannel; + manages PCache; + manages PCacheStorage; + manages PCacheStreamControl; manages PFileDescriptorSet; manages PVsync; @@ -42,6 +51,12 @@ parent: nsString scope); ShutdownServiceWorkerRegistrar(); + PCacheStorage(Namespace aNamespace, PrincipalInfo aPrincipalInfo); + +child: + PCache(); + PCacheStreamControl(); + both: PBlob(BlobConstructorParams params); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 516b32dda0..09237e701a 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -453,7 +453,9 @@ inline bool IsInternalFunctionObject(JSObject* funobj) { JSFunction* fun = &funobj->as(); - return fun->isLambda() && !funobj->getParent(); + MOZ_ASSERT_IF(fun->isLambda(), + fun->isInterpreted() || fun->isAsmJSNative()); + return fun->isLambda() && fun->isInterpreted() && !fun->environment(); } class AutoPropDescVector : public AutoVectorRooter diff --git a/layout/base/DisplayItemClip.cpp b/layout/base/DisplayItemClip.cpp index a43228b8b3..be390bcd82 100644 --- a/layout/base/DisplayItemClip.cpp +++ b/layout/base/DisplayItemClip.cpp @@ -152,7 +152,7 @@ DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext, } } -TemporaryRef +already_AddRefed DisplayItemClip::MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, const RoundedRect &aRoundRect) const diff --git a/layout/base/DisplayItemClip.h b/layout/base/DisplayItemClip.h index de6fa97f80..b08016f28f 100644 --- a/layout/base/DisplayItemClip.h +++ b/layout/base/DisplayItemClip.h @@ -92,7 +92,7 @@ public: uint32_t aBegin, uint32_t aEnd) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext - mozilla::TemporaryRef MakeRoundedRectPath(DrawTarget& aDrawTarget, + already_AddRefed MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, const RoundedRect &aRoundRect) const; diff --git a/layout/base/nsCSSRenderingBorders.cpp b/layout/base/nsCSSRenderingBorders.cpp index b8c692a950..e511cefce0 100644 --- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -443,7 +443,7 @@ MaybeMoveToMidPoint(Point& aP0, Point& aP1, const Point& aMidPoint) } } -TemporaryRef +already_AddRefed nsCSSBorderRenderer::GetSideClipSubPath(mozilla::css::Side aSide) { // the clip proceeds clockwise from the top left corner; @@ -1032,7 +1032,7 @@ bool IsVisible(int aStyle) return false; } -TemporaryRef +already_AddRefed nsCSSBorderRenderer::CreateCornerGradient(mozilla::css::Corner aCorner, nscolor aFirstColor, nscolor aSecondColor, diff --git a/layout/base/nsCSSRenderingBorders.h b/layout/base/nsCSSRenderingBorders.h index 67efbb55e6..cbe2d06bd8 100644 --- a/layout/base/nsCSSRenderingBorders.h +++ b/layout/base/nsCSSRenderingBorders.h @@ -165,7 +165,7 @@ private: // This code needs to make sure that the individual pieces // don't ever (mathematically) overlap; the pixel overlap // is taken care of by the ADD compositing. - mozilla::TemporaryRef GetSideClipSubPath(mozilla::css::Side aSide); + already_AddRefed GetSideClipSubPath(mozilla::css::Side aSide); // Given a set of sides to fill and a color, do so in the fastest way. // @@ -212,7 +212,7 @@ private: bool AllBordersSolid(bool *aHasCompositeColors); // Azure variant of CreateCornerGradient. - mozilla::TemporaryRef + already_AddRefed CreateCornerGradient(mozilla::css::Corner aCorner, nscolor aFirstColor, nscolor aSecondColor, mozilla::gfx::DrawTarget *aDT, mozilla::gfx::Point &aPoint1, mozilla::gfx::Point &aPoint2); diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index a852c70155..75a3365405 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -590,7 +590,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mAncestorHasApzAwareEventHandler(false), mHaveScrollableDisplayPort(false), mWindowDraggingAllowed(false), - mIsBuildingForPopup(nsLayoutUtils::IsPopup(aReferenceFrame)) + mIsBuildingForPopup(nsLayoutUtils::IsPopup(aReferenceFrame)), + mForceLayerForScrollParent(false) { MOZ_COUNT_CTOR(nsDisplayListBuilder); PL_InitArenaPool(&mPool, "displayListArena", 4096, diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index e5ac8ea3a2..de55a5febf 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -253,6 +253,13 @@ public: * Get the ViewID of the nearest scrolling ancestor frame. */ ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; } + /** + * Get and set the flag that indicates if scroll parents should have layers + * forcibly created. This flag is set when a deeply nested scrollframe has + * a displayport, and for scroll handoff to work properly the ancestor + * scrollframes should also get their own scrollable layers. + */ + void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; } /** * Get the ViewID and the scrollbar flags corresponding to the scrollbar for * which we are building display items at the moment. @@ -660,15 +667,41 @@ public: class AutoCurrentScrollParentIdSetter { public: AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId) - : mBuilder(aBuilder), mOldValue(aBuilder->mCurrentScrollParentId) { + : mBuilder(aBuilder) + , mOldValue(aBuilder->mCurrentScrollParentId) + , mOldForceLayer(aBuilder->mForceLayerForScrollParent) { + // If this AutoCurrentScrollParentIdSetter has the same scrollId as the + // previous one on the stack, then that means the scrollframe that + // created this isn't actually scrollable and cannot participate in + // scroll handoff. We set mCanBeScrollParent to false to indicate this. + mCanBeScrollParent = (mOldValue != aScrollId); aBuilder->mCurrentScrollParentId = aScrollId; + aBuilder->mForceLayerForScrollParent = false; } + bool ShouldForceLayerForScrollParent() const { + // Only scrollframes participating in scroll handoff can be forced to + // layerize + return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent; + }; ~AutoCurrentScrollParentIdSetter() { mBuilder->mCurrentScrollParentId = mOldValue; + if (mCanBeScrollParent) { + // If this flag is set, caller code is responsible for having dealt + // with the current value of mBuilder->mForceLayerForScrollParent, so + // we can just restore the old value. + mBuilder->mForceLayerForScrollParent = mOldForceLayer; + } else { + // Otherwise we need to keep propagating the force-layerization flag + // upwards to the next ancestor scrollframe that does participate in + // scroll handoff. + mBuilder->mForceLayerForScrollParent |= mOldForceLayer; + } } private: nsDisplayListBuilder* mBuilder; ViewID mOldValue; + bool mOldForceLayer; + bool mCanBeScrollParent; }; /** @@ -919,6 +952,7 @@ private: bool mHaveScrollableDisplayPort; bool mWindowDraggingAllowed; bool mIsBuildingForPopup; + bool mForceLayerForScrollParent; }; class nsDisplayItem; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index aca4e6f938..183a6e2702 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1111,7 +1111,7 @@ public: * edge of the presshell area. The aPoint, aScreenRect and aSurface * arguments function in a similar manner as RenderSelection. */ - virtual mozilla::TemporaryRef + virtual already_AddRefed RenderNode(nsIDOMNode* aNode, nsIntRegion* aRegion, nsIntPoint& aPoint, @@ -1132,7 +1132,7 @@ public: * the original. When scaling does not occur, the mouse point isn't used * as the position can be determined from the displayed frames. */ - virtual mozilla::TemporaryRef + virtual already_AddRefed RenderSelection(nsISelection* aSelection, nsIntPoint& aPoint, nsIntRect* aScreenRect) = 0; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 14c007cbb7..cf76f9a68d 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -2401,7 +2401,8 @@ PresShell::ScrollPage(bool aForward) nsIScrollableFrame::PAGES, nsIScrollableFrame::SMOOTH, nullptr, nullptr, - nsIScrollableFrame::NOT_MOMENTUM); + nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ENABLE_SNAP); } return NS_OK; } @@ -2418,7 +2419,8 @@ PresShell::ScrollLine(bool aForward) nsIScrollableFrame::LINES, nsIScrollableFrame::SMOOTH, nullptr, nullptr, - nsIScrollableFrame::NOT_MOMENTUM); + nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ENABLE_SNAP); } return NS_OK; } @@ -2435,7 +2437,8 @@ PresShell::ScrollCharacter(bool aRight) nsIScrollableFrame::LINES, nsIScrollableFrame::SMOOTH, nullptr, nullptr, - nsIScrollableFrame::NOT_MOMENTUM); + nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ENABLE_SNAP); } return NS_OK; } @@ -2450,7 +2453,8 @@ PresShell::CompleteScroll(bool aForward) nsIScrollableFrame::WHOLE, nsIScrollableFrame::SMOOTH, nullptr, nullptr, - nsIScrollableFrame::NOT_MOMENTUM); + nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ENABLE_SNAP); } return NS_OK; } @@ -5199,7 +5203,7 @@ PresShell::CreateRangePaintInfo(nsIDOMRange* aRange, return info; } -TemporaryRef +already_AddRefed PresShell::PaintRangePaintInfo(nsTArray >* aItems, nsISelection* aSelection, nsIntRegion* aRegion, @@ -5324,7 +5328,7 @@ PresShell::PaintRangePaintInfo(nsTArray >* aItems, return dt->Snapshot(); } -TemporaryRef +already_AddRefed PresShell::RenderNode(nsIDOMNode* aNode, nsIntRegion* aRegion, nsIntPoint& aPoint, @@ -5370,7 +5374,7 @@ PresShell::RenderNode(nsIDOMNode* aNode, aScreenRect); } -TemporaryRef +already_AddRefed PresShell::RenderSelection(nsISelection* aSelection, nsIntPoint& aPoint, nsIntRect* aScreenRect) diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index cd8184439e..bf4fb67455 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -180,13 +180,13 @@ public: nscolor aBackgroundColor, gfxContext* aThebesContext) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed RenderNode(nsIDOMNode* aNode, nsIntRegion* aRegion, nsIntPoint& aPoint, nsIntRect* aScreenRect) override; - virtual mozilla::TemporaryRef + virtual already_AddRefed RenderSelection(nsISelection* aSelection, nsIntPoint& aPoint, nsIntRect* aScreenRect) override; @@ -545,7 +545,7 @@ protected: * aScreenRect - [out] set to the area of the screen the painted area should * be displayed at */ - mozilla::TemporaryRef + already_AddRefed PaintRangePaintInfo(nsTArray >* aItems, nsISelection* aSelection, nsIntRegion* aRegion, diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini index 06563356a5..c3bb88ed49 100644 --- a/layout/base/tests/mochitest.ini +++ b/layout/base/tests/mochitest.ini @@ -176,6 +176,8 @@ support-files = bug921928_event_target_iframe_apps_oop.html [test_mozPaintCount.html] skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(depends on plugins support) b2g-debug(depends on plugins support) b2g-desktop(depends on plugins support) [test_scroll_event_ordering.html] +[test_scroll_snapping.html] +skip-if = buildapp == 'android' # bug 1041833 [test_bug583889.html] support-files = bug583889_inner1.html bug583889_inner2.html [test_bug582771.html] diff --git a/layout/base/tests/test_scroll_snapping.html b/layout/base/tests/test_scroll_snapping.html new file mode 100644 index 0000000000..c17b5eeb7e --- /dev/null +++ b/layout/base/tests/test_scroll_snapping.html @@ -0,0 +1,785 @@ + + + + Test for scroll snapping + + + + + + +

+
+
+
+ +
+
+
+ + + diff --git a/layout/generic/TextOverflow.cpp b/layout/generic/TextOverflow.cpp index 910d48f6e0..a71719c7db 100644 --- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -322,6 +322,11 @@ TextOverflow::WillProcessLines(nsDisplayListBuilder* aBuilder, if (!CanHaveTextOverflow(aBuilder, aBlockFrame)) { return nullptr; } + nsIScrollableFrame* scrollableFrame = nsLayoutUtils::GetScrollableFrameFor(aBlockFrame); + if (scrollableFrame && scrollableFrame->IsTransformingByAPZ()) { + // If the APZ is actively scrolling this, don't bother with markers. + return nullptr; + } return new TextOverflow(aBuilder, aBlockFrame); } @@ -699,15 +704,21 @@ TextOverflow::PruneDisplayListContents(nsDisplayList* aList, aList->AppendToTop(&saved); } +/* static */ bool +TextOverflow::HasClippedOverflow(nsIFrame* aBlockFrame) +{ + const nsStyleTextReset* style = aBlockFrame->StyleTextReset(); + return style->mTextOverflow.mLeft.mType == NS_STYLE_TEXT_OVERFLOW_CLIP && + style->mTextOverflow.mRight.mType == NS_STYLE_TEXT_OVERFLOW_CLIP; +} + /* static */ bool TextOverflow::CanHaveTextOverflow(nsDisplayListBuilder* aBuilder, nsIFrame* aBlockFrame) { - const nsStyleTextReset* style = aBlockFrame->StyleTextReset(); // Nothing to do for text-overflow:clip or if 'overflow-x/y:visible' or if // we're just building items for event processing or image visibility. - if ((style->mTextOverflow.mLeft.mType == NS_STYLE_TEXT_OVERFLOW_CLIP && - style->mTextOverflow.mRight.mType == NS_STYLE_TEXT_OVERFLOW_CLIP) || + if (HasClippedOverflow(aBlockFrame) || IsInlineAxisOverflowVisible(aBlockFrame) || aBuilder->IsForEventDelivery() || aBuilder->IsForImageVisibility()) { return false; diff --git a/layout/generic/TextOverflow.h b/layout/generic/TextOverflow.h index b3b6076665..b8d5056744 100644 --- a/layout/generic/TextOverflow.h +++ b/layout/generic/TextOverflow.h @@ -48,6 +48,10 @@ class TextOverflow { */ nsDisplayList& GetMarkers() { return mMarkerList; } + /** + * @return true if aBlockFrmae has text-overflow:clip on both sides. + */ + static bool HasClippedOverflow(nsIFrame* aBlockFrame); /** * @return true if aBlockFrame needs analysis for text overflow. */ diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 4f05b6c703..b6dc52ebea 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -3401,6 +3401,15 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext, if (frameSelection) { frameSelection->SetDragState(false); frameSelection->StopAutoScrollTimer(); + nsIScrollableFrame* scrollFrame = + nsLayoutUtils::GetNearestScrollableFrame(this, + nsLayoutUtils::SCROLLABLE_SAME_DOC | + nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN); + if (scrollFrame) { + // Perform any additional scrolling needed to maintain CSS snap point + // requirements when autoscrolling is over. + scrollFrame->ScrollSnap(); + } } // Do not call any methods of the current object after this point!!! diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 254c6ae1f4..c544fd62d1 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -80,6 +80,21 @@ BuildScrollContainerLayers() return !sContainerlessScrollingEnabled; } +static uint32_t +GetOverflowChange(const nsRect& aCurScrolledRect, const nsRect& aPrevScrolledRect) +{ + uint32_t result = 0; + if (aPrevScrolledRect.x != aCurScrolledRect.x || + aPrevScrolledRect.width != aCurScrolledRect.width) { + result |= nsIScrollableFrame::HORIZONTAL; + } + if (aPrevScrolledRect.y != aCurScrolledRect.y || + aPrevScrolledRect.height != aCurScrolledRect.height) { + result |= nsIScrollableFrame::VERTICAL; + } + return result; +} + //---------------------------------------------------------------------- //----------nsHTMLScrollFrame------------------------------------------- @@ -914,6 +929,8 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, mHelper.PostScrolledAreaEvent(); } + mHelper.UpdatePrevScrolledRect(); + aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); mHelper.PostOverflowEvent(); @@ -1913,6 +1930,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, , mIgnoreMomentumScroll(false) , mScaleToResolution(false) , mTransformingByAPZ(false) + , mVelocityQueue(aOuter->PresContext()) { if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter)); @@ -2083,8 +2101,16 @@ void ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode, nsIAtom *aOrigin, - const nsRect* aRange) + const nsRect* aRange, + nsIScrollableFrame::ScrollSnapMode aSnap) { + + if (aSnap == nsIScrollableFrame::ENABLE_SNAP) { + GetSnapPointForDestination(nsIScrollableFrame::DEVICE_PIXELS, + mDestination, + aScrollPosition); + } + nsRect scrollRange = GetScrollRangeForClamping(); mDestination = scrollRange.ClampPoint(aScrollPosition); @@ -2108,6 +2134,9 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition, if (aMode == nsIScrollableFrame::SMOOTH_MSD) { mIgnoreMomentumScroll = true; if (!mAsyncSmoothMSDScroll) { + nsPoint sv = mVelocityQueue.GetVelocity(); + currentVelocity.width = sv.x; + currentVelocity.height = sv.y; if (mAsyncScroll) { if (mAsyncScroll->mIsSmoothScroll) { currentVelocity = mAsyncScroll->VelocityAt(now); @@ -3079,6 +3108,22 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, } mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent); + + if (idSetter.ShouldForceLayerForScrollParent() && + !gfxPrefs::LayoutUseContainersForRootFrames()) + { + // Note that forcing layerization of scroll parents follows the scroll + // handoff chain which is subject to the out-of-flow-frames caveat noted + // above (where the idSetter variable is created). + // + // This is not compatible when using containes for root scrollframes. + MOZ_ASSERT(shouldBuildLayer && mScrolledFrame->GetContent()); + mShouldBuildScrollableLayer = true; + } + } + + if (mShouldBuildScrollableLayer && !gfxPrefs::LayoutUseContainersForRootFrames()) { + aBuilder->ForceLayerForScrollParent(); } if (MOZ_UNLIKELY(mOuter->StyleDisplay()->mOverflowClipBox == @@ -3359,7 +3404,8 @@ ScrollFrameHelper::ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom *aOrigin, - nsIScrollableFrame::ScrollMomentum aMomentum) + nsIScrollableFrame::ScrollMomentum aMomentum, + nsIScrollableFrame::ScrollSnapMode aSnap) { // When a smooth scroll is being processed on a frame, mouse wheel and trackpad // momentum scroll event updates must notcancel the SMOOTH or SMOOTH_MSD @@ -3422,6 +3468,9 @@ ScrollFrameHelper::ScrollBy(nsIntPoint aDelta, nsPoint pos = GetScrollPosition(); AdjustForWholeDelta(aDelta.x, &pos.x); AdjustForWholeDelta(aDelta.y, &pos.y); + if (aSnap == nsIScrollableFrame::ENABLE_SNAP) { + GetSnapPointForDestination(aUnit, mDestination, pos); + } ScrollTo(pos, aMode); // 'this' might be destroyed here if (aOverflow) { @@ -3434,8 +3483,27 @@ ScrollFrameHelper::ScrollBy(nsIntPoint aDelta, return; } - nsPoint newPos = mDestination + - nsPoint(aDelta.x*deltaMultiplier.width, aDelta.y*deltaMultiplier.height); + nsPoint newPos = mDestination + nsPoint(aDelta.x*deltaMultiplier.width, aDelta.y*deltaMultiplier.height); + + if (aSnap == nsIScrollableFrame::ENABLE_SNAP) { + ScrollbarStyles styles = GetScrollbarStylesFromFrame(); + if (styles.mScrollSnapTypeY != NS_STYLE_SCROLL_SNAP_TYPE_NONE || + styles.mScrollSnapTypeX != NS_STYLE_SCROLL_SNAP_TYPE_NONE) { + nscoord appUnitsPerDevPixel = mOuter->PresContext()->AppUnitsPerDevPixel(); + deltaMultiplier = nsSize(appUnitsPerDevPixel, appUnitsPerDevPixel); + negativeTolerance = 0.1f; + positiveTolerance = 0; + nsIScrollableFrame::ScrollUnit snapUnit = aUnit; + if (aOrigin == nsGkAtoms::mouseWheel) { + // When using a clicky scroll wheel, snap point selection works the same + // as keyboard up/down/left/right navigation, but with varying amounts + // of scroll delta. + snapUnit = nsIScrollableFrame::LINES; + } + GetSnapPointForDestination(snapUnit, mDestination, newPos); + } + } + // Calculate desired range values. nscoord rangeLowerX, rangeUpperX, rangeLowerY, rangeUpperY; CalcRangeForScrollBy(aDelta.x, newPos.x, negativeTolerance, positiveTolerance, @@ -3459,6 +3527,49 @@ ScrollFrameHelper::ScrollBy(nsIntPoint aDelta, NSAppUnitsToIntPixels(clampAmount.x, appUnitsPerDevPixel), NSAppUnitsToIntPixels(clampAmount.y, appUnitsPerDevPixel)); } + + if (aUnit == nsIScrollableFrame::DEVICE_PIXELS && + !gfxPrefs::AsyncPanZoomEnabled()) { + // When APZ is disabled, we must track the velocity + // on the main thread; otherwise, the APZC will manage this. + mVelocityQueue.Sample(GetScrollPosition()); + } +} + +void +ScrollFrameHelper::ScrollSnap() +{ + float flingSensitivity = gfxPrefs::ScrollSnapPredictionSensitivity(); + int maxVelocity = gfxPrefs::ScrollSnapPredictionMaxVelocity(); + maxVelocity = nsPresContext::CSSPixelsToAppUnits(maxVelocity); + int maxOffset = maxVelocity * flingSensitivity; + nsPoint velocity = mVelocityQueue.GetVelocity(); + // Multiply each component individually to avoid integer multiply + nsPoint predictedOffset = nsPoint(velocity.x * flingSensitivity, + velocity.y * flingSensitivity); + predictedOffset.Clamp(maxOffset); + nsPoint pos = GetScrollPosition(); + nsPoint destinationPos = pos + predictedOffset; + ScrollSnap(destinationPos); +} + +void +ScrollFrameHelper::FlingSnap(const mozilla::CSSPoint& aDestination) +{ + ScrollSnap(CSSPoint::ToAppUnits(aDestination)); +} + +void +ScrollFrameHelper::ScrollSnap(const nsPoint &aDestination) +{ + nsRect scrollRange = GetScrollRangeForClamping(); + nsPoint pos = GetScrollPosition(); + nsPoint snapDestination = scrollRange.ClampPoint(aDestination); + if (GetSnapPointForDestination(nsIScrollableFrame::DEVICE_PIXELS, + pos, + snapDestination)) { + ScrollTo(snapDestination, nsIScrollableFrame::SMOOTH_MSD); + } } nsSize @@ -4531,6 +4642,8 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState) f->SetRect(clippedRect); } + mHelper.UpdatePrevScrolledRect(); + mHelper.PostOverflowEvent(); return NS_OK; } @@ -4682,9 +4795,27 @@ ScrollFrameHelper::UpdateOverflow() nsIScrollableFrame* sf = do_QueryFrame(mOuter); ScrollbarStyles ss = sf->GetScrollbarStyles(); - if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || - ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN || - GetScrollPosition() != nsPoint()) { + // Reflow when the change in overflow leads to one of our scrollbars + // changing or might require repositioning the scrolled content due to + // reduced extents. + nsRect scrolledRect = GetScrolledRect(); + uint32_t overflowChange = GetOverflowChange(scrolledRect, mPrevScrolledRect); + mPrevScrolledRect = scrolledRect; + + bool needReflow = false; + nsPoint scrollPosition = GetScrollPosition(); + if (overflowChange & nsIScrollableFrame::HORIZONTAL) { + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN || scrollPosition.x) { + needReflow = true; + } + } + if (overflowChange & nsIScrollableFrame::VERTICAL) { + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || scrollPosition.y) { + needReflow = true; + } + } + + if (needReflow) { // If there are scrollbars, or we're not at the beginning of the pane, // the scroll position may change. In this case, mark the frame as // needing reflow. Don't use NS_FRAME_IS_DIRTY as dirty as that means @@ -4713,6 +4844,12 @@ ScrollFrameHelper::UpdateSticky() } } +void +ScrollFrameHelper::UpdatePrevScrolledRect() +{ + mPrevScrolledRect = GetScrolledRect(); +} + void ScrollFrameHelper::AdjustScrollbarRectForResizer( nsIFrame* aFrame, nsPresContext* aPresContext, @@ -5210,3 +5347,343 @@ nsIScrollableFrame::GetPerceivedScrollingDirections() const } return directions; } + +/** + * Stores candidate snapping edges. + */ +class SnappingEdgeCallback { +public: + virtual void AddHorizontalEdge(nscoord aEdge) = 0; + virtual void AddVerticalEdge(nscoord aEdge) = 0; + virtual void AddHorizontalEdgeInterval(const nsRect &aScrollRange, + nscoord aInterval, + nscoord aOffset) = 0; + virtual void AddVerticalEdgeInterval(const nsRect &aScrollRange, + nscoord aInterval, + nscoord aOffset) = 0; +}; + +/** + * Keeps track of the current best edge to snap to. The criteria for + * adding an edge depends on the scrolling unit. + */ +class CalcSnapPoints : public SnappingEdgeCallback { +public: + CalcSnapPoints(nsIScrollableFrame::ScrollUnit aUnit, + const nsPoint& aDestination, + const nsPoint& aStartPos); + virtual void AddHorizontalEdge(nscoord aEdge) MOZ_OVERRIDE; + virtual void AddVerticalEdge(nscoord aEdge) MOZ_OVERRIDE; + virtual void AddHorizontalEdgeInterval(const nsRect &aScrollRange, + nscoord aInterval, nscoord aOffset) + MOZ_OVERRIDE; + virtual void AddVerticalEdgeInterval(const nsRect &aScrollRange, + nscoord aInterval, nscoord aOffset) + MOZ_OVERRIDE; + void AddEdge(nscoord aEdge, + nscoord aDestination, + nscoord aStartPos, + nscoord aScrollingDirection, + nscoord* aBestEdge, + bool* aEdgeFound); + void AddEdgeInterval(nscoord aInterval, + nscoord aMinPos, + nscoord aMaxPos, + nscoord aOffset, + nscoord aDestination, + nscoord aStartPos, + nscoord aScrollingDirection, + nscoord* aBestEdge, + bool* aEdgeFound); + nsPoint GetBestEdge() const; +protected: + nsIScrollableFrame::ScrollUnit mUnit; + nsPoint mDestination; // gives the position after scrolling but before snapping + nsPoint mStartPos; // gives the position before scrolling + nsIntPoint mScrollingDirection; // always -1, 0, or 1 + nsPoint mBestEdge; // keeps track of the position of the current best edge + bool mHorizontalEdgeFound; // true if mBestEdge.x is storing a valid horizontal edge + bool mVerticalEdgeFound; // true if mBestEdge.y is storing a valid vertical edge +}; + +CalcSnapPoints::CalcSnapPoints(nsIScrollableFrame::ScrollUnit aUnit, + const nsPoint& aDestination, + const nsPoint& aStartPos) +{ + mUnit = aUnit; + mDestination = aDestination; + mStartPos = aStartPos; + + nsPoint direction = aDestination - aStartPos; + mScrollingDirection = nsIntPoint(0,0); + if (direction.x < 0) { + mScrollingDirection.x = -1; + } + if (direction.x > 0) { + mScrollingDirection.x = 1; + } + if (direction.y < 0) { + mScrollingDirection.y = -1; + } + if (direction.y > 0) { + mScrollingDirection.y = 1; + } + mBestEdge = aDestination; + mHorizontalEdgeFound = false; + mVerticalEdgeFound = false; +} + +nsPoint +CalcSnapPoints::GetBestEdge() const +{ + return nsPoint(mVerticalEdgeFound ? mBestEdge.x : mStartPos.x, + mHorizontalEdgeFound ? mBestEdge.y : mStartPos.y); +} + +void +CalcSnapPoints::AddHorizontalEdge(nscoord aEdge) +{ + AddEdge(aEdge, mDestination.y, mStartPos.y, mScrollingDirection.y, &mBestEdge.y, + &mHorizontalEdgeFound); +} + +void +CalcSnapPoints::AddVerticalEdge(nscoord aEdge) +{ + AddEdge(aEdge, mDestination.x, mStartPos.x, mScrollingDirection.x, &mBestEdge.x, + &mVerticalEdgeFound); +} + +void +CalcSnapPoints::AddHorizontalEdgeInterval(const nsRect &aScrollRange, + nscoord aInterval, nscoord aOffset) +{ + AddEdgeInterval(aInterval, aScrollRange.y, aScrollRange.YMost(), aOffset, + mDestination.y, mStartPos.y, mScrollingDirection.y, + &mBestEdge.y, &mHorizontalEdgeFound); +} + +void +CalcSnapPoints::AddVerticalEdgeInterval(const nsRect &aScrollRange, + nscoord aInterval, nscoord aOffset) +{ + AddEdgeInterval(aInterval, aScrollRange.x, aScrollRange.XMost(), aOffset, + mDestination.x, mStartPos.x, mScrollingDirection.x, + &mBestEdge.x, &mVerticalEdgeFound); +} + +void +CalcSnapPoints::AddEdge(nscoord aEdge, nscoord aDestination, nscoord aStartPos, + nscoord aScrollingDirection, nscoord* aBestEdge, + bool *aEdgeFound) +{ + // nsIScrollableFrame::DEVICE_PIXELS indicates that we are releasing a drag + // gesture or any other user input event that sets an absolute scroll + // position. In this case, scroll snapping is expected to travel in any + // direction. Otherwise, we will restrict the direction of the scroll + // snapping movement based on aScrollingDirection. + if (mUnit != nsIScrollableFrame::DEVICE_PIXELS) { + // Unless DEVICE_PIXELS, we only want to snap to points ahead of the + // direction we are scrolling + if (aScrollingDirection == 0) { + // The scroll direction is neutral - will not hit a snap point. + return; + } + // nsIScrollableFrame::WHOLE indicates that we are navigating to "home" or + // "end". In this case, we will always select the first or last snap point + // regardless of the direction of the scroll. Otherwise, we will select + // scroll snapping points only in the direction specified by + // aScrollingDirection. + if (mUnit != nsIScrollableFrame::WHOLE) { + // Direction of the edge from the current position (before scrolling) in + // the direction of scrolling + nscoord direction = (aEdge - aStartPos) * aScrollingDirection; + if (direction <= 0) { + // The edge is not in the direction we are scrolling, skip it. + return; + } + } + } + if (!*aEdgeFound) { + *aBestEdge = aEdge; + *aEdgeFound = true; + return; + } + if (mUnit == nsIScrollableFrame::DEVICE_PIXELS || + mUnit == nsIScrollableFrame::LINES) { + if (std::abs(aEdge - aDestination) < std::abs(*aBestEdge - aDestination)) { + *aBestEdge = aEdge; + } + } else if (mUnit == nsIScrollableFrame::PAGES) { + // distance to the edge from the scrolling destination in the direction of scrolling + nscoord overshoot = (aEdge - aDestination) * aScrollingDirection; + // distance to the current best edge from the scrolling destination in the direction of scrolling + nscoord curOvershoot = (*aBestEdge - aDestination) * aScrollingDirection; + + // edges between the current position and the scrolling destination are favoured + // to preserve context + if (overshoot < 0 && (overshoot > curOvershoot || curOvershoot >= 0)) { + *aBestEdge = aEdge; + } + // if there are no edges between the current position and the scrolling destination + // the closest edge beyond the destination is used + if (overshoot > 0 && overshoot < curOvershoot) { + *aBestEdge = aEdge; + } + } else if (mUnit == nsIScrollableFrame::WHOLE) { + // the edge closest to the top/bottom/left/right is used, depending on scrolling direction + if (aScrollingDirection > 0 && aEdge > *aBestEdge) { + *aBestEdge = aEdge; + } else if (aScrollingDirection < 0 && aEdge < *aBestEdge) { + *aBestEdge = aEdge; + } + } else { + NS_ERROR("Invalid scroll mode"); + return; + } +} + +void +CalcSnapPoints::AddEdgeInterval(nscoord aInterval, nscoord aMinPos, + nscoord aMaxPos, nscoord aOffset, + nscoord aDestination, nscoord aStartPos, + nscoord aScrollingDirection, + nscoord* aBestEdge, bool *aEdgeFound) +{ + if (aInterval == 0) { + // When interval is 0, there are no scroll snap points. + // Avoid division by zero and bail. + return; + } + + // The only possible candidate interval snap points are the edges immediately + // surrounding aDestination. + + // aDestination must be clamped to the scroll + // range in order to handle cases where the best matching snap point would + // result in scrolling out of bounds. This clamping must be prior to + // selecting the two interval edges. + nscoord clamped = std::max(std::min(aDestination, aMaxPos), aMinPos); + + // Add each edge in the interval immediately before aTarget and after aTarget + // Do not add edges that are out of range. + nscoord r = (clamped + aOffset) % aInterval; + if (r < aMinPos) { + r += aInterval; + } + nscoord edge = clamped - r; + if (edge >= aMinPos && edge <= aMaxPos) { + AddEdge(edge, aDestination, aStartPos, aScrollingDirection, aBestEdge, + aEdgeFound); + } + edge += aInterval; + if (edge >= aMinPos && edge <= aMaxPos) { + AddEdge(edge, aDestination, aStartPos, aScrollingDirection, aBestEdge, + aEdgeFound); + } +} + +static void +ScrollSnapHelper(SnappingEdgeCallback& aCallback, nsIFrame* aFrame, + nsIFrame* aScrolledFrame, + const nsPoint &aScrollSnapDestination) { + nsIFrame::ChildListIterator childLists(aFrame); + for (; !childLists.IsDone(); childLists.Next()) { + nsFrameList::Enumerator childFrames(childLists.CurrentList()); + for (; !childFrames.AtEnd(); childFrames.Next()) { + nsIFrame* f = childFrames.get(); + + const nsStyleDisplay* styleDisplay = f->StyleDisplay(); + size_t coordCount = styleDisplay->mScrollSnapCoordinate.Length(); + + if (coordCount) { + nsRect frameRect = f->GetRect(); + nsPoint offset = f->GetOffsetTo(aScrolledFrame); + nsRect edgesRect = nsRect(offset, frameRect.Size()); + for (size_t coordNum = 0; coordNum < coordCount; coordNum++) { + const nsStyleBackground::Position &coordPosition = + f->StyleDisplay()->mScrollSnapCoordinate[coordNum]; + nsPoint coordPoint = edgesRect.TopLeft() - aScrollSnapDestination; + coordPoint += nsPoint(coordPosition.mXPosition.mLength, + coordPosition.mYPosition.mLength); + if (coordPosition.mXPosition.mHasPercent) { + coordPoint.x += NSToCoordRound(coordPosition.mXPosition.mPercent * + frameRect.width); + } + if (coordPosition.mYPosition.mHasPercent) { + coordPoint.y += NSToCoordRound(coordPosition.mYPosition.mPercent * + frameRect.height); + } + + aCallback.AddVerticalEdge(coordPoint.x); + aCallback.AddHorizontalEdge(coordPoint.y); + } + } + + ScrollSnapHelper(aCallback, f, aScrolledFrame, aScrollSnapDestination); + } + } +} + +bool +ScrollFrameHelper::GetSnapPointForDestination(nsIScrollableFrame::ScrollUnit aUnit, + nsPoint aStartPos, + nsPoint &aDestination) +{ + ScrollbarStyles styles = GetScrollbarStylesFromFrame(); + if (styles.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_NONE && + styles.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_NONE) { + return false; + } + + nsSize scrollPortSize = mScrollPort.Size(); + nsRect scrollRange = GetScrollRangeForClamping(); + + nsPoint destPos = nsPoint(styles.mScrollSnapDestinationX.mLength, + styles.mScrollSnapDestinationY.mLength); + if (styles.mScrollSnapDestinationX.mHasPercent) { + destPos.x += NSToCoordFloorClamped(styles.mScrollSnapDestinationX.mPercent + * scrollPortSize.width); + } + + if (styles.mScrollSnapDestinationY.mHasPercent) { + destPos.y += NSToCoordFloorClamped(styles.mScrollSnapDestinationY.mPercent + * scrollPortSize.height); + } + + CalcSnapPoints calcSnapPoints(aUnit, aDestination, aStartPos); + + if (styles.mScrollSnapPointsX.GetUnit() != eStyleUnit_None) { + nscoord interval = nsRuleNode::ComputeCoordPercentCalc(styles.mScrollSnapPointsX, + scrollPortSize.width); + calcSnapPoints.AddVerticalEdgeInterval(scrollRange, interval, destPos.x); + } + if (styles.mScrollSnapPointsY.GetUnit() != eStyleUnit_None) { + nscoord interval = nsRuleNode::ComputeCoordPercentCalc(styles.mScrollSnapPointsY, + scrollPortSize.width); + calcSnapPoints.AddHorizontalEdgeInterval(scrollRange, interval, destPos.y); + } + + ScrollSnapHelper(calcSnapPoints, mScrolledFrame, mScrolledFrame, destPos); + bool snapped = false; + nsPoint finalPos = calcSnapPoints.GetBestEdge(); + nscoord proximityThreshold = + Preferences::GetInt("layout.css.scroll-snap.proximity-threshold", 0); + proximityThreshold = nsPresContext::CSSPixelsToAppUnits(proximityThreshold); + if (styles.mScrollSnapTypeY == NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY && + std::abs(aDestination.y - finalPos.y) > proximityThreshold) { + finalPos.y = aDestination.y; + } else { + snapped = true; + } + if (styles.mScrollSnapTypeX == NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY && + std::abs(aDestination.x - finalPos.x) > proximityThreshold) { + finalPos.x = aDestination.x; + } else { + snapped = true; + } + if (snapped) { + aDestination = finalPos; + } + return snapped; +} diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 11777fb7cf..dfd53ec275 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -20,6 +20,8 @@ #include "nsBoxLayoutState.h" #include "nsQueryFrame.h" #include "nsExpirationTracker.h" +#include "TextOverflow.h" +#include "ScrollVelocityQueue.h" class nsPresContext; class nsIPresShell; @@ -178,6 +180,9 @@ public: gfxSize GetResolution() const; void SetResolution(const gfxSize& aResolution); void SetResolutionAndScaleTo(const gfxSize& aResolution); + void FlingSnap(const mozilla::CSSPoint& aDestination); + void ScrollSnap(); + void ScrollSnap(const nsPoint &aDestination); protected: nsRect GetScrollRangeForClamping() const; @@ -194,8 +199,10 @@ public: * This is a closed-ended range --- aRange.XMost()/aRange.YMost() are allowed. */ void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode, - const nsRect* aRange = nullptr) { - ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other, aRange); + const nsRect* aRange = nullptr, + nsIScrollableFrame::ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP) { + ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other, aRange, + aSnap); } /** * @note This method might destroy the frame, pres shell and other objects. @@ -221,11 +228,23 @@ public: void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit, nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom* aOrigin = nullptr, - nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM); + nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP); /** * @note This method might destroy the frame, pres shell and other objects. */ void ScrollToRestoredPosition(); + /** + * GetSnapPointForDestination determines which point to snap to after + * scrolling. aStartPos gives the position before scrolling and aDestination + * gives the position after scrolling, with no snapping. Behaviour is + * dependent on the value of aUnit. + * Returns true if a suitable snap point could be found and aDestination has + * been updated to a valid snapping position. + */ + bool GetSnapPointForDestination(nsIScrollableFrame::ScrollUnit aUnit, + nsPoint aStartPos, + nsPoint &aDestination); nsSize GetLineScrollAmount() const; nsSize GetPageScrollAmount() const; @@ -300,6 +319,8 @@ public: void UpdateSticky(); + void UpdatePrevScrolledRect(); + bool IsRectNearlyVisible(const nsRect& aRect) const; nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const; @@ -327,6 +348,11 @@ public: void SetTransformingByAPZ(bool aTransforming) { mTransformingByAPZ = aTransforming; + if (!mozilla::css::TextOverflow::HasClippedOverflow(mOuter)) { + // If the block has some text-overflow stuff we should kick off a paint + // because we have special behaviour for it when APZ scrolling is active. + mOuter->SchedulePaint(); + } } bool IsTransformingByAPZ() const { return mTransformingByAPZ; @@ -417,6 +443,8 @@ public: // The scroll position where we last updated image visibility. nsPoint mLastUpdateImagesPos; + nsRect mPrevScrolledRect; + FrameMetrics::ViewID mScrollParentID; bool mNeverHasVerticalScrollbar:1; @@ -482,6 +510,8 @@ public: // (as best as we can tell on the main thread, anyway). bool mTransformingByAPZ:1; + mozilla::layout::ScrollVelocityQueue mVelocityQueue; + protected: /** * @note This method might destroy the frame, pres shell and other objects. @@ -489,7 +519,8 @@ protected: void ScrollToWithOrigin(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode, nsIAtom *aOrigin, // nullptr indicates "other" origin - const nsRect* aRange); + const nsRect* aRange, + nsIScrollableFrame::ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP); void CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin = nullptr); @@ -529,7 +560,7 @@ public: NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS - virtual mozilla::WritingMode GetWritingMode() const override + virtual mozilla::WritingMode GetWritingMode() const MOZ_OVERRIDE { if (mHelper.mScrolledFrame) { return mHelper.mScrolledFrame->GetWritingMode(); @@ -560,7 +591,7 @@ public: nscoord GetIntrinsicVScrollbarWidth(nsRenderingContext *aRenderingContext); virtual bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea, - Sides aSkipSides, nscoord aRadii[8]) const override { + Sides aSkipSides, nscoord aRadii[8]) const MOZ_OVERRIDE { return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii); } @@ -601,7 +632,7 @@ public: } virtual bool DoesClipChildren() override { return true; } - virtual nsSplittableType GetSplittableType() const override; + virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE; virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) override { nsPoint pt = aChild->GetPosition(); @@ -615,16 +646,16 @@ public: uint32_t aFilter) override; // nsIScrollableFrame - virtual nsIFrame* GetScrolledFrame() const override { + virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE { return mHelper.GetScrolledFrame(); } - virtual mozilla::ScrollbarStyles GetScrollbarStyles() const override { + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE { return mHelper.GetScrollbarStylesFromFrame(); } - virtual uint32_t GetScrollbarVisibility() const override { + virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE { return mHelper.GetScrollbarVisibility(); } - virtual nsMargin GetActualScrollbarSizes() const override { + virtual nsMargin GetActualScrollbarSizes() const MOZ_OVERRIDE { return mHelper.GetActualScrollbarSizes(); } virtual nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) override { @@ -640,25 +671,25 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return mHelper.GetNondisappearingScrollbarWidth(&bls); } - virtual nsRect GetScrolledRect() const override { + virtual nsRect GetScrolledRect() const MOZ_OVERRIDE { return mHelper.GetScrolledRect(); } - virtual nsRect GetScrollPortRect() const override { + virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mHelper.GetScrollPortRect(); } - virtual nsPoint GetScrollPosition() const override { + virtual nsPoint GetScrollPosition() const MOZ_OVERRIDE { return mHelper.GetScrollPosition(); } - virtual nsPoint GetLogicalScrollPosition() const override { + virtual nsPoint GetLogicalScrollPosition() const MOZ_OVERRIDE { return mHelper.GetLogicalScrollPosition(); } - virtual nsRect GetScrollRange() const override { + virtual nsRect GetScrollRange() const MOZ_OVERRIDE { return mHelper.GetScrollRange(); } - virtual nsSize GetScrollPositionClampingScrollPortSize() const override { + virtual nsSize GetScrollPositionClampingScrollPortSize() const MOZ_OVERRIDE { return mHelper.GetScrollPositionClampingScrollPortSize(); } - virtual gfxSize GetResolution() const override { + virtual gfxSize GetResolution() const MOZ_OVERRIDE { return mHelper.GetResolution(); } virtual void SetResolution(const gfxSize& aResolution) override { @@ -667,18 +698,20 @@ public: virtual void SetResolutionAndScaleTo(const gfxSize& aResolution) override { return mHelper.SetResolutionAndScaleTo(aResolution); } - virtual nsSize GetLineScrollAmount() const override { + virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE { return mHelper.GetLineScrollAmount(); } - virtual nsSize GetPageScrollAmount() const override { + virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE { return mHelper.GetPageScrollAmount(); } /** * @note This method might destroy the frame, pres shell and other objects. */ virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode, - const nsRect* aRange = nullptr) override { - mHelper.ScrollTo(aScrollPosition, aMode, aRange); + const nsRect* aRange = nullptr, + nsIScrollableFrame::ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP) + MOZ_OVERRIDE { + mHelper.ScrollTo(aScrollPosition, aMode, aRange, aSnap); } /** * @note This method might destroy the frame, pres shell and other objects. @@ -703,9 +736,16 @@ public: */ virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom* aOrigin = nullptr, - nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM) + nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP) MOZ_OVERRIDE { - mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin, aMomentum); + mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin, aMomentum, aSnap); + } + virtual void FlingSnap(const mozilla::CSSPoint& aDestination) MOZ_OVERRIDE { + mHelper.FlingSnap(aDestination); + } + virtual void ScrollSnap() MOZ_OVERRIDE { + mHelper.ScrollSnap(); } /** * @note This method might destroy the frame, pres shell and other objects. @@ -738,10 +778,10 @@ public: virtual void ResetScrollPositionForLayerPixelAlignment() override { mHelper.ResetScrollPositionForLayerPixelAlignment(); } - virtual bool IsResolutionSet() const override { + virtual bool IsResolutionSet() const MOZ_OVERRIDE { return mHelper.mIsResolutionSet; } - virtual bool DidHistoryRestore() const override { + virtual bool DidHistoryRestore() const MOZ_OVERRIDE { return mHelper.mDidHistoryRestore; } virtual void ClearDidHistoryRestore() override { @@ -750,7 +790,7 @@ public: virtual bool IsRectNearlyVisible(const nsRect& aRect) override { return mHelper.IsRectNearlyVisible(aRect); } - virtual nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const override { + virtual nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const MOZ_OVERRIDE { return mHelper.ExpandRectToNearlyVisible(aRect); } virtual nsIAtom* LastScrollOrigin() override { @@ -768,20 +808,20 @@ public: virtual void ResetScrollInfoIfGeneration(uint32_t aGeneration) override { mHelper.ResetScrollInfoIfGeneration(aGeneration); } - virtual bool WantAsyncScroll() const override { + virtual bool WantAsyncScroll() const MOZ_OVERRIDE { return mHelper.WantAsyncScroll(); } virtual void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, nsRect* aClipRect, - nsTArray* aOutput) const override { + nsTArray* aOutput) const MOZ_OVERRIDE { mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters, aClipRect, aOutput); } - virtual bool IsIgnoringViewportClipping() const override { + virtual bool IsIgnoringViewportClipping() const MOZ_OVERRIDE { return mHelper.IsIgnoringViewportClipping(); } - virtual void MarkScrollbarsDirtyForReflow() const override { + virtual void MarkScrollbarsDirtyForReflow() const MOZ_OVERRIDE { mHelper.MarkScrollbarsDirtyForReflow(); } @@ -802,7 +842,7 @@ public: * * @see nsGkAtoms::scrollFrame */ - virtual nsIAtom* GetType() const override; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; // nsIScrollbarMediator virtual void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection) override { @@ -826,8 +866,8 @@ public: virtual nsIFrame* GetScrollbarBox(bool aVertical) override { return mHelper.GetScrollbarBox(aVertical); } - virtual void ScrollbarActivityStarted() const override; - virtual void ScrollbarActivityStopped() const override; + virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE; + virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE; virtual void SetTransformingByAPZ(bool aTransforming) MOZ_OVERRIDE { mHelper.SetTransformingByAPZ(aTransforming); @@ -837,7 +877,7 @@ public: } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const override; + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif #ifdef ACCESSIBILITY @@ -936,7 +976,7 @@ public: } virtual bool DoesClipChildren() override { return true; } - virtual nsSplittableType GetSplittableType() const override; + virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE; virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) override { nsPoint pt = aChild->GetPosition(); @@ -959,7 +999,7 @@ public: virtual nsresult GetPadding(nsMargin& aPadding) override; virtual bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea, - Sides aSkipSides, nscoord aRadii[8]) const override { + Sides aSkipSides, nscoord aRadii[8]) const MOZ_OVERRIDE { return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii); } @@ -987,16 +1027,16 @@ public: static void AdjustReflowStateBack(nsBoxLayoutState& aState, bool aSetBack); // nsIScrollableFrame - virtual nsIFrame* GetScrolledFrame() const override { + virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE { return mHelper.GetScrolledFrame(); } - virtual mozilla::ScrollbarStyles GetScrollbarStyles() const override { + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE { return mHelper.GetScrollbarStylesFromFrame(); } - virtual uint32_t GetScrollbarVisibility() const override { + virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE { return mHelper.GetScrollbarVisibility(); } - virtual nsMargin GetActualScrollbarSizes() const override { + virtual nsMargin GetActualScrollbarSizes() const MOZ_OVERRIDE { return mHelper.GetActualScrollbarSizes(); } virtual nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) override { @@ -1012,25 +1052,25 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return mHelper.GetNondisappearingScrollbarWidth(&bls); } - virtual nsRect GetScrolledRect() const override { + virtual nsRect GetScrolledRect() const MOZ_OVERRIDE { return mHelper.GetScrolledRect(); } - virtual nsRect GetScrollPortRect() const override { + virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mHelper.GetScrollPortRect(); } - virtual nsPoint GetScrollPosition() const override { + virtual nsPoint GetScrollPosition() const MOZ_OVERRIDE { return mHelper.GetScrollPosition(); } - virtual nsPoint GetLogicalScrollPosition() const override { + virtual nsPoint GetLogicalScrollPosition() const MOZ_OVERRIDE { return mHelper.GetLogicalScrollPosition(); } - virtual nsRect GetScrollRange() const override { + virtual nsRect GetScrollRange() const MOZ_OVERRIDE { return mHelper.GetScrollRange(); } - virtual nsSize GetScrollPositionClampingScrollPortSize() const override { + virtual nsSize GetScrollPositionClampingScrollPortSize() const MOZ_OVERRIDE { return mHelper.GetScrollPositionClampingScrollPortSize(); } - virtual gfxSize GetResolution() const override { + virtual gfxSize GetResolution() const MOZ_OVERRIDE { return mHelper.GetResolution(); } virtual void SetResolution(const gfxSize& aResolution) override { @@ -1039,18 +1079,19 @@ public: virtual void SetResolutionAndScaleTo(const gfxSize& aResolution) override { return mHelper.SetResolutionAndScaleTo(aResolution); } - virtual nsSize GetLineScrollAmount() const override { + virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE { return mHelper.GetLineScrollAmount(); } - virtual nsSize GetPageScrollAmount() const override { + virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE { return mHelper.GetPageScrollAmount(); } /** * @note This method might destroy the frame, pres shell and other objects. */ virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode, - const nsRect* aRange = nullptr) override { - mHelper.ScrollTo(aScrollPosition, aMode, aRange); + const nsRect* aRange = nullptr, + ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP) MOZ_OVERRIDE { + mHelper.ScrollTo(aScrollPosition, aMode, aRange, aSnap); } /** * @note This method might destroy the frame, pres shell and other objects. @@ -1072,9 +1113,16 @@ public: */ virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom* aOrigin = nullptr, - nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM) + nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM, + nsIScrollableFrame::ScrollSnapMode aSnap = nsIScrollableFrame::DISABLE_SNAP) MOZ_OVERRIDE { - mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin, aMomentum); + mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin, aMomentum, aSnap); + } + virtual void FlingSnap(const mozilla::CSSPoint& aDestination) MOZ_OVERRIDE { + mHelper.FlingSnap(aDestination); + } + virtual void ScrollSnap() MOZ_OVERRIDE { + mHelper.ScrollSnap(); } /** * @note This method might destroy the frame, pres shell and other objects. @@ -1107,10 +1155,10 @@ public: virtual void ResetScrollPositionForLayerPixelAlignment() override { mHelper.ResetScrollPositionForLayerPixelAlignment(); } - virtual bool IsResolutionSet() const override { + virtual bool IsResolutionSet() const MOZ_OVERRIDE { return mHelper.mIsResolutionSet; } - virtual bool DidHistoryRestore() const override { + virtual bool DidHistoryRestore() const MOZ_OVERRIDE { return mHelper.mDidHistoryRestore; } virtual void ClearDidHistoryRestore() override { @@ -1119,7 +1167,7 @@ public: virtual bool IsRectNearlyVisible(const nsRect& aRect) override { return mHelper.IsRectNearlyVisible(aRect); } - virtual nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const override { + virtual nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const MOZ_OVERRIDE { return mHelper.ExpandRectToNearlyVisible(aRect); } virtual nsIAtom* LastScrollOrigin() override { @@ -1137,20 +1185,20 @@ public: virtual void ResetScrollInfoIfGeneration(uint32_t aGeneration) override { mHelper.ResetScrollInfoIfGeneration(aGeneration); } - virtual bool WantAsyncScroll() const override { + virtual bool WantAsyncScroll() const MOZ_OVERRIDE { return mHelper.WantAsyncScroll(); } virtual void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, nsRect* aClipRect, - nsTArray* aOutput) const override { + nsTArray* aOutput) const MOZ_OVERRIDE { mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters, aClipRect, aOutput); } - virtual bool IsIgnoringViewportClipping() const override { + virtual bool IsIgnoringViewportClipping() const MOZ_OVERRIDE { return mHelper.IsIgnoringViewportClipping(); } - virtual void MarkScrollbarsDirtyForReflow() const override { + virtual void MarkScrollbarsDirtyForReflow() const MOZ_OVERRIDE { mHelper.MarkScrollbarsDirtyForReflow(); } @@ -1171,9 +1219,9 @@ public: * * @see nsGkAtoms::scrollFrame */ - virtual nsIAtom* GetType() const override; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const override + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { // Override bogus IsFrameOfType in nsBoxFrame. if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced)) @@ -1203,8 +1251,8 @@ public: return mHelper.GetScrollbarBox(aVertical); } - virtual void ScrollbarActivityStarted() const override; - virtual void ScrollbarActivityStopped() const override; + virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE; + virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE; virtual void SetTransformingByAPZ(bool aTransforming) MOZ_OVERRIDE { mHelper.SetTransformingByAPZ(aTransforming); @@ -1214,7 +1262,7 @@ public: } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const override; + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif protected: diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 8525c5b6eb..20ae8638bf 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -207,6 +207,13 @@ public: * been started since the last actual user input. */ enum ScrollMomentum { NOT_MOMENTUM, SYNTHESIZED_MOMENTUM_EVENT }; + /** + * When set to ENABLE_SNAP, additional scrolling will be performed after the + * scroll operation to maintain the constraints set by CSS Scroll snapping. + * The additional scrolling may include asynchronous smooth scrolls that + * continue to animate after the initial scroll position has been set. + */ + enum ScrollSnapMode { DISABLE_SNAP, ENABLE_SNAP }; /** * @note This method might destroy the frame, pres shell and other objects. * Clamps aScrollPosition to GetScrollRange and sets the scroll position @@ -217,7 +224,8 @@ public: * The choosen point will be as close as possible to aScrollPosition. */ virtual void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode, - const nsRect* aRange = nullptr) = 0; + const nsRect* aRange = nullptr, + ScrollSnapMode aSnap = DISABLE_SNAP) = 0; /** * @note This method might destroy the frame, pres shell and other objects. * Scrolls to a particular position in integer CSS pixels. @@ -271,7 +279,27 @@ public: virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, nsIntPoint* aOverflow = nullptr, nsIAtom* aOrigin = nullptr, - ScrollMomentum aMomentum = NOT_MOMENTUM) = 0; + ScrollMomentum aMomentum = NOT_MOMENTUM, + ScrollSnapMode aSnap = DISABLE_SNAP) = 0; + + /** + * Perform scroll snapping, possibly resulting in a smooth scroll to + * maintain the scroll snap position constraints. A predicted landing + * position determined by the APZC is used to select the best matching + * snap point, allowing touchscreen fling gestures to navigate between + * snap points. + * @param aDestination The desired landing position of the fling, which + * is used to select the best matching snap point. + */ + virtual void FlingSnap(const mozilla::CSSPoint& aDestination) = 0; + /** + * Perform scroll snapping, possibly resulting in a smooth scroll to + * maintain the scroll snap position constraints. Velocity sampled from + * main thread scrolling is used to determine best matching snap point + * when called after a fling gesture on a trackpad or mouse wheel. + */ + virtual void ScrollSnap() = 0; + /** * @note This method might destroy the frame, pres shell and other objects. * This tells the scroll frame to try scrolling to the scroll diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index e0c09675e9..361dbe7ccb 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -100,6 +100,24 @@ public: } } + virtual void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) MOZ_OVERRIDE + { + if (MessageLoop::current() != mUILoop) { + // We have to send this message from the "UI thread" (main + // thread). + mUILoop->PostTask( + FROM_HERE, + NewRunnableMethod(this, &RemoteContentController::RequestFlingSnap, + aScrollId, aDestination)); + return; + } + if (mRenderFrame) { + TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager()); + browser->RequestFlingSnap(aScrollId, aDestination); + } + } + virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, const uint32_t& aScrollGeneration) override { diff --git a/layout/reftests/scrolling/move-item-ref.html b/layout/reftests/scrolling/move-item-ref.html new file mode 100644 index 0000000000..613fd5c243 --- /dev/null +++ b/layout/reftests/scrolling/move-item-ref.html @@ -0,0 +1,27 @@ + + + + + + + +
+
+
+ + + diff --git a/layout/reftests/scrolling/move-item.html b/layout/reftests/scrolling/move-item.html new file mode 100644 index 0000000000..774db68560 --- /dev/null +++ b/layout/reftests/scrolling/move-item.html @@ -0,0 +1,31 @@ + + + + + + + +
+
+
+ + + diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list index 0db7f1b65f..fe4a3d8d97 100644 --- a/layout/reftests/scrolling/reftest.list +++ b/layout/reftests/scrolling/reftest.list @@ -33,3 +33,4 @@ skip-if(B2G) == huge-vertical-overflow.html huge-vertical-overflow-ref.html skip-if(B2G&&browserIsRemote) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html == frame-scrolling-attr-1.html frame-scrolling-attr-ref.html == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html +== move-item.html move-item-ref.html # bug 1125750 diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 4e7b12a39c..bca9b69435 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -4855,7 +4855,7 @@ SVGTextFrame::GetTextPathPathElement(nsIFrame* aTextPathFrame) static_cast(element) : nullptr; } -TemporaryRef +already_AddRefed SVGTextFrame::GetTextPath(nsIFrame* aTextPathFrame) { SVGPathElement* element = GetTextPathPathElement(aTextPathFrame); diff --git a/layout/svg/SVGTextFrame.h b/layout/svg/SVGTextFrame.h index 6150e2374c..c35ea3e4f9 100644 --- a/layout/svg/SVGTextFrame.h +++ b/layout/svg/SVGTextFrame.h @@ -605,7 +605,7 @@ private: // Methods to get information for a frame. mozilla::dom::SVGPathElement* GetTextPathPathElement(nsIFrame* aTextPathFrame); - mozilla::TemporaryRef GetTextPath(nsIFrame* aTextPathFrame); + already_AddRefed GetTextPath(nsIFrame* aTextPathFrame); gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame); gfxFloat GetStartOffset(nsIFrame* aTextPathFrame); diff --git a/layout/svg/nsSVGMaskFrame.cpp b/layout/svg/nsSVGMaskFrame.cpp index bc49dc385e..e03de86d23 100644 --- a/layout/svg/nsSVGMaskFrame.cpp +++ b/layout/svg/nsSVGMaskFrame.cpp @@ -200,7 +200,7 @@ NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame) -TemporaryRef +already_AddRefed nsSVGMaskFrame::GetMaskForMaskedFrame(gfxContext* aContext, nsIFrame* aMaskedFrame, const gfxMatrix &aMatrix, diff --git a/layout/svg/nsSVGMaskFrame.h b/layout/svg/nsSVGMaskFrame.h index c94899f8c9..a93c96898d 100644 --- a/layout/svg/nsSVGMaskFrame.h +++ b/layout/svg/nsSVGMaskFrame.h @@ -53,7 +53,7 @@ public: NS_DECL_FRAMEARENA_HELPERS // nsSVGMaskFrame method: - mozilla::TemporaryRef + already_AddRefed GetMaskForMaskedFrame(gfxContext* aContext, nsIFrame* aMaskedFrame, const gfxMatrix &aMatrix, diff --git a/layout/svg/nsSVGPatternFrame.cpp b/layout/svg/nsSVGPatternFrame.cpp index ca9a27fac9..4a18fb1a3b 100644 --- a/layout/svg/nsSVGPatternFrame.cpp +++ b/layout/svg/nsSVGPatternFrame.cpp @@ -229,7 +229,7 @@ GetTargetGeometry(gfxRect *aBBox, return NS_OK; } -TemporaryRef +already_AddRefed nsSVGPatternFrame::PaintPattern(const DrawTarget* aDrawTarget, Matrix* patternMatrix, const Matrix &aContextMatrix, diff --git a/layout/svg/nsSVGPatternFrame.h b/layout/svg/nsSVGPatternFrame.h index 7d9f8f2132..c7cbcbdf0a 100644 --- a/layout/svg/nsSVGPatternFrame.h +++ b/layout/svg/nsSVGPatternFrame.h @@ -112,7 +112,7 @@ protected: return GetLengthValue(aIndex, mContent); } - mozilla::TemporaryRef + already_AddRefed PaintPattern(const DrawTarget* aDrawTarget, Matrix *patternMatrix, const Matrix &aContextMatrix, diff --git a/media/mtransport/dtlsidentity.cpp b/media/mtransport/dtlsidentity.cpp index 7e17c98e72..b0a0b21907 100644 --- a/media/mtransport/dtlsidentity.cpp +++ b/media/mtransport/dtlsidentity.cpp @@ -26,7 +26,7 @@ DtlsIdentity::~DtlsIdentity() { const std::string DtlsIdentity::DEFAULT_HASH_ALGORITHM = "sha-256"; -TemporaryRef DtlsIdentity::Generate() { +already_AddRefed DtlsIdentity::Generate() { ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot) { diff --git a/media/mtransport/dtlsidentity.h b/media/mtransport/dtlsidentity.h index f511e37a3f..ab2c160302 100644 --- a/media/mtransport/dtlsidentity.h +++ b/media/mtransport/dtlsidentity.h @@ -24,7 +24,7 @@ class DtlsIdentity { public: // Generate an identity with a random name. - static TemporaryRef Generate(); + static already_AddRefed Generate(); // Note: the following two functions just provide access. They // do not transfer ownership. If you want a pointer that lasts diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index c74e2dac5e..840bc3db3e 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -1202,7 +1202,7 @@ RefPtr SourceStreamInfo::GetPipelineByTrackId_m( return nullptr; } -TemporaryRef +already_AddRefed LocalSourceStreamInfo::ForgetPipelineByTrackId_m(const std::string& trackId) { ASSERT_ON_THREAD(mParent->GetMainThread()); diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 5d4c269b38..dac13def9e 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -138,7 +138,7 @@ public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LocalSourceStreamInfo) private: - TemporaryRef ForgetPipelineByTrackId_m( + already_AddRefed ForgetPipelineByTrackId_m( const std::string& trackId); }; diff --git a/mfbt/RefPtr.h b/mfbt/RefPtr.h index bc26c9f1db..9fad346cdd 100644 --- a/mfbt/RefPtr.h +++ b/mfbt/RefPtr.h @@ -28,7 +28,6 @@ namespace mozilla { -template class TemporaryRef; template class OutParamRef; template OutParamRef byRef(RefPtr&); @@ -48,7 +47,6 @@ template class RefPtr { // To allow them to use unref() - friend class TemporaryRef; friend class OutParamRef; struct DontRef {}; @@ -56,8 +54,8 @@ class RefPtr public: RefPtr() : mPtr(0) {} RefPtr(const RefPtr& aOther) : mPtr(ref(aOther.mPtr)) {} - MOZ_IMPLICIT RefPtr(const TemporaryRef& aOther) : mPtr(aOther.take()) {} MOZ_IMPLICIT RefPtr(already_AddRefed& aOther) : mPtr(aOther.take()) {} + MOZ_IMPLICIT RefPtr(already_AddRefed&& aOther) : mPtr(aOther.take()) {} MOZ_IMPLICIT RefPtr(T* aVal) : mPtr(ref(aVal)) {} template @@ -70,12 +68,12 @@ public: assign(ref(aOther.mPtr)); return *this; } - RefPtr& operator=(const TemporaryRef& aOther) + RefPtr& operator=(already_AddRefed& aOther) { assign(aOther.take()); return *this; } - RefPtr& operator=(already_AddRefed& aOther) + RefPtr& operator=(already_AddRefed&& aOther) { assign(aOther.take()); return *this; @@ -93,11 +91,11 @@ public: return *this; } - TemporaryRef forget() + already_AddRefed forget() { T* tmp = mPtr; mPtr = nullptr; - return TemporaryRef(tmp, DontRef()); + return already_AddRefed(tmp); } T* get() const { return mPtr; } @@ -130,49 +128,6 @@ private: } }; -/** - * TemporaryRef represents an object that holds a temporary - * reference to a T. TemporaryRef objects can't be manually ref'd or - * unref'd (being temporaries, not lvalues), so can only relinquish - * references to other objects, or unref on destruction. - */ -template -class TemporaryRef -{ - // To allow it to construct TemporaryRef from a bare T* - friend class RefPtr; - - typedef typename RefPtr::DontRef DontRef; - -public: - // Please see already_AddRefed for a description of what these constructors - // do. - TemporaryRef() : mPtr(nullptr) {} - typedef void (TemporaryRef::* MatchNullptr)(double, float); - MOZ_IMPLICIT TemporaryRef(MatchNullptr aRawPtr) : mPtr(nullptr) {} - explicit TemporaryRef(T* aVal) : mPtr(RefPtr::ref(aVal)) {} - TemporaryRef(const TemporaryRef& aOther) : mPtr(aOther.take()) {} - - template - TemporaryRef(const TemporaryRef& aOther) : mPtr(aOther.take()) {} - - ~TemporaryRef() { RefPtr::unref(mPtr); } - - MOZ_WARN_UNUSED_RESULT T* take() const - { - T* tmp = mPtr; - mPtr = nullptr; - return tmp; - } - -private: - TemporaryRef(T* aVal, const DontRef&) : mPtr(aVal) {} - - mutable T* MOZ_OWNING_REF mPtr; - - void operator=(const TemporaryRef&) = delete; -}; - /** * OutParamRef is a wrapper that tracks a refcounted pointer passed as * an outparam argument to a function. OutParamRef implements COM T** @@ -183,7 +138,7 @@ private: * returns the same T* passed to it through the T** outparam, as long * as the callee obeys the COM discipline. * - * Prefer returning TemporaryRef from functions over creating T** + * Prefer returning already_AddRefed from functions over creating T** * outparams and passing OutParamRef to T**. Prefer RefPtr* * outparams over T** outparams. */ @@ -224,19 +179,14 @@ byRef(RefPtr& aPtr) /** * Helper function to be able to conveniently write things like: * - * TemporaryRef + * already_AddRefed * f(...) * { * return MakeAndAddRef(...); * } - * - * since explicitly constructing TemporaryRef is unsightly. Having an - * explicit construction of TemporaryRef from T* also inhibits a future - * auto-conversion from TemporaryRef to already_AddRefed, since the semantics - * of TemporaryRef(T*) differ from already_AddRefed(T*). */ template -TemporaryRef +already_AddRefed MakeAndAddRef(Args&&... aArgs) { RefPtr p(new T(Forward(aArgs)...)); diff --git a/mfbt/tests/TestRefPtr.cpp b/mfbt/tests/TestRefPtr.cpp index 1b281fb4aa..a129d62330 100644 --- a/mfbt/tests/TestRefPtr.cpp +++ b/mfbt/tests/TestRefPtr.cpp @@ -9,7 +9,6 @@ using mozilla::RefCounted; using mozilla::RefPtr; -using mozilla::TemporaryRef; class Foo : public RefCounted { @@ -34,14 +33,14 @@ int Foo::sNumDestroyed; struct Bar : public Foo {}; -TemporaryRef +already_AddRefed NewFoo() { RefPtr f(new Foo()); return f.forget(); } -TemporaryRef +already_AddRefed NewBar() { RefPtr bar = new Bar(); @@ -63,7 +62,7 @@ GetNewFoo(RefPtr* aFoo) } -TemporaryRef +already_AddRefed GetNullFoo() { return 0; @@ -105,8 +104,10 @@ main() MOZ_RELEASE_ASSERT(5 == Foo::sNumDestroyed); { - RefPtr f = new Foo(); - f.forget(); + { + RefPtr f = new Foo(); + RefPtr g = f.forget(); + } MOZ_RELEASE_ASSERT(6 == Foo::sNumDestroyed); } diff --git a/mozglue/linker/BaseElf.cpp b/mozglue/linker/BaseElf.cpp index 2eadf12403..8a78285ef6 100644 --- a/mozglue/linker/BaseElf.cpp +++ b/mozglue/linker/BaseElf.cpp @@ -81,7 +81,7 @@ BaseElf::FindExidx(int *pcount) const } #endif -mozilla::TemporaryRef +already_AddRefed LoadedElf::Create(const char *path, void *base_addr) { DEBUG_LOG("LoadedElf::Create(\"%s\", %p) = ...", path, base_addr); diff --git a/mozglue/linker/BaseElf.h b/mozglue/linker/BaseElf.h index 5d3a8fd914..a7b708b50b 100644 --- a/mozglue/linker/BaseElf.h +++ b/mozglue/linker/BaseElf.h @@ -114,7 +114,7 @@ public: * Returns a LoadedElf corresponding to the already loaded ELF * at the given base address. */ - static mozilla::TemporaryRef Create(const char *path, + static already_AddRefed Create(const char *path, void *base_addr); private: diff --git a/mozglue/linker/CustomElf.cpp b/mozglue/linker/CustomElf.cpp index 1e23aed5ba..0abedffe66 100644 --- a/mozglue/linker/CustomElf.cpp +++ b/mozglue/linker/CustomElf.cpp @@ -101,7 +101,7 @@ private: }; -TemporaryRef +already_AddRefed CustomElf::Load(Mappable *mappable, const char *path, int flags) { DEBUG_LOG("CustomElf::Load(\"%s\", 0x%x) = ...", path, flags); diff --git a/mozglue/linker/CustomElf.h b/mozglue/linker/CustomElf.h index c7242fb465..430ce76659 100644 --- a/mozglue/linker/CustomElf.h +++ b/mozglue/linker/CustomElf.h @@ -28,7 +28,7 @@ public: * currently, none are supported and the behaviour is more or less that of * RTLD_GLOBAL | RTLD_BIND_NOW. */ - static mozilla::TemporaryRef Load(Mappable *mappable, + static already_AddRefed Load(Mappable *mappable, const char *path, int flags); /** diff --git a/mozglue/linker/ElfLoader.cpp b/mozglue/linker/ElfLoader.cpp index b8c2ae726d..e87678ef79 100644 --- a/mozglue/linker/ElfLoader.cpp +++ b/mozglue/linker/ElfLoader.cpp @@ -252,7 +252,7 @@ LibHandle::MappableMUnmap(void *addr, size_t length) const /** * SystemElf */ -TemporaryRef +already_AddRefed SystemElf::Load(const char *path, int flags) { /* The Android linker returns a handle when the file name matches an @@ -331,7 +331,7 @@ SystemElf::FindExidx(int *pcount) const /* Unique ElfLoader instance */ ElfLoader ElfLoader::Singleton; -TemporaryRef +already_AddRefed ElfLoader::Load(const char *path, int flags, LibHandle *parent) { /* Ensure logging is initialized or refresh if environment changed. */ @@ -406,7 +406,7 @@ ElfLoader::Load(const char *path, int flags, LibHandle *parent) return handle.forget(); } -mozilla::TemporaryRef +already_AddRefed ElfLoader::GetHandleByPtr(void *addr) { /* Scan the list of handles we already have for a match */ diff --git a/mozglue/linker/ElfLoader.h b/mozglue/linker/ElfLoader.h index 11f12d6819..a5bdaacb48 100644 --- a/mozglue/linker/ElfLoader.h +++ b/mozglue/linker/ElfLoader.h @@ -280,7 +280,7 @@ public: * Returns a new SystemElf for the given path. The given flags are passed * to dlopen(). */ - static mozilla::TemporaryRef Load(const char *path, int flags); + static already_AddRefed Load(const char *path, int flags); /** * Inherited from LibHandle @@ -413,7 +413,7 @@ public: * requesting the given library to be loaded. The loader may look in the * directory containing that parent library for the library to load. */ - mozilla::TemporaryRef Load(const char *path, int flags, + already_AddRefed Load(const char *path, int flags, LibHandle *parent = nullptr); /** @@ -422,7 +422,7 @@ public: * LibHandle::Contains returns true. Its purpose is to allow to * implement dladdr(). */ - mozilla::TemporaryRef GetHandleByPtr(void *addr); + already_AddRefed GetHandleByPtr(void *addr); /** * Returns a Mappable object for the path. Paths in the form diff --git a/mozglue/linker/Zip.cpp b/mozglue/linker/Zip.cpp index 80628e59b7..3344a9a349 100644 --- a/mozglue/linker/Zip.cpp +++ b/mozglue/linker/Zip.cpp @@ -12,7 +12,7 @@ #include "Logging.h" #include "Zip.h" -mozilla::TemporaryRef +already_AddRefed Zip::Create(const char *filename) { /* Open and map the file in memory */ @@ -41,7 +41,7 @@ Zip::Create(const char *filename) return Create(filename, mapped, size); } -mozilla::TemporaryRef +already_AddRefed Zip::Create(const char *filename, void *mapped, size_t size) { mozilla::RefPtr zip = new Zip(filename, mapped, size); @@ -181,7 +181,7 @@ Zip::GetFirstEntry() const ZipCollection ZipCollection::Singleton; -mozilla::TemporaryRef +already_AddRefed ZipCollection::GetZip(const char *path) { /* Search the list of Zips we already have for a match */ diff --git a/mozglue/linker/Zip.h b/mozglue/linker/Zip.h index 4fb63022e7..e45de11a3d 100644 --- a/mozglue/linker/Zip.h +++ b/mozglue/linker/Zip.h @@ -156,17 +156,17 @@ public: * Create a Zip instance for the given file name. Returns nullptr in case * of failure. */ - static mozilla::TemporaryRef Create(const char *filename); + static already_AddRefed Create(const char *filename); /** * Create a Zip instance using the given buffer. */ - static mozilla::TemporaryRef Create(void *buffer, size_t size) { + static already_AddRefed Create(void *buffer, size_t size) { return Create(nullptr, buffer, size); } private: - static mozilla::TemporaryRef Create(const char *filename, + static already_AddRefed Create(const char *filename, void *buffer, size_t size); /** @@ -456,7 +456,7 @@ public: * Get a Zip instance for the given path. If there is an existing one * already, return that one, otherwise create a new one. */ - static mozilla::TemporaryRef GetZip(const char *path); + static already_AddRefed GetZip(const char *path); protected: friend class Zip; diff --git a/security/manager/ssl/src/nsCertTree.cpp b/security/manager/ssl/src/nsCertTree.cpp index 45611d8bf8..27ce2a5b68 100644 --- a/security/manager/ssl/src/nsCertTree.cpp +++ b/security/manager/ssl/src/nsCertTree.cpp @@ -284,7 +284,7 @@ nsCertTree::GetCertAtIndex(int32_t index, int32_t *outAbsoluteCertOffset) } // If the row at index is a cert, return that cert. Otherwise, return null. -TemporaryRef +already_AddRefed nsCertTree::GetDispInfoAtIndex(int32_t index, int32_t *outAbsoluteCertOffset) { diff --git a/security/manager/ssl/src/nsCertTree.h b/security/manager/ssl/src/nsCertTree.h index 0907843ef0..52c616ddc1 100644 --- a/security/manager/ssl/src/nsCertTree.h +++ b/security/manager/ssl/src/nsCertTree.h @@ -131,7 +131,7 @@ private: treeArrayEl *GetThreadDescAtIndex(int32_t _index); already_AddRefed GetCertAtIndex(int32_t _index, int32_t *outAbsoluteCertOffset = nullptr); - mozilla::TemporaryRef + already_AddRefed GetDispInfoAtIndex(int32_t index, int32_t *outAbsoluteCertOffset = nullptr); void FreeCertArray(); nsresult UpdateUIContents(); diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index f15ccf8b7b..7c80ff2a9b 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1597,7 +1597,7 @@ nsNSSComponent::IsNSSInitialized(bool* initialized) SharedCertVerifier::~SharedCertVerifier() { } -TemporaryRef +already_AddRefed nsNSSComponent::GetDefaultCertVerifier() { MutexAutoLock lock(mutex); @@ -1608,7 +1608,7 @@ nsNSSComponent::GetDefaultCertVerifier() namespace mozilla { namespace psm { -TemporaryRef +already_AddRefed GetDefaultCertVerifier() { static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index ed450c3775..5e49515120 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -29,7 +29,7 @@ class SmartCardThreadList; namespace mozilla { namespace psm { MOZ_WARN_UNUSED_RESULT - ::mozilla::TemporaryRef + ::already_AddRefed GetDefaultCertVerifier(); } } // namespace mozilla::psm @@ -95,7 +95,7 @@ class NS_NO_VTABLE nsINSSComponent : public nsISupports { NS_IMETHOD IsNSSInitialized(bool* initialized) = 0; - virtual ::mozilla::TemporaryRef + virtual ::already_AddRefed GetDefaultCertVerifier() = 0; }; @@ -152,7 +152,7 @@ public: NS_IMETHOD IsNSSInitialized(bool* initialized) override; - ::mozilla::TemporaryRef + ::already_AddRefed GetDefaultCertVerifier() override; // The following two methods are thread-safe. diff --git a/toolkit/content/browser-content.js b/toolkit/content/browser-content.js index c03ff9544f..d6d9d2d50a 100644 --- a/toolkit/content/browser-content.js +++ b/toolkit/content/browser-content.js @@ -143,6 +143,7 @@ let ClickEventHandler = { stopScroll: function() { if (this._scrollable) { + this._scrollable.mozScrollSnap(); this._scrollable = null; Services.els.removeSystemEventListener(global, "mousemove", this, true); diff --git a/widget/android/APZCCallbackHandler.cpp b/widget/android/APZCCallbackHandler.cpp index a0a35afe6c..c8fd298be2 100644 --- a/widget/android/APZCCallbackHandler.cpp +++ b/widget/android/APZCCallbackHandler.cpp @@ -102,6 +102,13 @@ APZCCallbackHandler::RequestContentRepaint(const FrameMetrics& aFrameMetrics) } } +void +APZCCallbackHandler::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) +{ + APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination); +} + void APZCCallbackHandler::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, const uint32_t& aScrollGeneration) diff --git a/widget/android/APZCCallbackHandler.h b/widget/android/APZCCallbackHandler.h index 82fbe8edd5..0289f2144c 100644 --- a/widget/android/APZCCallbackHandler.h +++ b/widget/android/APZCCallbackHandler.h @@ -43,6 +43,8 @@ public: public: // GoannaContentController methods void RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics) override; + void RequestFlingSnap(const mozilla::layers::FrameMetrics::ViewID& aScrollId, + const mozilla::CSSPoint& aDestination) MOZ_OVERRIDE; void AcknowledgeScrollUpdate(const mozilla::layers::FrameMetrics::ViewID& aScrollId, const uint32_t& aScrollGeneration) override; void HandleDoubleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index 2cc7f63ba3..54e643a7b2 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -526,7 +526,7 @@ public: return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor()); } - mozilla::TemporaryRef StartRemoteDrawing() override; + already_AddRefed StartRemoteDrawing() override; void EndRemoteDrawing() override; void CleanupRemoteDrawing() override; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index a3552897d1..9ad619dc8b 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -295,7 +295,7 @@ public: virtual ~RectTextureImage(); - TemporaryRef + already_AddRefed BeginUpdate(const nsIntSize& aNewSize, const nsIntRegion& aDirtyRegion = nsIntRegion()); void EndUpdate(bool aKeepSurface = false); @@ -2511,7 +2511,7 @@ nsChildView::EnsureVibrancyManager() return *mVibrancyManager; } -TemporaryRef +already_AddRefed nsChildView::StartRemoteDrawing() { if (!mGLPresenter) { @@ -2628,7 +2628,7 @@ RectTextureImage::TextureSizeForSize(const nsIntSize& aSize) gfx::NextPowerOfTwo(aSize.height)); } -TemporaryRef +already_AddRefed RectTextureImage::BeginUpdate(const nsIntSize& aNewSize, const nsIntRegion& aDirtyRegion) { diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index ec88fb0dbd..02bfbf9199 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -946,6 +946,7 @@ static const ShadowParams kWindowShadowParametersPostYosemite[] = { void nsCocoaWindow::AdjustWindowShadow() { +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) NS_OBJC_BEGIN_TRY_ABORT_BLOCK; if (!mWindow || ![mWindow isVisible] || ![mWindow hasShadow] || @@ -962,6 +963,9 @@ nsCocoaWindow::AdjustWindowShadow() params.flags); NS_OBJC_END_TRY_ABORT_BLOCK; +#else // not 10.6 or later + return; +#endif } static const NSUInteger kWindowBackgroundBlurRadius = 4; diff --git a/widget/cocoa/nsColorPicker.mm b/widget/cocoa/nsColorPicker.mm index 3bfa42cfd3..22cf34dd11 100644 --- a/widget/cocoa/nsColorPicker.mm +++ b/widget/cocoa/nsColorPicker.mm @@ -9,6 +9,11 @@ #include "nsCocoaUtils.h" #include "nsThreadUtils.h" +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 +@protocol NSWindowDelegate +@end +#endif + using namespace mozilla; static unsigned int diff --git a/widget/cocoa/nsMenuBarX.mm b/widget/cocoa/nsMenuBarX.mm index 187bb6c4ea..1c036abd04 100644 --- a/widget/cocoa/nsMenuBarX.mm +++ b/widget/cocoa/nsMenuBarX.mm @@ -500,7 +500,10 @@ char nsMenuBarX::GetLocalizedAccelKey(const char *shortcutID) /* static */ void nsMenuBarX::ResetNativeApplicationMenu() { - [sApplicationMenu removeAllItems]; + NSInteger ni; + ni = [sApplicationMenu numberOfItems]; + for (NSInteger c = 0; c < ni; ni++) + [sApplicationMenu removeItemAtIndex:c]; [sApplicationMenu release]; sApplicationMenu = nil; } diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp index f70b537ed5..4fd4728027 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp +++ b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp @@ -126,7 +126,7 @@ status_t GonkBufferQueue::setTransformHint(uint32_t hint) { return NO_ERROR; } -TemporaryRef +already_AddRefed GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { Mutex::Autolock _l(mMutex); diff --git a/widget/gonk/nativewindow/GonkBufferQueueJB.h b/widget/gonk/nativewindow/GonkBufferQueueJB.h index afce611402..e3fa3d494b 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueJB.h +++ b/widget/gonk/nativewindow/GonkBufferQueueJB.h @@ -385,7 +385,7 @@ public: // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). status_t setTransformHint(uint32_t hint); - mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); int getSlotFromTextureClientLocked(TextureClient* client) const; diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp index 1d9a88e00d..3bacbb76f9 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp +++ b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp @@ -118,7 +118,7 @@ status_t GonkBufferQueue::setTransformHint(uint32_t hint) { return NO_ERROR; } -TemporaryRef +already_AddRefed GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { Mutex::Autolock _l(mMutex); diff --git a/widget/gonk/nativewindow/GonkBufferQueueKK.h b/widget/gonk/nativewindow/GonkBufferQueueKK.h index 0209de02c5..447437b579 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueKK.h +++ b/widget/gonk/nativewindow/GonkBufferQueueKK.h @@ -323,7 +323,7 @@ public: // dump our state in a String virtual void dumpToString(String8& result, const char* prefix) const; - mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); int getSlotFromTextureClientLocked(TextureClient* client) const; diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp index 5e7d4b378c..20367a5de3 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp +++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.cpp @@ -520,7 +520,7 @@ void GonkBufferQueueConsumer::dump(String8& result, const char* prefix) const { mCore->dump(result, prefix); } -TemporaryRef +already_AddRefed GonkBufferQueueConsumer::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { Mutex::Autolock _l(mCore->mMutex); diff --git a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h index 1bd49a9246..02ea5bbb22 100644 --- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h +++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueConsumer.h @@ -140,7 +140,7 @@ public: virtual void dump(String8& result, const char* prefix) const; // Added by mozilla - virtual mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + virtual already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); virtual int getSlotFromTextureClientLocked(GonkBufferSlot::TextureClient* client) const; diff --git a/widget/gonk/nativewindow/GonkNativeWindowICS.cpp b/widget/gonk/nativewindow/GonkNativeWindowICS.cpp index 6874efc930..a32e8a1357 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowICS.cpp +++ b/widget/gonk/nativewindow/GonkNativeWindowICS.cpp @@ -401,7 +401,7 @@ int GonkNativeWindow::getSlotFromTextureClientLocked( return BAD_VALUE; } -TemporaryRef +already_AddRefed GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { int buf = getSlotFromBufferLocked(buffer); @@ -464,7 +464,7 @@ status_t GonkNativeWindow::queueBuffer(int buf, int64_t timestamp, } -TemporaryRef +already_AddRefed GonkNativeWindow::getCurrentBuffer() { CNW_LOGD("GonkNativeWindow::getCurrentBuffer"); Mutex::Autolock lock(mMutex); diff --git a/widget/gonk/nativewindow/GonkNativeWindowICS.h b/widget/gonk/nativewindow/GonkNativeWindowICS.h index eebbd4bb51..f4ec9ef2ae 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowICS.h +++ b/widget/gonk/nativewindow/GonkNativeWindowICS.h @@ -62,7 +62,7 @@ public: // Get next frame from the queue and mark it as RENDERING, caller // owns the returned buffer. - mozilla::TemporaryRef getCurrentBuffer(); + already_AddRefed getCurrentBuffer(); // Return the buffer to the queue and mark it as FREE. After that // the buffer is useable again for the decoder. @@ -138,7 +138,7 @@ public: // then those buffer will remain allocated. void abandon(); - mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); static void RecycleCallback(TextureClient* client, void* closure); diff --git a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp index 252b0ff0e2..df7ef18e3e 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp +++ b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp @@ -108,7 +108,7 @@ status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { return mBufferQueue->setDefaultBufferFormat(defaultFormat); } -TemporaryRef +already_AddRefed GonkNativeWindow::getCurrentBuffer() { Mutex::Autolock _l(mMutex); GonkBufferQueue::BufferItem item; @@ -156,7 +156,7 @@ void GonkNativeWindow::returnBuffer(TextureClient* client) { releaseBufferLocked(index); } -TemporaryRef +already_AddRefed GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { Mutex::Autolock lock(mMutex); return mBufferQueue->getTextureClientFromBuffer(buffer); diff --git a/widget/gonk/nativewindow/GonkNativeWindowJB.h b/widget/gonk/nativewindow/GonkNativeWindowJB.h index 3a4410162d..882b307f7c 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowJB.h +++ b/widget/gonk/nativewindow/GonkNativeWindowJB.h @@ -110,13 +110,13 @@ class GonkNativeWindow: public GonkConsumerBase status_t setDefaultBufferFormat(uint32_t defaultFormat); // Get next frame from the queue, caller owns the returned buffer. - mozilla::TemporaryRef getCurrentBuffer(); + already_AddRefed getCurrentBuffer(); // Return the buffer to the queue and mark it as FREE. After that // the buffer is useable again for the decoder. void returnBuffer(TextureClient* client); - mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback); diff --git a/widget/gonk/nativewindow/GonkNativeWindowKK.cpp b/widget/gonk/nativewindow/GonkNativeWindowKK.cpp index 22be01d19e..1d73822c44 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowKK.cpp +++ b/widget/gonk/nativewindow/GonkNativeWindowKK.cpp @@ -108,7 +108,7 @@ status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { return mConsumer->setDefaultBufferFormat(defaultFormat); } -TemporaryRef +already_AddRefed GonkNativeWindow::getCurrentBuffer() { Mutex::Autolock _l(mMutex); BufferItem item; @@ -158,7 +158,7 @@ void GonkNativeWindow::returnBuffer(TextureClient* client) { releaseBufferLocked(index, mSlots[index].mGraphicBuffer); } -TemporaryRef +already_AddRefed GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { Mutex::Autolock lock(mMutex); return mConsumer->getTextureClientFromBuffer(buffer); diff --git a/widget/gonk/nativewindow/GonkNativeWindowKK.h b/widget/gonk/nativewindow/GonkNativeWindowKK.h index f9f3dc475d..13f93809f8 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowKK.h +++ b/widget/gonk/nativewindow/GonkNativeWindowKK.h @@ -112,13 +112,13 @@ class GonkNativeWindow: public GonkConsumerBase status_t setDefaultBufferFormat(uint32_t defaultFormat); // Get next frame from the queue, caller owns the returned buffer. - mozilla::TemporaryRef getCurrentBuffer(); + already_AddRefed getCurrentBuffer(); // Return the buffer to the queue and mark it as FREE. After that // the buffer is useable again for the decoder. void returnBuffer(TextureClient* client); - mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback); diff --git a/widget/gonk/nativewindow/GonkNativeWindowLL.cpp b/widget/gonk/nativewindow/GonkNativeWindowLL.cpp index bb943ec797..56b54e2ca2 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowLL.cpp +++ b/widget/gonk/nativewindow/GonkNativeWindowLL.cpp @@ -119,7 +119,7 @@ status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { return mConsumer->setDefaultBufferFormat(defaultFormat); } -TemporaryRef +already_AddRefed GonkNativeWindow::getCurrentBuffer() { Mutex::Autolock _l(mMutex); BufferItem item; @@ -175,7 +175,7 @@ void GonkNativeWindow::returnBuffer(TextureClient* client) { } } -TemporaryRef +already_AddRefed GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { Mutex::Autolock lock(mMutex); return mConsumer->getTextureClientFromBuffer(buffer); diff --git a/widget/gonk/nativewindow/GonkNativeWindowLL.h b/widget/gonk/nativewindow/GonkNativeWindowLL.h index a257cc562f..30215eb73c 100644 --- a/widget/gonk/nativewindow/GonkNativeWindowLL.h +++ b/widget/gonk/nativewindow/GonkNativeWindowLL.h @@ -105,13 +105,13 @@ class GonkNativeWindow: public GonkConsumerBase status_t setDefaultBufferFormat(uint32_t defaultFormat); // Get next frame from the queue, caller owns the returned buffer. - mozilla::TemporaryRef getCurrentBuffer(); + already_AddRefed getCurrentBuffer(); // Return the buffer to the queue and mark it as FREE. After that // the buffer is useable again for the decoder. void returnBuffer(TextureClient* client); - mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); + already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer); void setNewFrameCallback(GonkNativeWindowNewFrameCallback* callback); diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp index 5e570298e1..b751081107 100644 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp +++ b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.cpp @@ -415,7 +415,7 @@ public: } // Added by mozilla - virtual mozilla::TemporaryRef + virtual already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { return nullptr; diff --git a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h index c76aa90f19..685a3d4990 100644 --- a/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h +++ b/widget/gonk/nativewindow/IGonkGraphicBufferConsumerLL.h @@ -311,7 +311,7 @@ public: virtual void dump(String8& result, const char* prefix) const = 0; // Added by mozilla - virtual mozilla::TemporaryRef + virtual already_AddRefed getTextureClientFromBuffer(ANativeWindowBuffer* buffer) = 0; virtual int getSlotFromTextureClientLocked(mozilla::layers::TextureClient* client) const = 0; diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 8a7347288a..b3cb8dabef 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -683,7 +683,7 @@ HalFormatToSurfaceFormat(int aHalFormat, int* bytepp) } } -TemporaryRef +already_AddRefed nsWindow::StartRemoteDrawing() { GonkDisplay* display = GetGonkDisplay(); diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index d733c669b7..eb03b1c1e1 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -109,7 +109,7 @@ public: NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) /*override*/; - virtual mozilla::TemporaryRef + virtual already_AddRefed StartRemoteDrawing() override; virtual void EndRemoteDrawing() override; diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 5d0663eb39..def0c1a36e 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -6255,7 +6255,7 @@ nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable, } #endif -TemporaryRef +already_AddRefed nsWindow::StartRemoteDrawing() { gfxASurface *surf = GetThebesSurface(); diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index a7f366ea06..252be42a52 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -193,7 +193,7 @@ public: guint aTime, gpointer aData); - mozilla::TemporaryRef StartRemoteDrawing() override; + already_AddRefed StartRemoteDrawing() override; private: void UpdateAlpha(gfxPattern* aPattern, nsIntRect aBoundsRect); diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 12282abbdc..67e296d6be 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1178,7 +1178,7 @@ CompositorChild* nsBaseWidget::GetRemoteRenderer() return mCompositorChild; } -TemporaryRef nsBaseWidget::StartRemoteDrawing() +already_AddRefed nsBaseWidget::StartRemoteDrawing() { return nullptr; } diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index c3ce9fbdb8..259e47f42e 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -157,7 +157,7 @@ public: virtual void PostRender(LayerManagerComposite* aManager) override {} virtual void DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect) override {} virtual void DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) override {} - virtual mozilla::TemporaryRef StartRemoteDrawing() override; + virtual already_AddRefed StartRemoteDrawing() override; virtual void EndRemoteDrawing() override { }; virtual void CleanupRemoteDrawing() override { }; virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) override {} diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index cb898a0b8c..834a9976c3 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1583,7 +1583,7 @@ class nsIWidget : public nsISupports { * Called by BasicCompositor on the compositor thread for OMTC drawing * before each composition. */ - virtual mozilla::TemporaryRef StartRemoteDrawing() = 0; + virtual already_AddRefed StartRemoteDrawing() = 0; /** * Ensure that what was painted into the DrawTarget returned from diff --git a/widget/qt/nsWindow.cpp b/widget/qt/nsWindow.cpp index e48ab56459..2754a47481 100644 --- a/widget/qt/nsWindow.cpp +++ b/widget/qt/nsWindow.cpp @@ -805,7 +805,7 @@ nsWindow::GetGLFrameBufferFormat() return LOCAL_GL_NONE; } -TemporaryRef +already_AddRefed nsWindow::StartRemoteDrawing() { if (!mWidget) { diff --git a/widget/qt/nsWindow.h b/widget/qt/nsWindow.h index f8d054bba2..ba13219507 100644 --- a/widget/qt/nsWindow.h +++ b/widget/qt/nsWindow.h @@ -143,7 +143,7 @@ public: virtual uint32_t GetGLFrameBufferFormat() override; - mozilla::TemporaryRef StartRemoteDrawing() override; + already_AddRefed StartRemoteDrawing() override; // Widget notifications virtual void OnPaint(); diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index d14b03c8e7..1f0e432452 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -3481,7 +3481,7 @@ nsWindow::OverrideSystemMouseScrollSpeed(double aOriginalDeltaX, return NS_OK; } -mozilla::TemporaryRef +already_AddRefed nsWindow::StartRemoteDrawing() { MOZ_ASSERT(!mCompositeDC); diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index a41207e150..9ad31c0e32 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -189,7 +189,7 @@ public: NS_IMETHOD GetNonClientMargins(nsIntMargin &margins); NS_IMETHOD SetNonClientMargins(nsIntMargin &margins); void SetDrawsInTitlebar(bool aState); - mozilla::TemporaryRef StartRemoteDrawing() override; + already_AddRefed StartRemoteDrawing() override; virtual void EndRemoteDrawing() override; virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) override;