From 4e05a87d058e644a4e2d069c3454888983d83cb2 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Mon, 27 Aug 2012 19:11:05 +1200 Subject: [PATCH 01/21] Bug 780433 - Update the volume bar and scrubber icon. r=Unfocused --- .../pinstripe/global/media/videocontrols.css | 6 +++--- .../pinstripe/global/media/volumeThumb.png | Bin 167 -> 210 bytes .../winstripe/global/media/videocontrols.css | 6 +++--- .../winstripe/global/media/volumeThumb.png | Bin 167 -> 210 bytes 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/toolkit/themes/pinstripe/global/media/videocontrols.css b/toolkit/themes/pinstripe/global/media/videocontrols.css index 1adadc90aea..0fc313e1565 100644 --- a/toolkit/themes/pinstripe/global/media/videocontrols.css +++ b/toolkit/themes/pinstripe/global/media/videocontrols.css @@ -77,14 +77,14 @@ -moz-appearance: none; background: url(chrome://global/skin/media/volumeThumb.png) no-repeat center; border: none; - min-width: 16px; - min-height: 11px; + min-width: 21px; + min-height: 10px; } .volumeBackgroundBar { /* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */ margin: 0 10px; - background-color: rgba(255,255,255,.5); + background-color: rgba(255,255,255,.75); border-radius: 2.5px; } diff --git a/toolkit/themes/pinstripe/global/media/volumeThumb.png b/toolkit/themes/pinstripe/global/media/volumeThumb.png index 75ab7fb282ad3a867d64a03dba49694c0f319d26..cfd77f65045564e2db5ee7c6c5dcf82067594f64 100644 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^qCm{W!3HFwr;FYIQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F52SAuH>slu#P*AGGHKHUqKdq!Zu_%=xATcwqM9KLZB)? zPZ!4!3;*OF|Nq-Fa|DYnkX*%JGDnD~PmdKI;Vst0Jxz$ As{jB1 literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~o!3HGD9`RZNsXR{?#}JM4$q5Zj|Ns9tXZZN{ ze+#3BFEg_d1J{}V{#G;iFVA5R-dXYS(f>=AF8zP^?p=hT2j3DlPL&283;xSJ-pW>P zMo(;*d#>KN;jx8LVXFayIm7(R8!K54GkC=~6iNh$af>WxUUDSF!Ox3@;o_V(bDqC` R?FO`&!PC{xWt~$(69DdSJSG4D diff --git a/toolkit/themes/winstripe/global/media/videocontrols.css b/toolkit/themes/winstripe/global/media/videocontrols.css index 693f4191dfc..12ad44c2327 100644 --- a/toolkit/themes/winstripe/global/media/videocontrols.css +++ b/toolkit/themes/winstripe/global/media/videocontrols.css @@ -79,14 +79,14 @@ -moz-appearance: none; background: url(chrome://global/skin/media/volumeThumb.png) no-repeat center; border: none; - min-width: 16px; - min-height: 11px; + min-width: 21px; + min-height: 10px; } .volumeBackgroundBar { /* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */ margin: 0 10px; - background-color: rgba(255,255,255,.5); + background-color: rgba(255,255,255,.75); border-radius: 2.5px; } diff --git a/toolkit/themes/winstripe/global/media/volumeThumb.png b/toolkit/themes/winstripe/global/media/volumeThumb.png index 75ab7fb282ad3a867d64a03dba49694c0f319d26..cfd77f65045564e2db5ee7c6c5dcf82067594f64 100644 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^qCm{W!3HFwr;FYIQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F52SAuH>slu#P*AGGHKHUqKdq!Zu_%=xATcwqM9KLZB)? zPZ!4!3;*OF|Nq-Fa|DYnkX*%JGDnD~PmdKI;Vst0Jxz$ As{jB1 literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~o!3HGD9`RZNsXR{?#}JM4$q5Zj|Ns9tXZZN{ ze+#3BFEg_d1J{}V{#G;iFVA5R-dXYS(f>=AF8zP^?p=hT2j3DlPL&283;xSJ-pW>P zMo(;*d#>KN;jx8LVXFayIm7(R8!K54GkC=~6iNh$af>WxUUDSF!Ox3@;o_V(bDqC` R?FO`&!PC{xWt~$(69DdSJSG4D From dd3bc76051e5466a590882693845f37deac1d713 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 27 Aug 2012 17:51:48 +1000 Subject: [PATCH 02/21] No bug - Comment fix now that InvalidateAndScheduleBoundsUpdate has been renamed to InvalidateAndScheduleReflowSVG. DONTBUILD --- layout/svg/base/src/nsSVGUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index 649e90442c4..81dfaa25edc 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -733,7 +733,7 @@ nsSVGUtils::ScheduleReflowSVG(nsIFrame *aFrame) "Do not call under nsISVGChildFrame::ReflowSVG!"); // We don't call nsSVGEffects::InvalidateRenderingObservers here because - // we should only be called under InvalidateAndScheduleBoundsUpdate (which + // we should only be called under InvalidateAndScheduleReflowSVG (which // calls InvalidateBounds) or nsSVGDisplayContainerFrame::InsertFrames // (at which point the frame has no observers). From 5bbd8de743ef21cbd38e3fd59f686cb0a49c6d64 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Mon, 27 Aug 2012 20:30:29 +1200 Subject: [PATCH 03/21] Bug 784932 - Allow HTMLMediaElement.buffered to be read when readyState > HAVE_NOTHING instead of > HAVE_METADATA. r=roc --- content/html/content/src/nsHTMLMediaElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index ec27ec1114b..e7ff5ea492a 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -3429,7 +3429,7 @@ nsHTMLMediaElement::CopyInnerTo(nsGenericElement* aDest) nsresult nsHTMLMediaElement::GetBuffered(nsIDOMTimeRanges** aBuffered) { nsRefPtr ranges = new nsTimeRanges(); - if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && mDecoder) { + if (mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING && mDecoder) { // If GetBuffered fails we ignore the error result and just return the // time ranges we found up till the error. mDecoder->GetBuffered(ranges); From 50f99e06da618204dab9d0dfbbb2253c13e1f40d Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:31:33 +0200 Subject: [PATCH 04/21] Bug 781731 - Fixed Azure Cairo GTK perf by removing xlib to buffered image conversion; r=Bas --- gfx/thebes/gfxPlatform.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 7e7e4bf1329..8ec7dfa15d0 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -535,8 +535,21 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa dt->Flush(); } srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf); - } + } else #endif + if (aSurface->CairoSurface()) { + // If this is an xlib cairo surface we don't want to fetch it into memory + // because this is a major slow down. + NativeSurface surf; + surf.mFormat = format; + surf.mType = NATIVE_SURFACE_CAIRO_SURFACE; + surf.mSurface = aSurface->CairoSurface(); + srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf); + + // It's cheap enough to make a new one so we won't keep it around and + // keeping it creates a cycle. + return srcBuffer; + } if (!srcBuffer) { nsRefPtr imgSurface = aSurface->GetAsImageSurface(); From 8ee1742fda8e0f0e4f7a5b73b9657fbfdcdfe209 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:31:36 +0200 Subject: [PATCH 05/21] Bug 781731 - Fixed passing of text bounds to AdjustedTarget in order to limit the size of the temporary target; r=Bas --- content/canvas/src/nsCanvasRenderingContext2DAzure.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index fae0bcf40cd..05f05b1f643 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -3102,8 +3102,9 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP buffer.mGlyphs = &glyphBuf.front(); buffer.mNumGlyphs = glyphBuf.size(); + Rect bounds(mBoundingBox.x, mBoundingBox.y, mBoundingBox.width, mBoundingBox.height); if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL) { - AdjustedTarget(mCtx)-> + AdjustedTarget(mCtx, &bounds)-> FillGlyphs(scaledFont, buffer, CanvasGeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget), @@ -3112,7 +3113,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP RefPtr path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget); const ContextState& state = *mState; - AdjustedTarget(mCtx)-> + AdjustedTarget(mCtx, &bounds)-> Stroke(path, CanvasGeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget), StrokeOptions(state.lineWidth, state.lineJoin, From 80a032090240c31b0afc34db2683a71e2cb71b72 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:31:56 +0200 Subject: [PATCH 06/21] Bug 781731 - Clean up DrawTargetCairo::DrawSurfaceWithShadow() to make it simpler and paint correctly in all modes; r=jrmuizel --- gfx/2d/DrawTargetCairo.cpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 10e305007f5..0ec9ecd8117 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -412,19 +412,13 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, // Draw the source surface into the surface we're going to blur. SourceSurfaceCairo* source = static_cast(aSurface); cairo_surface_t* surf = source->GetSurface(); - cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf); - cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); cairo_t* ctx = cairo_create(blursurf); - - cairo_set_source(ctx, pat); - + cairo_set_source_surface(ctx, surf, 0, 0); IntRect blurrect = blur.GetRect(); cairo_new_path(ctx); cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height); - cairo_clip(ctx); - cairo_paint(ctx); - + cairo_fill(ctx); cairo_destroy(ctx); // Blur the result, then use that blurred result as a mask to draw the shadow @@ -440,32 +434,26 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, cairo_push_group(mContext); cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a); cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y); - cairo_pop_group_to_source(mContext); - cairo_paint(mContext); - // Now that the shadow has been drawn, we can draw the surface on top. - cairo_push_group(mContext); + // Now that the shadow has been drawn, we can draw the surface on top. + cairo_set_source_surface(mContext, surf, 0, 0); cairo_new_path(mContext); cairo_rectangle(mContext, 0, 0, width, height); - cairo_set_source(mContext, pat); cairo_fill(mContext); cairo_pop_group_to_source(mContext); + cairo_paint(mContext); } else { cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a); cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y); // Now that the shadow has been drawn, we can draw the surface on top. - cairo_set_source(mContext, pat); + cairo_set_source_surface(mContext, surf, 0, 0); cairo_new_path(mContext); cairo_rectangle(mContext, 0, 0, width, height); - cairo_clip(mContext); + cairo_fill(mContext); } - cairo_paint(mContext); - cairo_restore(mContext); - - cairo_pattern_destroy(pat); cairo_surface_destroy(blursurf); } From efc3961ad025b8a26335b385ccd93e10dc9a4715 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:32:14 +0200 Subject: [PATCH 07/21] Bug 781731 - Fix shadow surface extents so they aren't double padded; r=roc --- gfx/2d/Blur.cpp | 21 +++++++++++++++++-- gfx/2d/Blur.h | 12 ++++++++++- gfx/2d/DrawTargetCairo.cpp | 42 +++++++++++++++----------------------- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/gfx/2d/Blur.cpp b/gfx/2d/Blur.cpp index 9fe87983630..e8a9e7efbb9 100644 --- a/gfx/2d/Blur.cpp +++ b/gfx/2d/Blur.cpp @@ -330,7 +330,8 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, const Rect* aSkipRect) : mSpreadRadius(aSpreadRadius), mBlurRadius(aBlurRadius), - mData(nullptr) + mData(nullptr), + mFreeData(true) { Rect rect(aRect); rect.Inflate(Size(aBlurRadius + aSpreadRadius)); @@ -384,9 +385,25 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, } } +AlphaBoxBlur::AlphaBoxBlur(uint8_t* aData, + const Rect& aRect, + int8_t aStride, + float aSigma) + : mSpreadRadius(), + mBlurRadius(CalculateBlurRadius(Point(aSigma, aSigma))), + mData(aData), + mFreeData(false), + mStride(aStride), + mRect(aRect.x, aRect.y, aRect.width, aRect.height) +{ +} + + AlphaBoxBlur::~AlphaBoxBlur() { - free(mData); + if (mFreeData) { + delete mData; + } } unsigned char* diff --git a/gfx/2d/Blur.h b/gfx/2d/Blur.h index 30d84e296de..17722e3448f 100644 --- a/gfx/2d/Blur.h +++ b/gfx/2d/Blur.h @@ -57,6 +57,11 @@ public: const Rect* aDirtyRect, const Rect* aSkipRect); + AlphaBoxBlur(uint8_t* aData, + const Rect& aRect, + int8_t aStride, + float aSigma); + ~AlphaBoxBlur(); /** @@ -135,7 +140,12 @@ private: /** * A pointer to the backing 8-bit alpha surface. */ - unsigned char* mData; + uint8_t* mData; + + /** + * True if we need to dispose the data. + */ + bool mFreeData; /** * The stride of the data contained in mData. diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 0ec9ecd8117..c1facf04f69 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -387,43 +387,33 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, return; } - WillChange(); - Float width = aSurface->GetSize().width; Float height = aSurface->GetSize().height; - Rect extents(0, 0, width, height); - - AlphaBoxBlur blur(extents, IntSize(0, 0), - AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)), - nullptr, nullptr); - if (!blur.GetData()) { - return; - } - - IntSize blursize = blur.GetSize(); - cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(), - CAIRO_FORMAT_A8, - blursize.width, - blursize.height, - blur.GetStride()); - - ClearSurfaceForUnboundedSource(aOperator); - - // Draw the source surface into the surface we're going to blur. + SourceSurfaceCairo* source = static_cast(aSurface); cairo_surface_t* surf = source->GetSurface(); + + cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8, + width, + height); cairo_t* ctx = cairo_create(blursurf); cairo_set_source_surface(ctx, surf, 0, 0); - IntRect blurrect = blur.GetRect(); cairo_new_path(ctx); - cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height); + cairo_rectangle(ctx, 0, 0, width, height); cairo_fill(ctx); cairo_destroy(ctx); - - // Blur the result, then use that blurred result as a mask to draw the shadow - // colour to the surface. + + Rect extents(0, 0, width, height); + AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf), + extents, + cairo_image_surface_get_stride(blursurf), + aSigma); blur.Blur(); + + WillChange(); + ClearSurfaceForUnboundedSource(aOperator); + cairo_save(mContext); cairo_set_operator(mContext, GfxOpToCairoOp(aOperator)); cairo_identity_matrix(mContext); From c67126fb9b7f9881882efe9192fbe67da4fb3575 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:34:07 +0200 Subject: [PATCH 08/21] Bug 781731 - Speed up shadows by using tee surface to avoid doing a read back; r=roc --- .../src/nsCanvasRenderingContext2DAzure.cpp | 2 +- gfx/2d/2D.h | 9 ++++ gfx/2d/DrawTargetCairo.cpp | 52 ++++++++++++++----- gfx/2d/DrawTargetCairo.h | 2 + 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 05f05b1f643..9223a39d8b8 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -311,7 +311,7 @@ public: transform._32 -= mTempRect.y; mTarget = - mCtx->mTarget->CreateSimilarDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), + mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), FORMAT_B8G8R8A8); if (!mTarget) { diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index bc12195a674..38abe5bba09 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -727,6 +727,15 @@ public: virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0; + /* + * Create a draw target optimized for drawing a shadow. + */ + virtual TemporaryRef + CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const + { + return CreateSimilarDrawTarget(aSize, aFormat); + } + /* * Create a path builder with the specified fillmode. * diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index c1facf04f69..33d2ff7594b 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -11,6 +11,7 @@ #include "ScaledFontBase.h" #include "cairo.h" +#include "cairo-tee.h" #include #include "Blur.h" @@ -391,19 +392,11 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, Float height = aSurface->GetSize().height; SourceSurfaceCairo* source = static_cast(aSurface); - cairo_surface_t* surf = source->GetSurface(); - - cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8, - width, - height); - - cairo_t* ctx = cairo_create(blursurf); - cairo_set_source_surface(ctx, surf, 0, 0); - cairo_new_path(ctx); - cairo_rectangle(ctx, 0, 0, width, height); - cairo_fill(ctx); - cairo_destroy(ctx); + cairo_surface_t* sourcesurf = source->GetSurface(); + cairo_surface_t* blursurf = cairo_tee_surface_index(sourcesurf, 0); + cairo_surface_t* surf = cairo_tee_surface_index(sourcesurf, 1); + MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE); Rect extents(0, 0, width, height); AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf), extents, @@ -444,7 +437,6 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, } cairo_restore(mContext); - cairo_surface_destroy(blursurf); } void @@ -799,6 +791,40 @@ DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& return true; } +TemporaryRef +DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const +{ + cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext), + GfxFormatToCairoContent(aFormat), + aSize.width, aSize.height); + + if (cairo_surface_status(similar)) { + return nullptr; + } + + cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8, + aSize.width, + aSize.height); + + if (cairo_surface_status(blursurf)) { + return nullptr; + } + + cairo_surface_t* tee = cairo_tee_surface_create(blursurf); + cairo_surface_destroy(blursurf); + if (cairo_surface_status(tee)) { + cairo_surface_destroy(similar); + return nullptr; + } + + cairo_tee_surface_add(tee, similar); + cairo_surface_destroy(similar); + + RefPtr target = new DrawTargetCairo(); + target->InitAlreadyReferenced(tee, aSize); + return target; +} + bool DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize) { diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index 0f4edd5af64..68799673268 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -115,6 +115,8 @@ public: CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; + virtual TemporaryRef + CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; virtual TemporaryRef CreateGradientStops(GradientStop *aStops, From eac6b7c446ac4c89d36f8f3e47875c9fe7aa9465 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:34:12 +0200 Subject: [PATCH 09/21] Bug 781731 - Set azure shadow canvas size match thebes in order to match performance; r=roc --- content/canvas/src/nsCanvasRenderingContext2DAzure.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 9223a39d8b8..5f56c3d7c24 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -287,7 +287,8 @@ public: mTempRect = mgfx::Rect(0, 0, ctx->mWidth, ctx->mHeight); - Float blurRadius = mSigma * 3; + static const gfxFloat GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * 1.5; + int32_t blurRadius = (int32_t) floor(mSigma * GAUSSIAN_SCALE_FACTOR + 0.5); // We need to enlarge and possibly offset our temporary surface // so that things outside of the canvas may cast shadows. From 845006b170dfbf6a7fe3c7e3f2fff9a5ae87bca9 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:34:33 +0200 Subject: [PATCH 10/21] Bug 781731 - Use a similar surface for non-blurred shadows to improve performance; r=roc --- .../src/nsCanvasRenderingContext2DAzure.cpp | 2 +- gfx/2d/2D.h | 8 +++- gfx/2d/DrawTargetCairo.cpp | 41 ++++++++++++++----- gfx/2d/DrawTargetCairo.h | 3 +- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 5f56c3d7c24..bf2777d7cb4 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -313,7 +313,7 @@ public: mTarget = mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), - FORMAT_B8G8R8A8); + FORMAT_B8G8R8A8, mSigma); if (!mTarget) { // XXX - Deal with the situation where our temp size is too big to diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 38abe5bba09..2ace7846549 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -729,9 +729,15 @@ public: /* * Create a draw target optimized for drawing a shadow. + * + * Note that aSigma is the blur radius that must be used when we draw the + * shadow. Also note that this doesn't affect the size of the allocated + * surface, the caller is still responsible for including the shadow area in + * its size. */ virtual TemporaryRef - CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const + CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, + float aSigma) const { return CreateSimilarDrawTarget(aSize, aFormat); } diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 33d2ff7594b..97ca9e49477 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -393,16 +393,26 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, SourceSurfaceCairo* source = static_cast(aSurface); cairo_surface_t* sourcesurf = source->GetSurface(); - cairo_surface_t* blursurf = cairo_tee_surface_index(sourcesurf, 0); - cairo_surface_t* surf = cairo_tee_surface_index(sourcesurf, 1); - - MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE); - Rect extents(0, 0, width, height); - AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf), - extents, - cairo_image_surface_get_stride(blursurf), - aSigma); - blur.Blur(); + cairo_surface_t* blursurf; + cairo_surface_t* surf; + + // We only use the A8 surface for blurred shadows. Unblurred shadows can just + // use the RGBA surface directly. + if (cairo_surface_get_type(sourcesurf) == CAIRO_SURFACE_TYPE_TEE) { + blursurf = cairo_tee_surface_index(sourcesurf, 0); + surf = cairo_tee_surface_index(sourcesurf, 1); + + MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE); + Rect extents(0, 0, width, height); + AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf), + extents, + cairo_image_surface_get_stride(blursurf), + aSigma); + blur.Blur(); + } else { + blursurf = sourcesurf; + surf = sourcesurf; + } WillChange(); ClearSurfaceForUnboundedSource(aOperator); @@ -792,7 +802,8 @@ DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& } TemporaryRef -DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const +DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, + float aSigma) const { cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext), GfxFormatToCairoContent(aFormat), @@ -802,6 +813,14 @@ DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFor return nullptr; } + // If we don't have a blur then we can use the RGBA mask and keep all the + // operations in graphics memory. + if (aSigma == 0.0F) { + RefPtr target = new DrawTargetCairo(); + target->InitAlreadyReferenced(similar, aSize); + return target; + } + cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8, aSize.width, aSize.height); diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index 68799673268..27de74a1ebe 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -116,7 +116,8 @@ public: virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; virtual TemporaryRef - CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; + CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, + float aSigma) const; virtual TemporaryRef CreateGradientStops(GradientStop *aStops, From 00a632ec431645a4fc6028d2d86c341080545501 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 11:35:10 +0200 Subject: [PATCH 11/21] Bug 781731 - Fixed crash caused by an empty shadow region; r=Bas --- content/canvas/src/nsCanvasRenderingContext2DAzure.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index bf2777d7cb4..eb255c7f214 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -306,6 +306,13 @@ public: mTempRect = mTempRect.Intersect(*aBounds); } + // Nothing to draw + if (mTempRect.IsEmpty()) { + mTarget = ctx->mTarget; + mCtx = nullptr; + return; + } + mTempRect.ScaleRoundOut(1.0f); transform._31 -= mTempRect.x; @@ -313,7 +320,7 @@ public: mTarget = mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), - FORMAT_B8G8R8A8, mSigma); + FORMAT_B8G8R8A8, mSigma); if (!mTarget) { // XXX - Deal with the situation where our temp size is too big to From bf498a4c08efa005c2a0b7754242121eb0238037 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 27 Aug 2012 22:01:47 +1200 Subject: [PATCH 12/21] Bug 781731 - Fixed failed assertion in reftest1; r=doublec --- gfx/2d/Blur.cpp | 2 +- gfx/2d/Blur.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/2d/Blur.cpp b/gfx/2d/Blur.cpp index e8a9e7efbb9..6849d8b2176 100644 --- a/gfx/2d/Blur.cpp +++ b/gfx/2d/Blur.cpp @@ -387,7 +387,7 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, AlphaBoxBlur::AlphaBoxBlur(uint8_t* aData, const Rect& aRect, - int8_t aStride, + int32_t aStride, float aSigma) : mSpreadRadius(), mBlurRadius(CalculateBlurRadius(Point(aSigma, aSigma))), diff --git a/gfx/2d/Blur.h b/gfx/2d/Blur.h index 17722e3448f..68bb06d4a9f 100644 --- a/gfx/2d/Blur.h +++ b/gfx/2d/Blur.h @@ -59,7 +59,7 @@ public: AlphaBoxBlur(uint8_t* aData, const Rect& aRect, - int8_t aStride, + int32_t aStride, float aSigma); ~AlphaBoxBlur(); From 6a8ff69ba11c1bbfb7fa10cc1f0043e6a7d5462c Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 27 Aug 2012 12:27:40 +0200 Subject: [PATCH 13/21] Backout bug 781731. --- .../src/nsCanvasRenderingContext2DAzure.cpp | 19 +-- gfx/2d/2D.h | 15 --- gfx/2d/Blur.cpp | 21 +-- gfx/2d/Blur.h | 12 +- gfx/2d/DrawTargetCairo.cpp | 125 +++++++----------- gfx/2d/DrawTargetCairo.h | 3 - gfx/thebes/gfxPlatform.cpp | 15 +-- 7 files changed, 60 insertions(+), 150 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index eb255c7f214..fae0bcf40cd 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -287,8 +287,7 @@ public: mTempRect = mgfx::Rect(0, 0, ctx->mWidth, ctx->mHeight); - static const gfxFloat GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * 1.5; - int32_t blurRadius = (int32_t) floor(mSigma * GAUSSIAN_SCALE_FACTOR + 0.5); + Float blurRadius = mSigma * 3; // We need to enlarge and possibly offset our temporary surface // so that things outside of the canvas may cast shadows. @@ -306,21 +305,14 @@ public: mTempRect = mTempRect.Intersect(*aBounds); } - // Nothing to draw - if (mTempRect.IsEmpty()) { - mTarget = ctx->mTarget; - mCtx = nullptr; - return; - } - mTempRect.ScaleRoundOut(1.0f); transform._31 -= mTempRect.x; transform._32 -= mTempRect.y; mTarget = - mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), - FORMAT_B8G8R8A8, mSigma); + mCtx->mTarget->CreateSimilarDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), + FORMAT_B8G8R8A8); if (!mTarget) { // XXX - Deal with the situation where our temp size is too big to @@ -3110,9 +3102,8 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP buffer.mGlyphs = &glyphBuf.front(); buffer.mNumGlyphs = glyphBuf.size(); - Rect bounds(mBoundingBox.x, mBoundingBox.y, mBoundingBox.width, mBoundingBox.height); if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL) { - AdjustedTarget(mCtx, &bounds)-> + AdjustedTarget(mCtx)-> FillGlyphs(scaledFont, buffer, CanvasGeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget), @@ -3121,7 +3112,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP RefPtr path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget); const ContextState& state = *mState; - AdjustedTarget(mCtx, &bounds)-> + AdjustedTarget(mCtx)-> Stroke(path, CanvasGeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget), StrokeOptions(state.lineWidth, state.lineJoin, diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 2ace7846549..bc12195a674 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -727,21 +727,6 @@ public: virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0; - /* - * Create a draw target optimized for drawing a shadow. - * - * Note that aSigma is the blur radius that must be used when we draw the - * shadow. Also note that this doesn't affect the size of the allocated - * surface, the caller is still responsible for including the shadow area in - * its size. - */ - virtual TemporaryRef - CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const - { - return CreateSimilarDrawTarget(aSize, aFormat); - } - /* * Create a path builder with the specified fillmode. * diff --git a/gfx/2d/Blur.cpp b/gfx/2d/Blur.cpp index 6849d8b2176..9fe87983630 100644 --- a/gfx/2d/Blur.cpp +++ b/gfx/2d/Blur.cpp @@ -330,8 +330,7 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, const Rect* aSkipRect) : mSpreadRadius(aSpreadRadius), mBlurRadius(aBlurRadius), - mData(nullptr), - mFreeData(true) + mData(nullptr) { Rect rect(aRect); rect.Inflate(Size(aBlurRadius + aSpreadRadius)); @@ -385,25 +384,9 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, } } -AlphaBoxBlur::AlphaBoxBlur(uint8_t* aData, - const Rect& aRect, - int32_t aStride, - float aSigma) - : mSpreadRadius(), - mBlurRadius(CalculateBlurRadius(Point(aSigma, aSigma))), - mData(aData), - mFreeData(false), - mStride(aStride), - mRect(aRect.x, aRect.y, aRect.width, aRect.height) -{ -} - - AlphaBoxBlur::~AlphaBoxBlur() { - if (mFreeData) { - delete mData; - } + free(mData); } unsigned char* diff --git a/gfx/2d/Blur.h b/gfx/2d/Blur.h index 68bb06d4a9f..30d84e296de 100644 --- a/gfx/2d/Blur.h +++ b/gfx/2d/Blur.h @@ -57,11 +57,6 @@ public: const Rect* aDirtyRect, const Rect* aSkipRect); - AlphaBoxBlur(uint8_t* aData, - const Rect& aRect, - int32_t aStride, - float aSigma); - ~AlphaBoxBlur(); /** @@ -140,12 +135,7 @@ private: /** * A pointer to the backing 8-bit alpha surface. */ - uint8_t* mData; - - /** - * True if we need to dispose the data. - */ - bool mFreeData; + unsigned char* mData; /** * The stride of the data contained in mData. diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 97ca9e49477..10e305007f5 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -11,7 +11,6 @@ #include "ScaledFontBase.h" #include "cairo.h" -#include "cairo-tee.h" #include #include "Blur.h" @@ -388,35 +387,49 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, return; } + WillChange(); + Float width = aSurface->GetSize().width; Float height = aSurface->GetSize().height; - - SourceSurfaceCairo* source = static_cast(aSurface); - cairo_surface_t* sourcesurf = source->GetSurface(); - cairo_surface_t* blursurf; - cairo_surface_t* surf; + Rect extents(0, 0, width, height); - // We only use the A8 surface for blurred shadows. Unblurred shadows can just - // use the RGBA surface directly. - if (cairo_surface_get_type(sourcesurf) == CAIRO_SURFACE_TYPE_TEE) { - blursurf = cairo_tee_surface_index(sourcesurf, 0); - surf = cairo_tee_surface_index(sourcesurf, 1); - - MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE); - Rect extents(0, 0, width, height); - AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf), - extents, - cairo_image_surface_get_stride(blursurf), - aSigma); - blur.Blur(); - } else { - blursurf = sourcesurf; - surf = sourcesurf; + AlphaBoxBlur blur(extents, IntSize(0, 0), + AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)), + nullptr, nullptr); + if (!blur.GetData()) { + return; } - WillChange(); + IntSize blursize = blur.GetSize(); + cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(), + CAIRO_FORMAT_A8, + blursize.width, + blursize.height, + blur.GetStride()); + ClearSurfaceForUnboundedSource(aOperator); + // Draw the source surface into the surface we're going to blur. + SourceSurfaceCairo* source = static_cast(aSurface); + cairo_surface_t* surf = source->GetSurface(); + cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); + + cairo_t* ctx = cairo_create(blursurf); + + cairo_set_source(ctx, pat); + + IntRect blurrect = blur.GetRect(); + cairo_new_path(ctx); + cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height); + cairo_clip(ctx); + cairo_paint(ctx); + + cairo_destroy(ctx); + + // Blur the result, then use that blurred result as a mask to draw the shadow + // colour to the surface. + blur.Blur(); cairo_save(mContext); cairo_set_operator(mContext, GfxOpToCairoOp(aOperator)); cairo_identity_matrix(mContext); @@ -427,26 +440,33 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, cairo_push_group(mContext); cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a); cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y); - - // Now that the shadow has been drawn, we can draw the surface on top. - cairo_set_source_surface(mContext, surf, 0, 0); - cairo_new_path(mContext); - cairo_rectangle(mContext, 0, 0, width, height); - cairo_fill(mContext); cairo_pop_group_to_source(mContext); cairo_paint(mContext); + + // Now that the shadow has been drawn, we can draw the surface on top. + cairo_push_group(mContext); + cairo_new_path(mContext); + cairo_rectangle(mContext, 0, 0, width, height); + cairo_set_source(mContext, pat); + cairo_fill(mContext); + cairo_pop_group_to_source(mContext); } else { cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a); cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y); // Now that the shadow has been drawn, we can draw the surface on top. - cairo_set_source_surface(mContext, surf, 0, 0); + cairo_set_source(mContext, pat); cairo_new_path(mContext); cairo_rectangle(mContext, 0, 0, width, height); - cairo_fill(mContext); + cairo_clip(mContext); } + cairo_paint(mContext); + cairo_restore(mContext); + + cairo_pattern_destroy(pat); + cairo_surface_destroy(blursurf); } void @@ -801,49 +821,6 @@ DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& return true; } -TemporaryRef -DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const -{ - cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext), - GfxFormatToCairoContent(aFormat), - aSize.width, aSize.height); - - if (cairo_surface_status(similar)) { - return nullptr; - } - - // If we don't have a blur then we can use the RGBA mask and keep all the - // operations in graphics memory. - if (aSigma == 0.0F) { - RefPtr target = new DrawTargetCairo(); - target->InitAlreadyReferenced(similar, aSize); - return target; - } - - cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8, - aSize.width, - aSize.height); - - if (cairo_surface_status(blursurf)) { - return nullptr; - } - - cairo_surface_t* tee = cairo_tee_surface_create(blursurf); - cairo_surface_destroy(blursurf); - if (cairo_surface_status(tee)) { - cairo_surface_destroy(similar); - return nullptr; - } - - cairo_tee_surface_add(tee, similar); - cairo_surface_destroy(similar); - - RefPtr target = new DrawTargetCairo(); - target->InitAlreadyReferenced(tee, aSize); - return target; -} - bool DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize) { diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index 27de74a1ebe..0f4edd5af64 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -115,9 +115,6 @@ public: CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; - virtual TemporaryRef - CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const; virtual TemporaryRef CreateGradientStops(GradientStop *aStops, diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 8ec7dfa15d0..7e7e4bf1329 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -535,21 +535,8 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa dt->Flush(); } srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf); - } else -#endif - if (aSurface->CairoSurface()) { - // If this is an xlib cairo surface we don't want to fetch it into memory - // because this is a major slow down. - NativeSurface surf; - surf.mFormat = format; - surf.mType = NATIVE_SURFACE_CAIRO_SURFACE; - surf.mSurface = aSurface->CairoSurface(); - srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf); - - // It's cheap enough to make a new one so we won't keep it around and - // keeping it creates a cycle. - return srcBuffer; } +#endif if (!srcBuffer) { nsRefPtr imgSurface = aSurface->GetAsImageSurface(); From 5d201148e6437190d428e7e6b9a5f0f0b845c709 Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Mon, 27 Aug 2012 21:16:38 +1000 Subject: [PATCH 14/21] Bug 780987 - implement social.user-recommend-* messages. r=mixedpuppy --- browser/base/content/browser-social.js | 81 ++++++++++++++++-- browser/base/content/test/Makefile.in | 1 + .../test/browser_social_shareButton.js | 19 +++- browser/base/content/test/head.js | 9 ++ .../base/content/test/social_share_image.png | Bin 0 -> 934 bytes browser/base/content/test/social_worker.js | 19 ++++ .../en-US/chrome/browser/browser.properties | 4 - browser/themes/gnomestripe/browser.css | 11 +-- browser/themes/gnomestripe/jar.mn | 3 - .../gnomestripe/share-button-active.png | Bin 1249 -> 0 bytes .../gnomestripe/share-button-shared.png | Bin 1460 -> 0 bytes browser/themes/gnomestripe/share-button.png | Bin 1245 -> 0 bytes browser/themes/pinstripe/browser.css | 11 +-- browser/themes/pinstripe/jar.mn | 3 - .../themes/pinstripe/share-button-active.png | Bin 1249 -> 0 bytes .../themes/pinstripe/share-button-shared.png | Bin 1460 -> 0 bytes browser/themes/pinstripe/share-button.png | Bin 1245 -> 0 bytes browser/themes/winstripe/browser.css | 11 +-- browser/themes/winstripe/jar.mn | 6 -- .../themes/winstripe/share-button-active.png | Bin 1249 -> 0 bytes .../themes/winstripe/share-button-shared.png | Bin 1460 -> 0 bytes browser/themes/winstripe/share-button.png | Bin 1245 -> 0 bytes 22 files changed, 126 insertions(+), 52 deletions(-) create mode 100644 browser/base/content/test/social_share_image.png delete mode 100644 browser/themes/gnomestripe/share-button-active.png delete mode 100644 browser/themes/gnomestripe/share-button-shared.png delete mode 100644 browser/themes/gnomestripe/share-button.png delete mode 100644 browser/themes/pinstripe/share-button-active.png delete mode 100644 browser/themes/pinstripe/share-button-shared.png delete mode 100644 browser/themes/pinstripe/share-button.png delete mode 100644 browser/themes/winstripe/share-button-active.png delete mode 100644 browser/themes/winstripe/share-button-shared.png delete mode 100644 browser/themes/winstripe/share-button.png diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js index dfc1c681e4f..4d1d142d870 100644 --- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -293,6 +293,12 @@ let SocialFlyout = { } let SocialShareButton = { + // promptImages and promptMessages being null means we are yet to get the + // message back from the provider with the images and icons (or that we got + // the response but determined it was invalid.) + promptImages: null, + promptMessages: null, + // Called once, after window load, when the Social.provider object is initialized init: function SSB_init() { this.updateButtonHiddenState(); @@ -311,6 +317,61 @@ let SocialShareButton = { } else { profileRow.hidden = true; } + // XXX - this shouldn't be done as part of updateProfileInfo, but instead + // whenever we notice the provider has changed - but the concept of + // "provider changed" will only exist once bug 774520 lands. + this.promptImages = null; + this.promptMessages = null; + // get the recommend-prompt info. + let port = Social.provider._getWorkerPort(); + if (port) { + port.onmessage = function(evt) { + if (evt.data.topic == "social.user-recommend-prompt-response") { + port.close(); + this.acceptRecommendInfo(evt.data.data); + this.updateButtonHiddenState(); + this.updateShareState(); + } + }.bind(this); + port.postMessage({topic: "social.user-recommend-prompt"}); + } + }, + + acceptRecommendInfo: function SSB_acceptRecommendInfo(data) { + // Accept *and validate* the user-recommend-prompt-response message. + let promptImages = {}; + let promptMessages = {}; + function reportError(reason) { + Cu.reportError("Invalid recommend data from provider: " + reason + ": sharing is disabled for this provider"); + return false; + } + if (!data || + !data.images || typeof data.images != "object" || + !data.messages || typeof data.messages != "object") { + return reportError("data is missing valid 'images' or 'messages' elements"); + } + for (let sub of ["share", "unshare"]) { + let url = data.images[sub]; + if (!url || typeof url != "string" || url.length == 0) { + return reportError('images["' + sub + '"] is missing or not a non-empty string'); + } + // resolve potentially relative URLs then check the scheme is acceptable. + url = Services.io.newURI(Social.provider.origin, null, null).resolve(url); + let uri = Services.io.newURI(url, null, null); + if (!uri.schemeIs("http") && !uri.schemeIs("https") && !uri.schemeIs("data")) { + return reportError('images["' + sub + '"] does not have a valid scheme'); + } + promptImages[sub] = url; + } + for (let sub of ["shareTooltip", "unshareTooltip", "sharedLabel", "unsharedLabel"]) { + if (typeof data.messages[sub] != "string" || data.messages[sub].length == 0) { + return reportError('messages["' + sub + '"] is not a valid string'); + } + promptMessages[sub] = data.messages[sub]; + } + this.promptImages = promptImages; + this.promptMessages = promptMessages; + return true; }, get shareButton() { @@ -327,7 +388,7 @@ let SocialShareButton = { updateButtonHiddenState: function SSB_updateButtonHiddenState() { let shareButton = this.shareButton; if (shareButton) - shareButton.hidden = !Social.uiVisible; + shareButton.hidden = !Social.uiVisible || this.promptImages == null; }, onClick: function SSB_onClick(aEvent) { @@ -370,23 +431,33 @@ let SocialShareButton = { // Provide a11y-friendly notification of share. let status = document.getElementById("share-button-status"); if (status) { + // XXX - this should also be capable of reflecting that the page was + // unshared (ie, it needs to manage three-states: (1) nothing done, (2) + // shared, (3) shared then unshared) + // Note that we *do* have an appropriate string from the provider for + // this (promptMessages['unsharedLabel'] but currently lack a way of + // tracking this state) let statusString = currentPageShared ? - gNavigatorBundle.getString("social.pageShared.label") : ""; + this.promptMessages['sharedLabel'] : ""; status.setAttribute("value", statusString); } // Update the share button, if present let shareButton = this.shareButton; - if (!shareButton) + if (!shareButton || shareButton.hidden) return; + let imageURL; if (currentPageShared) { shareButton.setAttribute("shared", "true"); - shareButton.setAttribute("tooltiptext", gNavigatorBundle.getString("social.shareButton.sharedtooltip")); + shareButton.setAttribute("tooltiptext", this.promptMessages['unshareTooltip']); + imageURL = this.promptImages["unshare"] } else { shareButton.removeAttribute("shared"); - shareButton.setAttribute("tooltiptext", gNavigatorBundle.getString("social.shareButton.tooltip")); + shareButton.setAttribute("tooltiptext", this.promptMessages['shareTooltip']); + imageURL = this.promptImages["share"] } + shareButton.style.backgroundImage = 'url("' + encodeURI(imageURL) + '")'; } }; diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index c1ff516cd03..4fe61ae88ae 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -268,6 +268,7 @@ _BROWSER_FILES = \ browser_social_isVisible.js \ browser_social_chatwindow.js \ social_panel.html \ + social_share_image.png \ social_sidebar.html \ social_chat.html \ social_flyout.html \ diff --git a/browser/base/content/test/browser_social_shareButton.js b/browser/base/content/test/browser_social_shareButton.js index 4788b0a797c..c442acdd5ca 100644 --- a/browser/base/content/test/browser_social_shareButton.js +++ b/browser/base/content/test/browser_social_shareButton.js @@ -48,11 +48,12 @@ function testInitial(finishcb) { let okButton = document.getElementById("editSharePopupOkButton"); let undoButton = document.getElementById("editSharePopupUndoButton"); + let shareStatusLabel = document.getElementById("share-button-status"); // ensure the worker initialization and handshakes are all done and we - // have a profile. - waitForCondition(function() Social.provider.profile, function() { - is(shareButton.hidden, false, "share button should be visible"); + // have a profile and the worker has responsed to the recommend-prompt msg. + waitForCondition(function() Social.provider.profile && SocialShareButton.promptImages != null, function() { + is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' attribute before share button is clicked"); // check dom values let profile = Social.provider.profile; let portrait = document.getElementById("socialUserPortrait").getAttribute("src"); @@ -61,14 +62,24 @@ function testInitial(finishcb) { is(displayName.label, profile.displayName, "display name is set"); ok(!document.getElementById("editSharePopupHeader").hidden, "user profile is visible"); + // Check the strings from our worker actually ended up on the button. + is(shareButton.getAttribute("tooltiptext"), "Share this page", "check tooltip text is correct"); + is(shareStatusLabel.getAttribute("value"), "", "check status label text is blank"); + // Check the relative URL was resolved correctly (note this image has offsets of zero...) + is(shareButton.style.backgroundImage, 'url("https://example.com/browser/browser/base/content/test/social_share_image.png")', "check image url is correct"); + // Test clicking the share button shareButton.addEventListener("click", function listener() { shareButton.removeEventListener("click", listener); is(shareButton.hasAttribute("shared"), true, "Share button should have 'shared' attribute after share button is clicked"); + is(shareButton.getAttribute("tooltiptext"), "Unshare this page", "check tooltip text is correct"); + is(shareStatusLabel.getAttribute("value"), "This page has been shared", "check status label text is correct"); + // Check the URL and offsets were applied correctly + is(shareButton.style.backgroundImage, 'url("https://example.com/browser/browser/base/content/test/social_share_image.png")', "check image url is correct"); executeSoon(testSecondClick.bind(window, testPopupOKButton)); }); EventUtils.synthesizeMouseAtCenter(shareButton, {}); - }, "provider didn't provide a profile"); + }, "provider didn't provide user-recommend-prompt response"); } function testSecondClick(nextTest) { diff --git a/browser/base/content/test/head.js b/browser/base/content/test/head.js index e22bf9184ba..8cc7597b316 100644 --- a/browser/base/content/test/head.js +++ b/browser/base/content/test/head.js @@ -134,6 +134,15 @@ function runSocialTestWithProvider(manifest, callback) { Services.prefs.setBoolPref("social.enabled", true); registerCleanupFunction(function () { + // if one test happens to fail, it is likely finishSocialTest will not + // be called, causing most future social tests to also fail as they + // attempt to add a provider which already exists - so work + // around that by also attempting to remove the test provider. + try { + SocialService.removeProvider(provider.origin, finish); + } catch (ex) { + ; + } Social.provider = oldProvider; Services.prefs.clearUserPref("social.enabled"); }); diff --git a/browser/base/content/test/social_share_image.png b/browser/base/content/test/social_share_image.png new file mode 100644 index 0000000000000000000000000000000000000000..fa1f8fb0e23b9689e51f667a5745898f929c0960 GIT binary patch literal 934 zcmV;X16lluP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&13O7XK~y+Tl~h?w z6HyeMX{VqdxP&#JML>gzF^WngX*5D0u|Y_zMiP}w{Nn>rQGbz7P5f-4KNwn+O$AF> zgVKtXvK0svEfujSv``QVEiLUV-kGsuAw}@@HhD91-#O>r^WH<~?G2J7H9f%ov98nOhJH8ceDV?e4Hp5)gc%_{E?d0-#BRtRAg? z*i-7p+yYcU5r3s@O5i1k=1!fqes*Z(4dvK5_OLD4PKMLBp0c*InFr8st)ta@owK*XwL`W7rL58Q|C<5?-2w=gd z{t;DsmuJl*6rj0T68(sAb=AdM$cC@!OYWryP4}e=>9}pY;qu$un7rKRJk^y({3I?w z1j>E|*T8kV$i3!y)1ua~dV%S}`Sj%#r*Xo}%jZ2X+Kh#Dg`@KZPALSQhC^_wD|#y` zdKEr=-!`4K{ZiC5PfpEnaFWxaB+>@BOKQlWayK11y-xy_& zvertb6vTcuO%55xcLWE8hU^4$hQ~}d^K&swIAgU9jv9Yj=6HyEh1Yp+0RoO| z$?KBT_|$?k1@K;}Q#Kiz9F&73$hN{Z3}sFO^FMOvAOwd3e6zL%pp1`=YVGVkm!2v~ zJN`kZ_osm_(~K}$go=vJ78N%XGkb~oaWQ}n6W&;Mu>c;!1Yw95DZN .ac-url-box > .ac-action- /* social recommending panel */ #share-button { - list-style-image: url(chrome://browser/skin/share-button.png); -} - -#share-button:not([shared]):not([disabled]):hover { - list-style-image: url(chrome://browser/skin/share-button-active.png); -} - -#share-button[shared] { - list-style-image: url(chrome://browser/skin/share-button-shared.png); + width: 16px; + height: 16px; } #socialUserPortrait { diff --git a/browser/themes/gnomestripe/jar.mn b/browser/themes/gnomestripe/jar.mn index a1e3276dde1..b7ad8ceb6a4 100644 --- a/browser/themes/gnomestripe/jar.mn +++ b/browser/themes/gnomestripe/jar.mn @@ -39,9 +39,6 @@ browser.jar: skin/classic/browser/Secure.png skin/classic/browser/Security-broken.png skin/classic/browser/setDesktopBackground.css - skin/classic/browser/share-button.png - skin/classic/browser/share-button-active.png - skin/classic/browser/share-button-shared.png skin/classic/browser/Toolbar.png skin/classic/browser/Toolbar-small.png skin/classic/browser/urlbar-arrow.png diff --git a/browser/themes/gnomestripe/share-button-active.png b/browser/themes/gnomestripe/share-button-active.png deleted file mode 100644 index a87501e89b3112b507b9385d43d021e7700fb150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1249 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=up}Cu>lZ&aVv6H2tp{s$DnT4~38IWZLlrVB} zgXwk2PcF?(%`1WFO+n~2!>JdP6mkoIHoK%2WtOF;xE1B+DuBIgm5JLe#yHJ`>P^Az z789I$^?{Dj2SqGWM8kxDsRzV_CtDx~p72xifT_I*n5@6tj!tD@U<~ziaSW-rmGtBP ze|zSY5vl*x%@pQwCK($};0XC%J1P0c_x}b0%Nu{_EXfGF`S~EH$65z5@eBj1X%3tBdDc33uAaCa0p++e%Q;1*Ei!X8w-zWLBYgDV@91Ex2|6!UgOC$QOi zUrRYMYeIuieIutTcL#GL(Cwd@Kbk0rF`c@}l*z7O*L0cHK*8{Dkp3j@ZTn7K`Ro|p zY_7?iyOKSrRH2Uj$jcj|f+uz@5zopr E08!kg%>V!Z diff --git a/browser/themes/gnomestripe/share-button-shared.png b/browser/themes/gnomestripe/share-button-shared.png deleted file mode 100644 index cb8a11e81d899117cc02c924525c99182b7b8166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1460 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=miIbtBv7582v6H2tp{s$DnT4~38IWaWXzpg@ z;s(>}lAm0fo0?Yw)0=|O>w;4+C@JI?0Bv?jEy^rQO>ryA&s6|>*(wvaTO4tk2i2Q` z+bvEw_38s1qYsK$q=<$I0aFi%2~V~_4m{zf<^fZC5inV|2bpeWU|`blba4!+xHV<+ z!R#vzBFECzPM#@Sz2kyygn_cH$j1ks+DB)1b*vB#5lHFpstDk3I#DM0GAwq_5B`b} zu4`dBaV{<)+t_Vio^95cT(WkzQ~AZ5$vKlg`rgP{th0?xZt~2^{pR;;Di5|UWx92s zdAH-08^124tX;phy5|44?kDz%xj+AY>Ig25%WNz2TRV~WfFZ|1{k>cH7deC(&o-_u ziS7S>(kg*}TU^&_HdC=13a5n+EK=wa{#vRs`PuTRbCRvUvzzhCT$fzJe7(?GBZBwc zfqhs0v({G!-_~?C;hyCF@SN?9zc0hi9IoLiQo6(+vgz&fYb_kkw!njv{+${~fG=c^i?EdSvw zkuD^>SAO2bin}*ld95_%xR3ZBcU>|=)b&NA8 z=U%lC3Xwb2`?So&-t2o@Tt%?qj^D-)>)vLcjVO0~_w)z%mc8$9iRIq^Ffq~E(u37g z)1y5|IMsbq>i)Oanan>dTzJ0Zp@!_=sK~P885uPzRPDOG6K;gXJ?O5FH9hxN_W%Ra Wia%XpEQh^8<*28tpUXO@geCyiVI1fH diff --git a/browser/themes/gnomestripe/share-button.png b/browser/themes/gnomestripe/share-button.png deleted file mode 100644 index 86bd5ec70add448cfa5647e9448d9bb2ea5349a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1245 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=up}Cu>lZ&CNv6H2tp{s$DnT4~38IWZLlrVB} zgXwk2PcF?(%`1WFO+n~2!l@UO6mkoIHoK%2WtOF;xE1B+DuBIgm5I|W&Tcr(gX&Ge z?G^)^di8;h(Fa8=QbfaqfT;(>geO}d2cGa#^MI+n2$-yer@y|;z`z*j>EaktacjzD zd+);mBJB^abSZE+9o(92*RZ;YBhOXC!h@Zay_GA^^@^j5po{L;c;V(L*Q7#@BxyJ8 zFjKIw>}(T$ry(_6^S!2jg}2$V ziN``BF8yb$-eu{NUD5tG>Y(wx)a}2%OO>(Sxc)6M)qcW* z#L`SX;a@x{M{CzPA2kc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=up}Cu>lZ&aVv6H2tp{s$DnT4~38IWZLlrVB} zgXwk2PcF?(%`1WFO+n~2!>JdP6mkoIHoK%2WtOF;xE1B+DuBIgm5JLe#yHJ`>P^Az z789I$^?{Dj2SqGWM8kxDsRzV_CtDx~p72xifT_I*n5@6tj!tD@U<~ziaSW-rmGtBP ze|zSY5vl*x%@pQwCK($};0XC%J1P0c_x}b0%Nu{_EXfGF`S~EH$65z5@eBj1X%3tBdDc33uAaCa0p++e%Q;1*Ei!X8w-zWLBYgDV@91Ex2|6!UgOC$QOi zUrRYMYeIuieIutTcL#GL(Cwd@Kbk0rF`c@}l*z7O*L0cHK*8{Dkp3j@ZTn7K`Ro|p zY_7?iyOKSrRH2Uj$jcj|f+uz@5zopr E08!kg%>V!Z diff --git a/browser/themes/pinstripe/share-button-shared.png b/browser/themes/pinstripe/share-button-shared.png deleted file mode 100644 index cb8a11e81d899117cc02c924525c99182b7b8166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1460 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=miIbtBv7582v6H2tp{s$DnT4~38IWaWXzpg@ z;s(>}lAm0fo0?Yw)0=|O>w;4+C@JI?0Bv?jEy^rQO>ryA&s6|>*(wvaTO4tk2i2Q` z+bvEw_38s1qYsK$q=<$I0aFi%2~V~_4m{zf<^fZC5inV|2bpeWU|`blba4!+xHV<+ z!R#vzBFECzPM#@Sz2kyygn_cH$j1ks+DB)1b*vB#5lHFpstDk3I#DM0GAwq_5B`b} zu4`dBaV{<)+t_Vio^95cT(WkzQ~AZ5$vKlg`rgP{th0?xZt~2^{pR;;Di5|UWx92s zdAH-08^124tX;phy5|44?kDz%xj+AY>Ig25%WNz2TRV~WfFZ|1{k>cH7deC(&o-_u ziS7S>(kg*}TU^&_HdC=13a5n+EK=wa{#vRs`PuTRbCRvUvzzhCT$fzJe7(?GBZBwc zfqhs0v({G!-_~?C;hyCF@SN?9zc0hi9IoLiQo6(+vgz&fYb_kkw!njv{+${~fG=c^i?EdSvw zkuD^>SAO2bin}*ld95_%xR3ZBcU>|=)b&NA8 z=U%lC3Xwb2`?So&-t2o@Tt%?qj^D-)>)vLcjVO0~_w)z%mc8$9iRIq^Ffq~E(u37g z)1y5|IMsbq>i)Oanan>dTzJ0Zp@!_=sK~P885uPzRPDOG6K;gXJ?O5FH9hxN_W%Ra Wia%XpEQh^8<*28tpUXO@geCyiVI1fH diff --git a/browser/themes/pinstripe/share-button.png b/browser/themes/pinstripe/share-button.png deleted file mode 100644 index 86bd5ec70add448cfa5647e9448d9bb2ea5349a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1245 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=up}Cu>lZ&CNv6H2tp{s$DnT4~38IWZLlrVB} zgXwk2PcF?(%`1WFO+n~2!l@UO6mkoIHoK%2WtOF;xE1B+DuBIgm5I|W&Tcr(gX&Ge z?G^)^di8;h(Fa8=QbfaqfT;(>geO}d2cGa#^MI+n2$-yer@y|;z`z*j>EaktacjzD zd+);mBJB^abSZE+9o(92*RZ;YBhOXC!h@Zay_GA^^@^j5po{L;c;V(L*Q7#@BxyJ8 zFjKIw>}(T$ry(_6^S!2jg}2$V ziN``BF8yb$-eu{NUD5tG>Y(wx)a}2%OO>(Sxc)6M)qcW* z#L`SX;a@x{M{CzPA2k .ac-url-box > .ac-action- /* social recommending panel */ #share-button { - list-style-image: url(chrome://browser/skin/share-button.png); -} - -#share-button:not([shared]):not([disabled]):hover { - list-style-image: url(chrome://browser/skin/share-button-active.png); -} - -#share-button[shared] { - list-style-image: url(chrome://browser/skin/share-button-shared.png); + width: 16px; + height: 16px; } #socialUserPortrait { diff --git a/browser/themes/winstripe/jar.mn b/browser/themes/winstripe/jar.mn index 2e1678e807d..345dc068648 100644 --- a/browser/themes/winstripe/jar.mn +++ b/browser/themes/winstripe/jar.mn @@ -50,9 +50,6 @@ browser.jar: skin/classic/browser/searchbar.css (searchbar.css) skin/classic/browser/searchbar-dropdown-arrow.png skin/classic/browser/setDesktopBackground.css - skin/classic/browser/share-button.png - skin/classic/browser/share-button-active.png - skin/classic/browser/share-button-shared.png skin/classic/browser/menu-back.png (menu-back.png) skin/classic/browser/menu-forward.png (menu-forward.png) skin/classic/browser/monitor.png @@ -254,9 +251,6 @@ browser.jar: skin/classic/aero/browser/searchbar.css (searchbar.css) skin/classic/aero/browser/searchbar-dropdown-arrow.png (searchbar-dropdown-arrow-aero.png) skin/classic/aero/browser/setDesktopBackground.css - skin/classic/aero/browser/share-button.png - skin/classic/aero/browser/share-button-active.png - skin/classic/aero/browser/share-button-shared.png skin/classic/aero/browser/menu-back.png (menu-back-aero.png) skin/classic/aero/browser/menu-forward.png (menu-forward-aero.png) skin/classic/aero/browser/monitor.png diff --git a/browser/themes/winstripe/share-button-active.png b/browser/themes/winstripe/share-button-active.png deleted file mode 100644 index a87501e89b3112b507b9385d43d021e7700fb150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1249 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=up}Cu>lZ&aVv6H2tp{s$DnT4~38IWZLlrVB} zgXwk2PcF?(%`1WFO+n~2!>JdP6mkoIHoK%2WtOF;xE1B+DuBIgm5JLe#yHJ`>P^Az z789I$^?{Dj2SqGWM8kxDsRzV_CtDx~p72xifT_I*n5@6tj!tD@U<~ziaSW-rmGtBP ze|zSY5vl*x%@pQwCK($};0XC%J1P0c_x}b0%Nu{_EXfGF`S~EH$65z5@eBj1X%3tBdDc33uAaCa0p++e%Q;1*Ei!X8w-zWLBYgDV@91Ex2|6!UgOC$QOi zUrRYMYeIuieIutTcL#GL(Cwd@Kbk0rF`c@}l*z7O*L0cHK*8{Dkp3j@ZTn7K`Ro|p zY_7?iyOKSrRH2Uj$jcj|f+uz@5zopr E08!kg%>V!Z diff --git a/browser/themes/winstripe/share-button-shared.png b/browser/themes/winstripe/share-button-shared.png deleted file mode 100644 index cb8a11e81d899117cc02c924525c99182b7b8166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1460 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=miIbtBv7582v6H2tp{s$DnT4~38IWaWXzpg@ z;s(>}lAm0fo0?Yw)0=|O>w;4+C@JI?0Bv?jEy^rQO>ryA&s6|>*(wvaTO4tk2i2Q` z+bvEw_38s1qYsK$q=<$I0aFi%2~V~_4m{zf<^fZC5inV|2bpeWU|`blba4!+xHV<+ z!R#vzBFECzPM#@Sz2kyygn_cH$j1ks+DB)1b*vB#5lHFpstDk3I#DM0GAwq_5B`b} zu4`dBaV{<)+t_Vio^95cT(WkzQ~AZ5$vKlg`rgP{th0?xZt~2^{pR;;Di5|UWx92s zdAH-08^124tX;phy5|44?kDz%xj+AY>Ig25%WNz2TRV~WfFZ|1{k>cH7deC(&o-_u ziS7S>(kg*}TU^&_HdC=13a5n+EK=wa{#vRs`PuTRbCRvUvzzhCT$fzJe7(?GBZBwc zfqhs0v({G!-_~?C;hyCF@SN?9zc0hi9IoLiQo6(+vgz&fYb_kkw!njv{+${~fG=c^i?EdSvw zkuD^>SAO2bin}*ld95_%xR3ZBcU>|=)b&NA8 z=U%lC3Xwb2`?So&-t2o@Tt%?qj^D-)>)vLcjVO0~_w)z%mc8$9iRIq^Ffq~E(u37g z)1y5|IMsbq>i)Oanan>dTzJ0Zp@!_=sK~P885uPzRPDOG6K;gXJ?O5FH9hxN_W%Ra Wia%XpEQh^8<*28tpUXO@geCyiVI1fH diff --git a/browser/themes/winstripe/share-button.png b/browser/themes/winstripe/share-button.png deleted file mode 100644 index 86bd5ec70add448cfa5647e9448d9bb2ea5349a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1245 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=up}Cu>lZ&CNv6H2tp{s$DnT4~38IWZLlrVB} zgXwk2PcF?(%`1WFO+n~2!l@UO6mkoIHoK%2WtOF;xE1B+DuBIgm5I|W&Tcr(gX&Ge z?G^)^di8;h(Fa8=QbfaqfT;(>geO}d2cGa#^MI+n2$-yer@y|;z`z*j>EaktacjzD zd+);mBJB^abSZE+9o(92*RZ;YBhOXC!h@Zay_GA^^@^j5po{L;c;V(L*Q7#@BxyJ8 zFjKIw>}(T$ry(_6^S!2jg}2$V ziN``BF8yb$-eu{NUD5tG>Y(wx)a}2%OO>(Sxc)6M)qcW* z#L`SX;a@x{M{CzPA2k Date: Mon, 27 Aug 2012 08:03:54 -0400 Subject: [PATCH 15/21] Bug 785781 - Remove artifact of the old re engine. r=njn --- js/src/jsreops.tbl | 111 --------------------------------------------- 1 file changed, 111 deletions(-) delete mode 100644 js/src/jsreops.tbl diff --git a/js/src/jsreops.tbl b/js/src/jsreops.tbl deleted file mode 100644 index 5bf8f7169d1..00000000000 --- a/js/src/jsreops.tbl +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=0 ft=C: */ - -/* 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/. */ - -/* Note : contiguity of 'simple opcodes' is important for SimpleMatch() */ - -/* match rest of input against rest of r.e. */ -REOP_DEF(REOP_EMPTY, "empty") -/* beginning of input (or line if multiline) */ -REOP_DEF(REOP_BOL, "bol") -/* end of input (or line if multiline) */ -REOP_DEF(REOP_EOL, "eol") -/* match "" at word boundary */ -REOP_DEF(REOP_WBDRY, "wbdry") -/* match "" at word non-boundary */ -REOP_DEF(REOP_WNONBDRY, "wnonbdry") -/* stands for any character */ -REOP_DEF(REOP_DOT, "dot") -/* match a digit char: [0-9] */ -REOP_DEF(REOP_DIGIT, "digit") -/* match a non-digit char: [^0-9] */ -REOP_DEF(REOP_NONDIGIT, "nondigit") -/* match an alphanumeric char: [0-9a-z_A-Z] */ -REOP_DEF(REOP_ALNUM, "alnum") -/* match a non-alphanumeric char: [^0-9a-z_A-Z] */ -REOP_DEF(REOP_NONALNUM, "nonalnum") -/* match a whitespace char */ -REOP_DEF(REOP_SPACE, "space") -/* match a non-whitespace char */ -REOP_DEF(REOP_NONSPACE, "nonspace") -/* back-reference (e.g., \1) to a parenthetical */ -REOP_DEF(REOP_BACKREF, "backref") -/* match a flat string */ -REOP_DEF(REOP_FLAT, "flat") -/* match a single char */ -REOP_DEF(REOP_FLAT1, "flat1") -/* case-independent REOP_FLAT */ -REOP_DEF(REOP_FLATi, "flati") -/* case-independent REOP_FLAT1 */ -REOP_DEF(REOP_FLAT1i, "flat1i") -/* single Unicode char */ -REOP_DEF(REOP_UCFLAT1, "ucflat1") -/* case-independent REOP_UCFLAT1 */ -REOP_DEF(REOP_UCFLAT1i, "ucflat1i") -/* flat Unicode string; len immediate counts chars */ -REOP_DEF(REOP_UCFLAT, "ucflat") -/* case-independent REOP_UCFLAT */ -REOP_DEF(REOP_UCFLATi, "ucflati") -/* character class with index */ -REOP_DEF(REOP_CLASS, "class") -/* negated character class with index */ -REOP_DEF(REOP_NCLASS, "nclass") - -/* NCLASS is considered to be the last "simple" op-code */ - - -/* alternative subexpressions in kid and next */ -REOP_DEF(REOP_ALT, "alt") -/* quantified atom: atom{1,2} */ -REOP_DEF(REOP_QUANT, "quant") -/* zero or more occurrences of kid */ -REOP_DEF(REOP_STAR, "star") -/* one or more occurrences of kid */ -REOP_DEF(REOP_PLUS, "plus") -/* optional subexpression in kid */ -REOP_DEF(REOP_OPT, "opt") -/* left paren bytecode: kid is u.num'th sub-regexp */ -REOP_DEF(REOP_LPAREN, "lparen") -/* right paren bytecode */ -REOP_DEF(REOP_RPAREN, "rparen") -/* for deoptimized closure loops */ -REOP_DEF(REOP_JUMP, "jump") -/* optimize .* to use a single opcode */ -REOP_DEF(REOP_DOTSTAR, "dotstar") -/* non-capturing version of REOP_LPAREN */ -REOP_DEF(REOP_LPARENNON, "lparennon") -/* zero width positive lookahead assertion */ -REOP_DEF(REOP_ASSERT, "assert") -/* zero width negative lookahead assertion */ -REOP_DEF(REOP_ASSERT_NOT, "assert_not") -/* sentinel at end of assertion child */ -REOP_DEF(REOP_ASSERTTEST, "asserttest") -/* sentinel at end of !assertion child */ -REOP_DEF(REOP_ASSERTNOTTEST, "assertnottest") -/* non-greedy version of * */ -REOP_DEF(REOP_MINIMALSTAR, "minimalstar") -/* non-greedy version of + */ -REOP_DEF(REOP_MINIMALPLUS, "minimalplus") -/* non-greedy version of ? */ -REOP_DEF(REOP_MINIMALOPT, "minimalopt") -/* non-greedy version of {} */ -REOP_DEF(REOP_MINIMALQUANT, "minimalquant") -/* sentinel at end of quantifier child */ -REOP_DEF(REOP_ENDCHILD, "endchild") -/* directs execution of greedy quantifier */ -REOP_DEF(REOP_REPEAT, "repeat") -/* directs execution of non-greedy quantifier */ -REOP_DEF(REOP_MINIMALREPEAT, "minimalrepeat") -/* prerequisite for ALT, either of two chars */ -REOP_DEF(REOP_ALTPREREQ, "altprereq") -/* prerequisite for ALT, a char or a class */ -REOP_DEF(REOP_ALTPREREQ2, "altprereq2") -/* end of final alternate */ -REOP_DEF(REOP_ENDALT, "endalt") -/* concatenation of terms (parse time only) */ -REOP_DEF(REOP_CONCAT, "concat") -/* end of expression */ -REOP_DEF(REOP_END, "end") From d76d19dc3d10ccf1b466c9b23312428629733c8d Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 27 Aug 2012 08:04:37 -0400 Subject: [PATCH 16/21] Bug 781035 - Use the C++ JS compile API in more places. r=jorendorff sr=jst --- content/base/src/nsFrameMessageManager.cpp | 18 ++--- dom/base/nsJSEnvironment.cpp | 67 +++++++++---------- dom/workers/ScriptLoader.cpp | 11 +-- dom/workers/WorkerPrivate.cpp | 17 +++-- .../autoconfig/src/nsJSConfigTriggers.cpp | 8 ++- js/xpconnect/src/XPCComponents.cpp | 13 ++-- 6 files changed, 65 insertions(+), 69 deletions(-) diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index d276920c160..838d39e3c7e 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -827,17 +827,13 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL) mGlobal->GetJSObject(&global); if (global) { JSAutoCompartment ac(mCx, global); - uint32_t oldopts = JS_GetOptions(mCx); - JS_SetOptions(mCx, oldopts | JSOPTION_NO_SCRIPT_RVAL); - - JSScript* script = - JS_CompileUCScriptForPrincipals(mCx, nullptr, - nsJSPrincipals::get(mPrincipal), - static_cast(dataString.get()), - dataString.Length(), - url.get(), 1); - - JS_SetOptions(mCx, oldopts); + JS::CompileOptions options(mCx); + options.setNoScriptRval(true) + .setFileAndLine(url.get(), 1) + .setPrincipals(nsJSPrincipals::get(mPrincipal)); + JS::RootedObject empty(mCx, NULL); + JSScript* script = JS::Compile(mCx, empty, options, + dataString.get(), dataString.Length()); if (script) { nsCAutoString scheme; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index b1cccd4bef0..549f68a119e 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1293,15 +1293,13 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, ++mExecuteDepth; - ok = ::JS_EvaluateUCScriptForPrincipalsVersion(mContext, - aScopeObject, - nsJSPrincipals::get(principal), - static_cast(PromiseFlatString(aScript).get()), - aScript.Length(), - aURL, - aLineNo, - &val, - JSVersion(aVersion)); + JS::CompileOptions options(mContext); + options.setFileAndLine(aURL, aLineNo) + .setVersion(JSVersion(aVersion)) + .setPrincipals(nsJSPrincipals::get(principal)); + JS::RootedObject rootedScope(mContext, aScopeObject); + ok = JS::Evaluate(mContext, rootedScope, options, PromiseFlatString(aScript).get(), + aScript.Length(), &val); --mExecuteDepth; @@ -1490,11 +1488,15 @@ nsJSContext::EvaluateString(const nsAString& aScript, XPCAutoRequest ar(mContext); JSAutoCompartment ac(mContext, aScopeObject); - ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin( - mContext, aScopeObject, - nsJSPrincipals::get(principal), nsJSPrincipals::get(aOriginPrincipal), - static_cast(PromiseFlatString(aScript).get()), - aScript.Length(), aURL, aLineNo, vp, JSVersion(aVersion)); + JS::RootedObject rootedScope(mContext, aScopeObject); + JS::CompileOptions options(mContext); + options.setFileAndLine(aURL, aLineNo) + .setPrincipals(nsJSPrincipals::get(principal)) + .setOriginPrincipals(nsJSPrincipals::get(aOriginPrincipal)) + .setVersion(JSVersion(aVersion)); + ok = JS::Evaluate(mContext, rootedScope, options, + PromiseFlatString(aScript).get(), + aScript.Length(), vp); if (!ok) { // Tell XPConnect about any pending exceptions. This is needed @@ -1751,17 +1753,16 @@ nsJSContext::CompileEventHandler(nsIAtom *aName, #endif // Event handlers are always shared, and must be bound before use. - // Therefore we never bother compiling with principals. - // (that probably means we should avoid JS_CompileUCFunctionForPrincipals!) + // Therefore we don't bother compiling with principals. XPCAutoRequest ar(mContext); - JSFunction* fun = - ::JS_CompileUCFunctionForPrincipalsVersion(mContext, - nullptr, nullptr, - nsAtomCString(aName).get(), aArgCount, aArgNames, - (jschar*)PromiseFlatString(aBody).get(), - aBody.Length(), - aURL, aLineNo, JSVersion(aVersion)); + JS::CompileOptions options(mContext); + options.setVersion(JSVersion(aVersion)) + .setFileAndLine(aURL, aLineNo); + JS::RootedObject empty(mContext, NULL); + JSFunction* fun = JS::CompileFunction(mContext, empty, options, nsAtomCString(aName).get(), + aArgCount, aArgNames, + PromiseFlatString(aBody).get(), aBody.Length()); if (!fun) { ReportPendingException(); @@ -1814,20 +1815,18 @@ nsJSContext::CompileFunction(JSObject* aTarget, } } - JSObject *target = aTarget; + JS::RootedObject target(mContext, aShared ? NULL : aTarget); XPCAutoRequest ar(mContext); - JSFunction* fun = - ::JS_CompileUCFunctionForPrincipalsVersion(mContext, - aShared ? nullptr : target, - nsJSPrincipals::get(principal), - PromiseFlatCString(aName).get(), - aArgCount, aArgArray, - static_cast(PromiseFlatString(aBody).get()), - aBody.Length(), - aURL, aLineNo, - JSVersion(aVersion)); + JS::CompileOptions options(mContext); + options.setPrincipals(nsJSPrincipals::get(principal)) + .setVersion(JSVersion(aVersion)) + .setFileAndLine(aURL, aLineNo); + JSFunction* fun = JS::CompileFunction(mContext, target, + options, PromiseFlatCString(aName).get(), + aArgCount, aArgArray, + PromiseFlatString(aBody).get(), aBody.Length()); if (!fun) return NS_ERROR_FAILURE; diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 99ee306310f..3e5356843ad 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -576,7 +576,7 @@ ScriptExecutorRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) } } - JSObject* global = JS_GetGlobalObject(aCx); + JS::RootedObject global(aCx, JS_GetGlobalObject(aCx)); NS_ASSERTION(global, "Must have a global by now!"); JSPrincipals* principal = GetWorkerPrincipal(); @@ -615,10 +615,11 @@ ScriptExecutorRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) NS_ConvertUTF16toUTF8 filename(loadInfo.mURL); - if (!JS_EvaluateUCScriptForPrincipals(aCx, global, principal, - loadInfo.mScriptText.get(), - loadInfo.mScriptText.Length(), - filename.get(), 1, nullptr)) { + JS::CompileOptions options(aCx); + options.setPrincipals(principal) + .setFileAndLine(filename.get(), 1); + if (!JS::Evaluate(aCx, global, options, loadInfo.mScriptText.get(), + loadInfo.mScriptText.Length(), nullptr)) { return true; } diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 5969e633935..9558c503447 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3760,7 +3760,7 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) bool retval = true; AutoPtrComparator comparator = GetAutoPtrComparator(mTimeouts); - JSObject* global = JS_GetGlobalObject(aCx); + JS::RootedObject global(aCx, JS_GetGlobalObject(aCx)); JSPrincipals* principal = GetWorkerPrincipal(); // We want to make sure to run *something*, even if the timer fired a little @@ -3794,18 +3794,17 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) if (info->mTimeoutVal.isString()) { JSString* expression = info->mTimeoutVal.toString(); + JS::CompileOptions options(aCx); + options.setPrincipals(principal) + .setFileAndLine(info->mFilename.get(), info->mLineNumber); + size_t stringLength; const jschar* string = JS_GetStringCharsAndLength(aCx, expression, &stringLength); - - if ((!string || - !JS_EvaluateUCScriptForPrincipals(aCx, global, principal, string, - stringLength, - info->mFilename.get(), - info->mLineNumber, nullptr)) && + if ((!string || !JS::Evaluate(aCx, global, options, string, stringLength, nullptr)) && !JS_ReportPendingException(aCx)) { - retval = false; - break; + retval = false; + break; } } else { diff --git a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp index b37b8126ffb..98a7a1750e2 100644 --- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp +++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp @@ -195,9 +195,11 @@ nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length, JS_BeginRequest(autoconfig_cx); nsCOMPtr principal; nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(principal)); - ok = JS_EvaluateScriptForPrincipals(autoconfig_cx, autoconfig_glob, - nsJSPrincipals::get(principal), - js_buffer, length, filename, 0, nullptr); + JS::CompileOptions options(autoconfig_cx); + options.setPrincipals(nsJSPrincipals::get(principal)) + .setFileAndLine(filename, 1); + JS::RootedObject glob(autoconfig_cx, autoconfig_glob); + ok = JS::Evaluate(autoconfig_cx, glob, options, js_buffer, length, nullptr); JS_EndRequest(autoconfig_cx); JS_MaybeGC(autoconfig_cx); diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index d7cf0295926..3a142543173 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3915,13 +3915,12 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, jsval v; JSString *str = nullptr; - JSBool ok = - JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox, - nsJSPrincipals::get(prin), - reinterpret_cast - (PromiseFlatString(source).get()), - source.Length(), filename, lineNo, - &v); + JS::CompileOptions options(sandcx->GetJSContext()); + options.setPrincipals(nsJSPrincipals::get(prin)) + .setFileAndLine(filename, lineNo); + JS::RootedObject rootedSandbox(sandcx->GetJSContext(), sandbox); + bool ok = JS::Evaluate(sandcx->GetJSContext(), rootedSandbox, options, + PromiseFlatString(source).get(), source.Length(), &v); if (ok && returnStringOnly && !(JSVAL_IS_VOID(v))) { ok = !!(str = JS_ValueToString(sandcx->GetJSContext(), v)); } From fce6b1df9623869fef4bb240b95b2ff6ac9b9108 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 27 Aug 2012 08:21:27 -0400 Subject: [PATCH 17/21] Bug 781035 followup - fix indentation. r=me --- dom/workers/WorkerPrivate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 9558c503447..7a99493b8ba 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3803,8 +3803,8 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) &stringLength); if ((!string || !JS::Evaluate(aCx, global, options, string, stringLength, nullptr)) && !JS_ReportPendingException(aCx)) { - retval = false; - break; + retval = false; + break; } } else { From 9a223560e134faac45ebc78ed6eed47f156243db Mon Sep 17 00:00:00 2001 From: Gabor Krizsanits Date: Mon, 27 Aug 2012 15:06:34 +0200 Subject: [PATCH 18/21] Bug 738244 - Supporting DOM specific collection properties through xray wrappers; r=mrbkap --- dom/base/nsDOMClassInfo.cpp | 50 ++--- dom/base/nsDOMClassInfo.h | 5 + js/xpconnect/tests/chrome/Makefile.in | 1 + js/xpconnect/tests/chrome/test_bug738244.xul | 50 +++++ js/xpconnect/tests/mochitest/Makefile.in | 1 + .../tests/mochitest/file_bug738244.html | 10 + js/xpconnect/wrappers/WrapperFactory.cpp | 8 + js/xpconnect/wrappers/WrapperFactory.h | 3 + js/xpconnect/wrappers/XrayWrapper.cpp | 206 +++++++++++++----- js/xpconnect/wrappers/XrayWrapper.h | 27 +++ 10 files changed, 276 insertions(+), 85 deletions(-) create mode 100644 js/xpconnect/tests/chrome/test_bug738244.xul create mode 100644 js/xpconnect/tests/mochitest/file_bug738244.html diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 3d53da5fda5..5199a9bf036 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -7197,7 +7197,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // method on an interface that would let us just call into the // window code directly... - if (!ObjectIsNativeWrapper(cx, obj)) { + if (!ObjectIsNativeWrapper(cx, obj) || + xpc::WrapperFactory::XrayWrapperNotShadowing(obj, id)) { nsCOMPtr dsn(do_QueryInterface(win->GetDocShell())); int32_t count = 0; @@ -9221,7 +9222,8 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSAutoRequest ar(cx); - if (!ObjectIsNativeWrapper(cx, obj)) { + if (!ObjectIsNativeWrapper(cx, obj) || + xpc::WrapperFactory::XrayWrapperNotShadowing(obj, id)) { nsCOMPtr result; nsWrapperCache *cache; nsresult rv = ResolveImpl(cx, wrapper, id, getter_AddRefs(result), @@ -9313,23 +9315,20 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsid id, jsval *vp, bool *_retval) { - // For native wrappers, do not get random names on document - if (!ObjectIsNativeWrapper(cx, obj)) { - nsCOMPtr result; + nsCOMPtr result; - JSAutoRequest ar(cx); + JSAutoRequest ar(cx); - nsWrapperCache *cache; - nsresult rv = ResolveImpl(cx, wrapper, id, getter_AddRefs(result), &cache); - NS_ENSURE_SUCCESS(rv, rv); + nsWrapperCache *cache; + nsresult rv = ResolveImpl(cx, wrapper, id, getter_AddRefs(result), &cache); + NS_ENSURE_SUCCESS(rv, rv); - if (result) { - rv = WrapNative(cx, obj, result, cache, true, vp); - if (NS_SUCCEEDED(rv)) { - rv = NS_SUCCESS_I_DID_SOMETHING; - } - return rv; + if (result) { + rv = WrapNative(cx, obj, result, cache, true, vp); + if (NS_SUCCEEDED(rv)) { + rv = NS_SUCCESS_I_DID_SOMETHING; } + return rv; } return NS_OK; @@ -9371,7 +9370,8 @@ nsHTMLFormElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper, { // For native wrappers, do not resolve random names on form if ((!(JSRESOLVE_ASSIGNING & flags)) && JSID_IS_STRING(id) && - !ObjectIsNativeWrapper(cx, obj)) { + (!ObjectIsNativeWrapper(cx, obj) || + xpc::WrapperFactory::XrayWrapperNotShadowing(obj, id))) { nsCOMPtr form(do_QueryWrappedNative(wrapper, obj)); nsCOMPtr result; nsWrapperCache *cache; @@ -9402,18 +9402,16 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, if (JSID_IS_STRING(id)) { // For native wrappers, do not get random names on form - if (!ObjectIsNativeWrapper(cx, obj)) { - nsCOMPtr result; - nsWrapperCache *cache; + nsCOMPtr result; + nsWrapperCache *cache; - FindNamedItem(form, id, getter_AddRefs(result), &cache); + FindNamedItem(form, id, getter_AddRefs(result), &cache); - if (result) { - // Wrap result, result can be either an element or a list of - // elements - nsresult rv = WrapNative(cx, obj, result, cache, true, vp); - return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; - } + if (result) { + // Wrap result, result can be either an element or a list of + // elements + nsresult rv = WrapNative(cx, obj, result, cache, true, vp); + return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } } else { int32_t n = GetArrayIndexFromId(cx, id); diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index eda41a24104..5db97878487 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -132,6 +132,11 @@ public: * dealing with document.domain, it's possible to end up in a scriptable * helper with a wrapper, even though we should be treating the lookup as a * transparent one. + * + * Note: So ObjectIsNativeWrapper(cx, obj) check usually means "through xray + * wrapper this part is not visible" while combined with + * || xpc::WrapperFactory::XrayWrapperNotShadowing(obj) it means "through + * xray wrapper it is visible only if it does not hide any native property." */ static bool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj); diff --git a/js/xpconnect/tests/chrome/Makefile.in b/js/xpconnect/tests/chrome/Makefile.in index 58ddb32bd89..17eb76441e4 100644 --- a/js/xpconnect/tests/chrome/Makefile.in +++ b/js/xpconnect/tests/chrome/Makefile.in @@ -32,6 +32,7 @@ MOCHITEST_CHROME_FILES = \ test_bug679861.xul \ test_bug706301.xul \ test_bug726949.xul \ + test_bug738244.xul \ test_bug743843.xul \ test_bug760076.xul \ test_bug760109.xul \ diff --git a/js/xpconnect/tests/chrome/test_bug738244.xul b/js/xpconnect/tests/chrome/test_bug738244.xul new file mode 100644 index 00000000000..0835ad75bee --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug738244.xul @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + diff --git a/js/xpconnect/tests/mochitest/Makefile.in b/js/xpconnect/tests/mochitest/Makefile.in index 358c9e45836..74ef1269563 100644 --- a/js/xpconnect/tests/mochitest/Makefile.in +++ b/js/xpconnect/tests/mochitest/Makefile.in @@ -72,6 +72,7 @@ MOCHITEST_FILES = bug500931_helper.html \ file_empty.html \ file_documentdomain.html \ test_lookupMethod.html \ + file_bug738244.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/js/xpconnect/tests/mochitest/file_bug738244.html b/js/xpconnect/tests/mochitest/file_bug738244.html new file mode 100644 index 00000000000..a399d9f0e0f --- /dev/null +++ b/js/xpconnect/tests/mochitest/file_bug738244.html @@ -0,0 +1,10 @@ + + +
+ + +
+ + + diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp index a4868576737..ff24ea69c5c 100644 --- a/js/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/xpconnect/wrappers/WrapperFactory.cpp @@ -625,6 +625,14 @@ WrapperFactory::WrapForSameCompartmentXray(JSContext *cx, JSObject *obj) return wrapperObj; } + +bool +WrapperFactory::XrayWrapperNotShadowing(JSObject *wrapper, jsid id) +{ + ResolvingId *rid = ResolvingId::getResolvingIdFromWrapper(wrapper); + return rid->isXrayShadowing(id); +} + /* * Calls to JS_TransplantObject* should go through these helpers here so that * waivers get fixed up properly. diff --git a/js/xpconnect/wrappers/WrapperFactory.h b/js/xpconnect/wrappers/WrapperFactory.h index b93c6d829fe..588a2582bf3 100644 --- a/js/xpconnect/wrappers/WrapperFactory.h +++ b/js/xpconnect/wrappers/WrapperFactory.h @@ -93,6 +93,9 @@ class WrapperFactory { // Wrap a same-compartment object for Xray inspection. static JSObject *WrapForSameCompartmentXray(JSContext *cx, JSObject *obj); + + // Returns true if the wrapper is in not shadowing mode for the id. + static bool XrayWrapperNotShadowing(JSObject *wrapper, jsid id); }; extern js::DirectWrapper XrayWaiver; diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index d55f58e0374..4db3d84b764 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -279,6 +279,68 @@ createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent) using namespace XrayUtils; +ResolvingId::ResolvingId(JSObject *wrapper, jsid id) + : mId(id), + mHolder(getHolderObject(wrapper)), + mPrev(getResolvingId(mHolder)), + mXrayShadowing(false) +{ + js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, js::PrivateValue(this)); +} + +ResolvingId::~ResolvingId() +{ + MOZ_ASSERT(getResolvingId(mHolder) == this, "unbalanced ResolvingIds"); + js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, js::PrivateValue(mPrev)); +} + +bool +ResolvingId::isXrayShadowing(jsid id) +{ + if (!mXrayShadowing) + return false; + + return mId == id; +} + +bool +ResolvingId::isResolving(jsid id) +{ + for (ResolvingId *cur = this; cur; cur = cur->mPrev) { + if (cur->mId == id) + return true; + } + + return false; +} + +ResolvingId * +ResolvingId::getResolvingId(JSObject *holder) +{ + MOZ_ASSERT(strcmp(JS_GetClass(holder)->name, "NativePropertyHolder") == 0); + return (ResolvingId *)js::GetReservedSlot(holder, JSSLOT_RESOLVING).toPrivate(); +} + +JSObject * +ResolvingId::getHolderObject(JSObject *wrapper) +{ + return &js::GetProxyExtra(wrapper, 0).toObject(); +} + +ResolvingId * +ResolvingId::getResolvingIdFromWrapper(JSObject *wrapper) +{ + return getResolvingId(getHolderObject(wrapper)); +} + +class ResolvingIdDummy +{ +public: + ResolvingIdDummy(JSObject *wrapper, jsid id) + { + } +}; + class XPCWrappedNativeXrayTraits { public: @@ -298,30 +360,18 @@ public: } static JSObject* getInnerObject(JSObject *wrapper); - class ResolvingId - { - public: - ResolvingId(JSObject *holder, jsid id); - ~ResolvingId(); - - private: - friend class XPCWrappedNativeXrayTraits; - - jsid mId; - JSObject *mHolder; - ResolvingId *mPrev; - }; static bool isResolving(JSContext *cx, JSObject *holder, jsid id); + static bool resolveDOMCollectionProperty(JSContext *cx, JSObject *wrapper, JSObject *holder, + jsid id, bool set, PropertyDescriptor *desc); + + typedef ResolvingId ResolvingIdImpl; + private: static JSObject* getHolderObject(JSObject *wrapper) { return &js::GetProxyExtra(wrapper, 0).toObject(); } - static ResolvingId* getResolvingId(JSObject *holder) - { - return (ResolvingId *)js::GetReservedSlot(holder, JSSLOT_RESOLVING).toPrivate(); - } }; class ProxyXrayTraits @@ -346,18 +396,13 @@ public: return &js::GetProxyPrivate(wrapper).toObject(); } - class ResolvingId - { - public: - ResolvingId(JSObject *holder, jsid id) - { - } - }; static bool isResolving(JSContext *cx, JSObject *holder, jsid id) { - return false; + return false; } + typedef ResolvingIdDummy ResolvingIdImpl; + private: static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper, bool createHolder) @@ -395,18 +440,13 @@ public: return &js::GetProxyPrivate(wrapper).toObject(); } - class ResolvingId - { - public: - ResolvingId(JSObject *holder, jsid id) - { - } - }; static bool isResolving(JSContext *cx, JSObject *holder, jsid id) { - return false; + return false; } + typedef ResolvingIdDummy ResolvingIdImpl; + private: static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper, bool createHolder) @@ -472,30 +512,11 @@ XPCWrappedNativeXrayTraits::getInnerObject(JSObject *wrapper) return GetWrappedNativeObjectFromHolder(getHolderObject(wrapper)); } -XPCWrappedNativeXrayTraits::ResolvingId::ResolvingId(JSObject *wrapper, jsid id) - : mId(id), - mHolder(getHolderObject(wrapper)), - mPrev(getResolvingId(mHolder)) -{ - js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, PrivateValue(this)); -} - -XPCWrappedNativeXrayTraits::ResolvingId::~ResolvingId() -{ - NS_ASSERTION(getResolvingId(mHolder) == this, "unbalanced ResolvingIds"); - js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, PrivateValue(mPrev)); -} - bool XPCWrappedNativeXrayTraits::isResolving(JSContext *cx, JSObject *holder, jsid id) { - for (ResolvingId *cur = getResolvingId(holder); cur; cur = cur->mPrev) { - if (cur->mId == id) - return true; - } - - return false; + return ResolvingId::getResolvingId(holder)->isResolving(id); } // Some DOM objects have shared properties that don't have an explicit @@ -548,6 +569,71 @@ holder_set(JSContext *cx, JSHandleObject wrapper_, JSHandleId id, JSBool strict, return true; } +class AutoSetWrapperNotShadowing +{ +public: + AutoSetWrapperNotShadowing(JSObject *wrapper MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + MOZ_ASSERT(wrapper); + mResolvingId = ResolvingId::getResolvingIdFromWrapper(wrapper); + MOZ_ASSERT(mResolvingId); + mResolvingId->mXrayShadowing = true; + } + + ~AutoSetWrapperNotShadowing() + { + mResolvingId->mXrayShadowing = false; + } + +private: + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + ResolvingId *mResolvingId; +}; + +// This is called after the resolveNativeProperty could not find any property +// with the given id. At this point we can check for DOM specific collections +// like document["formName"] because we already know that it is not shadowing +// any native property. +bool +XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, JSObject *wrapper, + JSObject *holder, jsid id, bool set, + PropertyDescriptor *desc) +{ + // If we are not currently resolving this id and resolveNative is called + // we don't do anything. (see defineProperty in case of shadowing is forbidden). + ResolvingId *rid = ResolvingId::getResolvingId(holder); + if (!rid || rid->mId != id) + return true; + + XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); + if (!NATIVE_HAS_FLAG(wn, WantNewResolve)) + return true; + + // Setting the current ResolvingId in non-shadowing mode. So for this id + // Xray won't ignore DOM specific collection properties temporarily. + AutoSetWrapperNotShadowing asw(wrapper); + + bool retval = true; + JSObject *pobj = NULL; + unsigned flags = (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED; + nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id, + flags, &pobj, &retval); + if (NS_FAILED(rv)) { + if (retval) + XPCThrower::Throw(rv, cx); + return false; + } + + if (pobj && !JS_GetPropertyDescriptorById(cx, holder, id, + JSRESOLVE_QUALIFIED, desc)) + { + return false; + } + + return true; +} + bool XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapper, JSObject *holder, jsid id, bool set, @@ -562,11 +648,13 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapp // This will do verification and the method lookup for us. XPCCallContext ccx(JS_CALLER, cx, wnObject, nullptr, id); - // There are no native numeric properties, so we can shortcut here. We will not - // find the property. + // There are no native numeric properties, so we can shortcut here. We will + // not find the property. However we want to support non shadowing dom + // specific collection properties like window.frames, so we still have to + // check for those. if (!JSID_IS_STRING(id)) { /* Not found */ - return true; + return resolveDOMCollectionProperty(cx, wrapper, holder, id, set, desc); } XPCNativeInterface *iface; @@ -576,7 +664,7 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapp !(iface = ccx.GetInterface()) || !(member = ccx.GetMember())) { /* Not found */ - return true; + return resolveDOMCollectionProperty(cx, wrapper, holder, id, set, desc); } desc->obj = holder; @@ -1235,7 +1323,7 @@ XrayWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrappe if (!this->enter(cx, wrapper, id, action, &status)) return status; - typename Traits::ResolvingId resolving(wrapper, id); + typename Traits::ResolvingIdImpl resolving(wrapper, id); // Redirect access straight to the wrapper if we should be transparent. if (XrayUtils::IsTransparent(cx, wrapper)) { @@ -1334,7 +1422,7 @@ XrayWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wra if (!this->enter(cx, wrapper, id, action, &status)) return status; - typename Traits::ResolvingId resolving(wrapper, id); + typename Traits::ResolvingIdImpl resolving(wrapper, id); // NB: Nothing we do here acts on the wrapped native itself, so we don't // enter our policy. diff --git a/js/xpconnect/wrappers/XrayWrapper.h b/js/xpconnect/wrappers/XrayWrapper.h index 5ebb4f435ce..0ce938cf356 100644 --- a/js/xpconnect/wrappers/XrayWrapper.h +++ b/js/xpconnect/wrappers/XrayWrapper.h @@ -7,6 +7,7 @@ #include "jsapi.h" #include "jswrapper.h" +#include "mozilla/GuardObjects.h" // Xray wrappers re-resolve the original native properties on the native // object and always directly access to those properties. @@ -100,4 +101,30 @@ public: }; extern SandboxProxyHandler sandboxProxyHandler; + +class AutoSetWrapperNotShadowing; +class XPCWrappedNativeXrayTraits; + +class ResolvingId { +public: + ResolvingId(JSObject *wrapper, jsid id); + ~ResolvingId(); + + bool isXrayShadowing(jsid id); + bool isResolving(jsid id); + static ResolvingId* getResolvingId(JSObject *holder); + static JSObject* getHolderObject(JSObject *wrapper); + static ResolvingId *getResolvingIdFromWrapper(JSObject *wrapper); + +private: + friend class AutoSetWrapperNotShadowing; + friend class XPCWrappedNativeXrayTraits; + + jsid mId; + JSObject *mHolder; + ResolvingId *mPrev; + bool mXrayShadowing; +}; + } + From 5138045efff1fdd395400254128a11a4e6597729 Mon Sep 17 00:00:00 2001 From: Gabor Krizsanits Date: Mon, 27 Aug 2012 15:15:20 +0200 Subject: [PATCH 19/21] Bug 763897 - Incorrect behaviour of mozMatchesSelector.call through xray; r=bholley --- js/xpconnect/src/XPCJSRuntime.cpp | 3 +- js/xpconnect/src/xpcprivate.h | 1 + js/xpconnect/tests/chrome/Makefile.in | 1 + .../tests/chrome/test_mozMatchesSelector.xul | 50 +++++++++ js/xpconnect/tests/mochitest/Makefile.in | 1 + .../mochitest/file_mozMatchesSelector.html | 1 + js/xpconnect/wrappers/XrayWrapper.cpp | 103 +++++++++++++++--- 7 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 js/xpconnect/tests/chrome/test_mozMatchesSelector.xul create mode 100644 js/xpconnect/tests/mochitest/file_mozMatchesSelector.html diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 51fe90c57c8..9da53e78597 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -65,7 +65,8 @@ const char* XPCJSRuntime::mStrings[] = { "__scriptOnly__", // IDX_SCRIPTONLY "baseURIObject", // IDX_BASEURIOBJECT "nodePrincipal", // IDX_NODEPRINCIPAL - "documentURIObject" // IDX_DOCUMENTURIOBJECT + "documentURIObject", // IDX_DOCUMENTURIOBJECT + "mozMatchesSelector" // IDX_MOZMATCHESSELECTOR }; /***************************************************************************/ diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index e0091373fdb..50c6ab441b5 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -730,6 +730,7 @@ public: IDX_BASEURIOBJECT , IDX_NODEPRINCIPAL , IDX_DOCUMENTURIOBJECT , + IDX_MOZMATCHESSELECTOR , IDX_TOTAL_COUNT // just a count of the above }; diff --git a/js/xpconnect/tests/chrome/Makefile.in b/js/xpconnect/tests/chrome/Makefile.in index 17eb76441e4..76ce9cf5d91 100644 --- a/js/xpconnect/tests/chrome/Makefile.in +++ b/js/xpconnect/tests/chrome/Makefile.in @@ -52,6 +52,7 @@ MOCHITEST_CHROME_FILES = \ test_expandosharing.xul \ file_expandosharing.jsm \ test_getweakmapkeys.xul \ + test_mozMatchesSelector.xul \ test_nodelists.xul \ test_precisegc.xul \ test_sandboxImport.xul \ diff --git a/js/xpconnect/tests/chrome/test_mozMatchesSelector.xul b/js/xpconnect/tests/chrome/test_mozMatchesSelector.xul new file mode 100644 index 00000000000..3c38456588e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_mozMatchesSelector.xul @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + diff --git a/js/xpconnect/tests/mochitest/Makefile.in b/js/xpconnect/tests/mochitest/Makefile.in index 74ef1269563..fc1e1c897f3 100644 --- a/js/xpconnect/tests/mochitest/Makefile.in +++ b/js/xpconnect/tests/mochitest/Makefile.in @@ -73,6 +73,7 @@ MOCHITEST_FILES = bug500931_helper.html \ file_documentdomain.html \ test_lookupMethod.html \ file_bug738244.html \ + file_mozMatchesSelector.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html b/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html new file mode 100644 index 00000000000..0dc101b5335 --- /dev/null +++ b/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html @@ -0,0 +1 @@ + diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 4db3d84b764..47185cca48a 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -18,6 +18,7 @@ #include "xpcprivate.h" #include "jsapi.h" +#include "nsJSUtils.h" #include "mozilla/dom/BindingUtils.h" @@ -634,14 +635,96 @@ XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, JSObject return true; } +template +static bool +Is(JSObject *wrapper) +{ + JSObject *holder = GetHolder(wrapper); + XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); + nsCOMPtr native = do_QueryWrappedNative(wn); + return !!native; +} + +// Helper function to work around some limitations of the current XPC +// calling mechanism. See: bug 763897. +// The idea is that we unwrap the 'this' object, and find the wrapped +// native that belongs to it. Then we simply make the call directly +// on it after a Query Interface. +static JSBool +mozMatchesSelectorStub(JSContext *cx, unsigned argc, jsval *vp) +{ + if (argc < 1) + JS_ReportError(cx, "Not enough arguments"); + + JSObject *wrapper = JS_THIS_OBJECT(cx, vp); + JSString *selector = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]); + nsDependentJSString selectorStr; + NS_ENSURE_TRUE(selectorStr.init(cx, selector), false); + + nsCOMPtr element; + if (IsWrapper(wrapper) && WrapperFactory::IsXrayWrapper(wrapper)) { + // If it's xray wrapped we can get the wn directly. + JSObject *holder = GetHolder(wrapper); + XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); + element = do_QueryWrappedNative(wn); + } else { + // Else we can use the XPC utility function for unwrapping it. + nsCOMPtr iwn; + nsIXPConnect *xpc = nsXPConnect::GetXPConnect(); + nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, wrapper, + getter_AddRefs(iwn)); + if (NS_FAILED(rv) || !iwn) { + JS_ReportError(cx, "Unexpected object"); + return false; + } + element = do_QueryWrappedNative(iwn); + } + + if (!element) { + JS_ReportError(cx, "Unexpected object"); + return false; + } + + bool ret; + nsresult rv = element->MozMatchesSelector(selectorStr, &ret); + if (NS_FAILED(rv)) { + XPCThrower::Throw(rv, cx); + return false; + } + + JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret)); + return true; +} + bool XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapper, JSObject *holder, jsid id, bool set, JSPropertyDescriptor *desc) { + MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass); + XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); + if (!set && + id == rt->GetStringID(XPCJSRuntime::IDX_MOZMATCHESSELECTOR) && + Is(wrapper)) + { + // XPC calling mechanism cannot handle call/bind properly in some cases + // especially through xray wrappers. This is a temoorary work around for + // this problem for mozMatchesSelector. See: bug 763897. + desc->obj = wrapper; + desc->attrs = JSPROP_ENUMERATE; + JSFunction *fun = JS_NewFunction(cx, mozMatchesSelectorStub, + 1, 0, JS_GetPrototype(wrapper), + "mozMatchesSelector"); + NS_ENSURE_TRUE(fun, false); + desc->value = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)); + desc->getter = NULL; + desc->setter = NULL; + desc->shortid = 0; + return true; + } + desc->obj = NULL; - MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass); JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder); XPCWrappedNative *wn = GetWrappedNative(wnObject); @@ -735,16 +818,6 @@ wrappedJSObject_getter(JSContext *cx, JSHandleObject wrapper, JSHandleId id, JSM return WrapperFactory::WaiveXrayAndWrap(cx, vp.address()); } -template -static bool -Is(JSObject *wrapper) -{ - JSObject *holder = GetHolder(wrapper); - XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); - nsCOMPtr native = do_QueryWrappedNative(wn); - return !!native; -} - static JSBool WrapURI(JSContext *cx, nsIURI *uri, jsval *vp) { @@ -933,13 +1006,9 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, js::Wrapper &jsWra return false; } - if (!pobj) { - return true; - } - #ifdef DEBUG - NS_ASSERTION(JS_HasPropertyById(cx, holder, id, &hasProp) && - hasProp, "id got defined somewhere else?"); + NS_ASSERTION(!pobj || (JS_HasPropertyById(cx, holder, id, &hasProp) && + hasProp), "id got defined somewhere else?"); #endif } From f47e2a99378429f74edb75c1386402e0ff466034 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Mon, 27 Aug 2012 11:13:02 -0300 Subject: [PATCH 20/21] Bug 776825 - Separate message managers into senders and broadcasters. r=smaug --HG-- rename : content/base/public/nsIFrameMessageManager.idl => content/base/public/nsIMessageManager.idl --- b2g/chrome/content/shell.js | 2 +- b2g/components/ContentHandler.js | 3 +- b2g/components/MozKeyboard.js | 8 +- browser/base/content/browser.js | 2 +- content/base/public/Makefile.in | 2 +- content/base/public/nsIFrameLoader.idl | 6 +- .../base/public/nsIFrameMessageManager.idl | 120 ------- content/base/public/nsIMessageManager.idl | 330 ++++++++++++++++++ content/base/src/messageWakeupService.js | 4 +- content/base/src/nsCCUncollectableMarker.cpp | 16 +- content/base/src/nsFrameLoader.cpp | 8 +- content/base/src/nsFrameMessageManager.cpp | 182 ++++++---- content/base/src/nsFrameMessageManager.h | 47 ++- .../base/src/nsInProcessTabChildGlobal.cpp | 5 +- content/base/src/nsInProcessTabChildGlobal.h | 3 +- content/base/test/chrome/file_bug549682.xul | 11 +- content/base/test/chrome/file_bug616841.xul | 4 +- docshell/base/nsDocShell.cpp | 1 - dom/activities/src/ActivitiesService.jsm | 19 +- dom/activities/src/ActivityProxy.js | 8 +- dom/activities/src/ActivityRequestHandler.js | 8 +- dom/alarm/AlarmService.jsm | 8 +- dom/apps/src/AppsService.js | 3 +- dom/apps/src/Webapps.js | 6 +- dom/apps/src/Webapps.jsm | 35 +- dom/base/DOMRequestHelper.jsm | 6 +- dom/base/nsDOMClassInfo.cpp | 30 +- dom/base/nsDOMClassInfoClasses.h | 2 + dom/base/nsGlobalWindow.cpp | 11 +- dom/base/nsGlobalWindow.h | 2 +- dom/contacts/ContactManager.js | 6 +- dom/contacts/fallback/ContactService.jsm | 8 +- dom/devicestorage/ipc/test_ipc.html | 2 +- dom/identity/DOMIdentity.jsm | 4 +- dom/identity/nsDOMIdentity.js | 4 +- dom/indexedDB/ipc/test_ipc.html | 2 +- dom/interfaces/base/nsIDOMChromeWindow.idl | 6 +- dom/ipc/TabChild.cpp | 5 +- dom/ipc/TabChild.h | 3 +- dom/ipc/test.xul | 25 +- dom/ipc/tests/process_error.xul | 7 +- dom/messages/SystemMessageInternal.js | 12 +- dom/messages/SystemMessageManager.js | 8 +- dom/permission/PermissionPromptHelper.jsm | 8 +- dom/settings/SettingsChangeNotifier.jsm | 8 +- dom/settings/SettingsManager.js | 6 +- dom/system/gonk/RILContentHelper.js | 7 +- dom/system/gonk/RadioInterfaceLayer.js | 41 ++- .../mochitest/general/test_interfaces.html | 3 - dom/wifi/WifiWorker.js | 5 +- .../cookie/test/unit_ipc/test_parent.js | 4 +- layout/base/nsPresContext.cpp | 2 +- layout/build/nsLayoutModule.cpp | 12 +- layout/ipc/test-ipcbrowser-chrome.js | 24 +- layout/tools/reftest/reftest.js | 2 +- mobile/xul/chrome/content/CapturePickerUI.js | 3 +- mobile/xul/chrome/content/WebappsUI.js | 23 +- .../xul/chrome/content/bindings/browser.xml | 4 +- mobile/xul/components/LoginManager.js | 2 +- netwerk/protocol/app/AppProtocolHandler.js | 8 +- testing/marionette/marionette-actors.js | 14 +- .../components/SpecialPowersObserver.js | 4 +- .../contentprefs/nsContentPrefService.js | 2 +- .../unit_ipc/test_contentPrefs_parentipc.js | 4 +- toolkit/components/satchel/nsFormHistory.js | 4 +- .../extensions/ChromeManifestParser.jsm | 4 +- toolkit/mozapps/extensions/XPIProvider.jsm | 4 +- toolkit/mozapps/extensions/addonManager.js | 2 +- 68 files changed, 748 insertions(+), 436 deletions(-) delete mode 100644 content/base/public/nsIFrameMessageManager.idl create mode 100644 content/base/public/nsIMessageManager.idl diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index eba9b308657..d805dfa328a 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -49,7 +49,7 @@ XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() { XPCOMUtils.defineLazyGetter(this, "ppmm", function() { return Cc["@mozilla.org/parentprocessmessagemanager;1"] - .getService(Ci.nsIFrameMessageManager); + .getService(Ci.nsIMessageListenerManager); }); function getContentWindow() { diff --git a/b2g/components/ContentHandler.js b/b2g/components/ContentHandler.js index e77bd37d42c..5cebd232965 100644 --- a/b2g/components/ContentHandler.js +++ b/b2g/components/ContentHandler.js @@ -14,7 +14,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyGetter(this, "cpmm", function() { - return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); + return Cc["@mozilla.org/childprocessmessagemanager;1"] + .getService(Ci.nsIMessageSender); }); function log(aMsg) { diff --git a/b2g/components/MozKeyboard.js b/b2g/components/MozKeyboard.js index 4f6d0754e73..8242847cd9c 100644 --- a/b2g/components/MozKeyboard.js +++ b/b2g/components/MozKeyboard.js @@ -14,7 +14,7 @@ Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/ObjectWrapper.jsm"); const messageManager = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIChromeFrameMessageManager); + .getService(Ci.nsIMessageBroadcaster); // ----------------------------------------------------------------------- @@ -70,19 +70,19 @@ MozKeyboard.prototype = { }, setSelectedOption: function mozKeyboardSetSelectedOption(index) { - messageManager.sendAsyncMessage("Forms:Select:Choice", { + messageManager.broadcastAsyncMessage("Forms:Select:Choice", { "index": index }); }, setValue: function mozKeyboardSetValue(value) { - messageManager.sendAsyncMessage("Forms:Input:Value", { + messageManager.broadcastAsyncMessage("Forms:Input:Value", { "value": value }); }, setSelectedOptions: function mozKeyboardSetSelectedOptions(indexes) { - messageManager.sendAsyncMessage("Forms:Select:Choice", { + messageManager.broadcastAsyncMessage("Forms:Select:Choice", { "indexes": indexes || [] }); }, diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 792057002f2..48a028a9a31 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -360,7 +360,7 @@ const gSessionHistoryObserver = { fwdCommand.setAttribute("disabled", "true"); // Hide session restore button on about:home - window.messageManager.sendAsyncMessage("Browser:HideSessionRestoreButton"); + window.messageManager.broadcastAsyncMessage("Browser:HideSessionRestoreButton"); if (gURLBar) { // Clear undo history of the URL bar diff --git a/content/base/public/Makefile.in b/content/base/public/Makefile.in index 40cdda670f3..3ea938ab3e2 100644 --- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -81,7 +81,7 @@ XPIDLSRCS = \ nsIFrameLoader.idl \ nsIXMLHttpRequest.idl \ nsIContentSecurityPolicy.idl \ - nsIFrameMessageManager.idl \ + nsIMessageManager.idl \ nsIWebSocket.idl \ nsIEventSource.idl \ $(NULL) diff --git a/content/base/public/nsIFrameLoader.idl b/content/base/public/nsIFrameLoader.idl index b9341a24de6..bf1e364e380 100644 --- a/content/base/public/nsIFrameLoader.idl +++ b/content/base/public/nsIFrameLoader.idl @@ -8,7 +8,7 @@ interface nsIDocShell; interface nsIURI; interface nsIFrame; -interface nsIChromeFrameMessageManager; +interface nsIMessageSender; interface nsIVariant; interface nsIDOMElement; @@ -108,7 +108,7 @@ interface nsIContentViewManager : nsISupports readonly attribute nsIContentView rootContentView; }; -[scriptable, uuid(fc338eea-47dc-475e-add7-a3933fcfa07c)] +[scriptable, uuid(f234c232-bb17-4450-b324-bf1ef5ccfd34)] interface nsIFrameLoader : nsISupports { /** @@ -177,7 +177,7 @@ interface nsIFrameLoader : nsISupports void activateFrameEvent(in AString aType, in boolean capture); // Note, when frameloaders are swapped, also messageManagers are swapped. - readonly attribute nsIChromeFrameMessageManager messageManager; + readonly attribute nsIMessageSender messageManager; /** * @see nsIDOMWindowUtils sendKeyEvent. diff --git a/content/base/public/nsIFrameMessageManager.idl b/content/base/public/nsIFrameMessageManager.idl deleted file mode 100644 index 1bc11f0ac7e..00000000000 --- a/content/base/public/nsIFrameMessageManager.idl +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- 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/. */ - -#include "nsISupports.idl" - -interface nsIDOMWindow; -interface nsIDocShell; -interface nsIContent; - -[scriptable, function, uuid(938fcb95-3d63-46be-aa72-94d08fd3b418)] -interface nsIFrameMessageListener : nsISupports -{ - /** - * This is for JS only. - * receiveMessage is called with one parameter, which has the following - * properties: - * { - * target: %the target of the message. Either an element owning - * the message manager, or message manager itself if no - * element owns it% - * name: %message name%, - * sync: %true or false%. - * json: %structured clone of the sent message data%, - * json: %same as .data, deprecated%, - * objects: %array of handles or null, always null if sync is false% - * } - * @note objects property isn't implemented yet. - * - * if the message is synchronous, possible return value is sent back - * as JSON (will be changed to use structured clones). - * - * When the listener is called, 'this' value is the target of the message. - */ - void receiveMessage(); -}; - -[scriptable, builtinclass, uuid(9be42627-a5db-456f-8de2-9097da45a8c3)] -interface nsIFrameMessageManager : nsISupports -{ - void addMessageListener(in AString aMessage, in nsIFrameMessageListener aListener); - void removeMessageListener(in AString aMessage, in nsIFrameMessageListener aListener); - [implicit_jscontext,optional_argc] - void sendAsyncMessage([optional] in AString messageName, [optional] in jsval obj); - [notxpcom] boolean markForCC(); -}; - -[scriptable, builtinclass, uuid(28a36ac7-2868-4fa0-ae24-be957d7dce10)] -interface nsISyncMessageSender : nsIFrameMessageManager -{ - /** - * Returns an array of JSON objects. - */ - [implicit_jscontext,optional_argc] - jsval sendSyncMessage([optional] in AString messageName, [optional] in jsval obj); -}; - -[scriptable, builtinclass, uuid(a83f4393-e3cf-44da-8867-1f9174c2c595)] -interface nsIContentFrameMessageManager : nsISyncMessageSender -{ - /** - * The current top level window in the frame or null. - */ - readonly attribute nsIDOMWindow content; - - /** - * The top level docshell or null. - */ - readonly attribute nsIDocShell docShell; - - /** - * Print a string to stdout. - */ - void dump(in DOMString aStr); - - /** - * If leak detection is enabled, print a note to the leak log that this - * process will intentionally crash. - */ - void privateNoteIntentionalCrash(); - - /** - * Ascii base64 data to binary data and vice versa - */ - DOMString atob(in DOMString aAsciiString); - DOMString btoa(in DOMString aBase64Data); -}; - -[uuid(f0936c56-e92c-4927-a85b-e289c3d4a01c)] -interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager -{ - [notxpcom] nsIContent getOwnerContent(); -}; - -[scriptable, builtinclass, uuid(09f79e8c-101b-432b-a494-02f9b5e111c0)] -interface nsITreeItemFrameMessageManager : nsIFrameMessageManager -{ - readonly attribute unsigned long childCount; - nsITreeItemFrameMessageManager getChildAt(in unsigned long aIndex); -}; - -[scriptable, builtinclass, uuid(a51597f0-d669-4260-83e6-1d426a8ac802)] -interface nsIChromeFrameMessageManager : nsITreeItemFrameMessageManager -{ - /** - * Load a script in the (remote) frame. aURL must be the absolute URL. - * data: URLs are also supported. For example data:,dump("foo\n"); - * If aAllowDelayedLoad is true, script will be loaded when the - * remote frame becomes available. Otherwise the script will be loaded - * only if the frame is already available. - */ - void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad); - - /** - * Removes aURL from the list of scripts which support delayed load. - */ - void removeDelayedFrameScript(in AString aURL); -}; - diff --git a/content/base/public/nsIMessageManager.idl b/content/base/public/nsIMessageManager.idl new file mode 100644 index 00000000000..ce9c32f8178 --- /dev/null +++ b/content/base/public/nsIMessageManager.idl @@ -0,0 +1,330 @@ +/* -*- 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/. */ + +#include "nsISupports.idl" + +interface nsIDOMWindow; +interface nsIDocShell; +interface nsIContent; + +/** + * Message managers provide a way for chrome-privileged JS code to + * communicate with each other, even across process boundaries. + * + * Message managers are separated into "parent side" and "child side". + * These don't always correspond to process boundaries, but can. For + * each child-side message manager, there is always exactly one + * corresponding parent-side message manager that it sends messages + * to. However, for each parent-side message manager, there may be + * either one or many child-side managers it can message. + * + * Message managers that always have exactly one "other side" are of + * type nsIMessageSender. Parent-side message managers that have many + * "other sides" are of type nsIMessageBroadcaster. + * + * Child-side message managers can send synchronous messages to their + * parent side, but not the other way around. + * + * There are two realms of message manager hierarchies. One realm + * approximately corresponds to DOM elements, the other corresponds to + * process boundaries. + * + * Message managers corresponding to DOM elements + * ============================================== + * + * In this realm of message managers, there are + * - "frame message managers" which correspond to frame elements + * - "window message managers" which correspond to top-level chrome + * windows + * - the "global message manager", on the parent side. See below. + * + * The DOM-realm message managers can communicate in the ways shown by + * the following diagram. The parent side and child side can + * correspond to process boundaries, but don't always. + * + * Parent side Child side + * ------------- ------------ + * global MMg + * | + * +-->window MMw1 + * | | + * | +-->frame MMp1_1<------------>frame MMc1_1 + * | | + * | +-->frame MMp1_2<------------>frame MMc1_2 + * | ... + * | + * +-->window MMw2 + * ... + * + * For example: a message sent from MMc1_1, from the child side, is + * sent only to MMp1_1 on the parent side. However, note that all + * message managers in the hierarchy above MMp1_1, in this diagram + * MMw1 and MMg, will also notify their message listeners when the + * message arrives. + + * For example: a message broadcast through the global MMg on the + * parent side would be broadcast to MMw1, which would transitively + * broadcast it to MMp1_1, MM1p_2". The message would next be + * broadcast to MMw2, and so on down the hierarchy. + * + * ***** PERFORMANCE AND SECURITY WARNING ***** + * Messages broadcast through the global MM and window MMs can result + * in messages being dispatched across many OS processes, and to many + * processes with different permissions. Great care should be taken + * when broadcasting. + * + * Interfaces + * ---------- + * + * The global MMg and window MMw's are message broadcasters implementing + * nsIMessageBroadcaster while the frame MMp's are simple message senders + * (nsIMessageSender). Their counterparts in the content processes are + * message senders implementing nsIContentFrameMessageManager. + * + * nsIMessageListenerManager + * / \ + * nsIMessageSender nsIMessageBroadcaster + * | + * nsISyncMessageSender (content process/in-process only) + * | + * nsIContentFrameMessageManager (content process/in-process only) + * | + * nsIInProcessContentFrameMessageManager (in-process only) + * + * + * Message managers in the chrome process can also be QI'ed to nsIFrameScriptLoader. + * + * + * Message managers corresponding to process boundaries + * ==================================================== + * + * The second realm of message managers is the "process message + * managers". With one exception, these always correspond to process + * boundaries. The picture looks like + * + * Parent process Child processes + * ---------------- ----------------- + * global PPMM + * | + * +<----> child PPMM + * | + * +-->parent PMM1<------------------>child process CMM1 + * | + * +-->parent PMM2<------------------>child process PMM2 + * ... + * + * For example: the parent-process PMM1 sends messages directly to + * only the child-process CMM1. + * + * For example: CMM1 sends messages directly to PMM1. The global PPMM + * will also notify their message listeners when the message arrives. + * + * For example: messages sent through the global PPMM will be + * dispatched to the listeners of the same-process, "child PPMM". + * They will also be broadcast to PPM1, PPM2, etc. + * + * ***** PERFORMANCE AND SECURITY WARNING ***** + * Messages broadcast through the global PPMM can result in messages + * being dispatched across many OS processes, and to many processes + * with different permissions. Great care should be taken when + * broadcasting. + * + * Requests sent to parent-process message listeners should usually + * have replies scoped to the requesting CPMM. The following pattern + * is common + * + * const ParentProcessListener = { + * receiveMessage: function(aMessage) { + * let childMM = aMessage.target.QueryInterface(Ci.nsIMessageSender); + * switch (aMessage.name) { + * case "Foo:Request": + * // service request + * childMM.sendAsyncMessage("Foo:Response", { data }); + * } + * } + * }; + */ + +[scriptable, function, uuid(2b44eb57-a9c6-4773-9a1e-fe0818739a4c)] +interface nsIMessageListener : nsISupports +{ + /** + * This is for JS only. + * receiveMessage is called with one parameter, which has the following + * properties: + * { + * target: %the target of the message. Either an element owning + * the message manager, or message manager itself if no + * element owns it% + * name: %message name%, + * sync: %true or false%. + * data: %structured clone of the sent message data%, + * json: %same as .data, deprecated%, + * objects: %array of handles or null, always null if sync is false% + * } + * @note objects property isn't implemented yet. + * + * Each listener is invoked with its own copy of the message + * parameter. + * + * When the listener is called, 'this' value is the target of the message. + * + * If the message is synchronous, the possible return value is + * returned as JSON (will be changed to use structured clones). + * When there are multiple listeners to sync messages, each + * listener's return value is sent back as an array. |undefined| + * return values show up as undefined values in the array. + */ + void receiveMessage(); +}; + +[scriptable, builtinclass, uuid(9c37a142-3de3-4902-a1a4-133f37d5980a)] +interface nsIMessageListenerManager : nsISupports +{ + /** + * Register |listener| to receive |messageName|. All listener + * callbacks for a particular message are invoked when that message + * is received. + * + * The message manager holds a strong ref to |listener|. + * + * If the same listener registers twice for the same message, the + * second registration is ignored. + */ + void addMessageListener(in AString messageName, + in nsIMessageListener listener); + + /** + * No longer invoke |listener| when |messageName| is received, after + * the first time removeMessageListener() is called. + */ + void removeMessageListener(in AString messageName, + in nsIMessageListener listener); + + [notxpcom] boolean markForCC(); +}; + +/** + * Message "senders" have a single "other side" to which messages are + * sent. For example, a child-process message manager will send + * messages that are only delivered to its one parent-process message + * manager. + */ +[scriptable, builtinclass, uuid(7f23767d-0f39-40c1-a22d-d3ab8a481f9d)] +interface nsIMessageSender : nsIMessageListenerManager +{ + /** + * Send |messageName| and |obj| to the "other side" of this message + * manager. This invokes listeners who registered for + * |messageName|. + * + * See nsIMessageListener::receiveMessage() for the format of the + * data delivered to listeners. + */ + [implicit_jscontext, optional_argc] + void sendAsyncMessage([optional] in AString messageName, + [optional] in jsval obj); +}; + +/** + * Message "broadcasters" don't have a single "other side" that they + * send messages to, but rather a set of subordinate message managers. + * For example, broadcasting a message through a window message + * manager will broadcast the message to all frame message managers + * within its window. + */ +[scriptable, builtinclass, uuid(d36346b9-5d3b-497d-9c28-ffbc3e4f6d0d)] +interface nsIMessageBroadcaster : nsIMessageListenerManager +{ + /** + * Like |sendAsyncMessage()|, but also broadcasts this message to + * all "child" message managers of this message manager. See long + * comment above for details. + * + * WARNING: broadcasting messages can be very expensive and leak + * sensitive data. Use with extreme caution. + */ + [implicit_jscontext, optional_argc] + void broadcastAsyncMessage([optional] in AString messageName, + [optional] in jsval obj); + + /** + * Number of subordinate message managers. + */ + readonly attribute unsigned long childCount; + + /** + * Return a single subordinate message manager. + */ + nsIMessageListenerManager getChildAt(in unsigned long aIndex); +}; + +[scriptable, builtinclass, uuid(83be5862-2996-4685-ae7d-ae25bd795d50)] +interface nsISyncMessageSender : nsIMessageSender +{ + /** + * Like |sendAsyncMessage()|, except blocks the sender until all + * listeners of the message have been invoked. Returns an array + * containing return values from each listener invoked. + */ + [implicit_jscontext, optional_argc] + jsval sendSyncMessage([optional] in AString messageName, + [optional] in jsval obj); +}; + +[scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)] +interface nsIContentFrameMessageManager : nsISyncMessageSender +{ + /** + * The current top level window in the frame or null. + */ + readonly attribute nsIDOMWindow content; + + /** + * The top level docshell or null. + */ + readonly attribute nsIDocShell docShell; + + /** + * Print a string to stdout. + */ + void dump(in DOMString aStr); + + /** + * If leak detection is enabled, print a note to the leak log that this + * process will intentionally crash. + */ + void privateNoteIntentionalCrash(); + + /** + * Ascii base64 data to binary data and vice versa + */ + DOMString atob(in DOMString aAsciiString); + DOMString btoa(in DOMString aBase64Data); +}; + +[uuid(a2325927-9c0c-437d-9215-749c79235031)] +interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager +{ + [notxpcom] nsIContent getOwnerContent(); +}; + +[scriptable, builtinclass, uuid(a54acd34-4141-46f5-b71b-e2ca32879b08)] +interface nsIFrameScriptLoader : nsISupports +{ + /** + * Load a script in the (remote) frame. aURL must be the absolute URL. + * data: URLs are also supported. For example data:,dump("foo\n"); + * If aAllowDelayedLoad is true, script will be loaded when the + * remote frame becomes available. Otherwise the script will be loaded + * only if the frame is already available. + */ + void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad); + + /** + * Removes aURL from the list of scripts which support delayed load. + */ + void removeDelayedFrameScript(in AString aURL); +}; diff --git a/content/base/src/messageWakeupService.js b/content/base/src/messageWakeupService.js index bd32bcd2af0..ca68a5afd20 100644 --- a/content/base/src/messageWakeupService.js +++ b/content/base/src/messageWakeupService.js @@ -21,7 +21,7 @@ MessageWakeupService.prototype = get messageManager() { if (!this._messageManager) this._messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"]. - getService(Ci.nsIFrameMessageManager); + getService(Ci.nsIMessageListenerManager); return this._messageManager; }, @@ -39,7 +39,7 @@ MessageWakeupService.prototype = let data = this.messagesData[aMessage.name]; // TODO: When bug 593407 is ready, stop doing the wrappedJSObject hack // and use this line instead: - // QueryInterface(Ci.nsIFrameMessageListener); + // QueryInterface(Ci.nsIMessageListener); let service = Cc[data.cid][data.method](Ci[data.iid]). wrappedJSObject; diff --git a/content/base/src/nsCCUncollectableMarker.cpp b/content/base/src/nsCCUncollectableMarker.cpp index 26c0441a896..b7a9b6234ac 100644 --- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -92,7 +92,7 @@ MarkUserDataHandler(void* aNode, nsIAtom* aKey, void* aValue, void* aData) static void MarkMessageManagers() { - nsCOMPtr globalMM = + nsCOMPtr globalMM = do_GetService("@mozilla.org/globalmessagemanager;1"); if (!globalMM) { return; @@ -102,20 +102,22 @@ MarkMessageManagers() uint32_t childCount = 0; globalMM->GetChildCount(&childCount); for (uint32_t i = 0; i < childCount; ++i) { - nsCOMPtr windowMM; - globalMM->GetChildAt(i, getter_AddRefs(windowMM)); - if (!windowMM) { + nsCOMPtr childMM; + globalMM->GetChildAt(i, getter_AddRefs(childMM)); + if (!childMM) { continue; } + nsCOMPtr windowMM = do_QueryInterface(childMM); windowMM->MarkForCC(); uint32_t tabChildCount = 0; windowMM->GetChildCount(&tabChildCount); for (uint32_t j = 0; j < tabChildCount; ++j) { - nsCOMPtr tabMM; - windowMM->GetChildAt(j, getter_AddRefs(tabMM)); - if (!tabMM) { + nsCOMPtr childMM; + windowMM->GetChildAt(j, getter_AddRefs(childMM)); + if (!childMM) { continue; } + nsCOMPtr tabMM = do_QueryInterface(childMM); tabMM->MarkForCC(); //XXX hack warning, but works, since we know that // callback data is frameloader. diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index cc7c52021fe..65832422f79 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2244,7 +2244,7 @@ bool SendAsyncMessageToChild(void* aCallbackData, } NS_IMETHODIMP -nsFrameLoader::GetMessageManager(nsIChromeFrameMessageManager** aManager) +nsFrameLoader::GetMessageManager(nsIMessageSender** aManager) { EnsureMessageManager(); if (mMessageManager) { @@ -2336,13 +2336,13 @@ nsFrameLoader::EnsureMessageManager() nsCOMPtr chromeWindow = do_QueryInterface(GetOwnerDoc()->GetWindow()); - nsCOMPtr parentManager; + nsCOMPtr parentManager; if (chromeWindow) { chromeWindow->GetMessageManager(getter_AddRefs(parentManager)); } if (ShouldUseRemoteProcess()) { - mMessageManager = new nsFrameMessageManager(true, + mMessageManager = new nsFrameMessageManager(true, /* aChrome */ nullptr, SendAsyncMessageToChild, LoadScript, @@ -2350,7 +2350,7 @@ nsFrameLoader::EnsureMessageManager() static_cast(parentManager.get()), cx); } else { - mMessageManager = new nsFrameMessageManager(true, + mMessageManager = new nsFrameMessageManager(true, /* aChrome */ nullptr, SendAsyncMessageToChild, LoadScript, diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 838d39e3c7e..45e1308ee91 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -24,6 +24,7 @@ #include "nsIProtocolHandler.h" #include "nsIScriptSecurityManager.h" #include "nsIJSRuntimeService.h" +#include "nsIDOMClassInfo.h" #include "nsIDOMFile.h" #include "xpcpublic.h" #include "mozilla/Preferences.h" @@ -64,7 +65,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameMessageManager) tmp->mListeners.Clear(); - for (int32_t i = tmp->mChildManagers.Count(); i > 0; --i) { + for (PRInt32 i = tmp->mChildManagers.Count(); i > 0; --i) { static_cast(tmp->mChildManagers[i - 1])-> Disconnect(false); } @@ -74,30 +75,48 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager) - NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIFrameMessageManager, - (mChrome ? - static_cast( - static_cast(this)) : - static_cast( - static_cast(this)))) + + /* nsFrameMessageManager implements nsIMessageSender and nsIMessageBroadcaster, + * both of which descend from nsIMessageListenerManager. QI'ing to + * nsIMessageListenerManager is therefore ambiguous and needs explicit casts + * depending on which child interface applies. */ + NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIMessageListenerManager, + (mIsBroadcaster ? + static_cast( + static_cast(this)) : + static_cast( + static_cast(this)))) + + /* Message managers in child process implement nsIMessageSender and + nsISyncMessageSender. Message managers in the chrome process are + either broadcasters (if they have subordinate/child message + managers) or they're simple message senders. */ + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMessageSender, !mChrome || !mIsBroadcaster) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMessageBroadcaster, mChrome && mIsBroadcaster) + /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager, !mChrome && !mIsProcessManager) - /* Message managers in child process support nsISyncMessageSender. */ - NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome) - /* Message managers in chrome process support nsITreeItemFrameMessageManager. */ - NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITreeItemFrameMessageManager, mChrome) - /* Process message manager doesn't support nsIChromeFrameMessageManager. */ - NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager, + + /* Frame message managers (non-process message managers) support nsIFrameScriptLoader. */ + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFrameScriptLoader, mChrome && !mIsProcessManager) + + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageBroadcaster, + mChrome && mIsBroadcaster) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageSender, + mChrome && !mIsBroadcaster) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameMessageManager) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameMessageManager) +// nsIMessageListenerManager + NS_IMETHODIMP nsFrameMessageManager::AddMessageListener(const nsAString& aMessage, - nsIFrameMessageListener* aListener) + nsIMessageListener* aListener) { nsCOMPtr message = do_GetAtom(aMessage); uint32_t len = mListeners.Length(); @@ -116,7 +135,7 @@ nsFrameMessageManager::AddMessageListener(const nsAString& aMessage, NS_IMETHODIMP nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage, - nsIFrameMessageListener* aListener) + nsIMessageListener* aListener) { nsCOMPtr message = do_GetAtom(aMessage); uint32_t len = mListeners.Length(); @@ -130,6 +149,8 @@ nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage, return NS_OK; } +// nsIFrameScriptLoader + NS_IMETHODIMP nsFrameMessageManager::LoadFrameScript(const nsAString& aURL, bool aAllowDelayedLoad) @@ -152,7 +173,7 @@ nsFrameMessageManager::LoadFrameScript(const nsAString& aURL, NS_ENSURE_TRUE(mLoadScriptCallback(mCallbackData, aURL), NS_ERROR_FAILURE); } - for (int32_t i = 0; i < mChildManagers.Count(); ++i) { + for (PRInt32 i = 0; i < mChildManagers.Count(); ++i) { nsRefPtr mm = static_cast(mChildManagers[i]); if (mm) { @@ -208,6 +229,9 @@ GetParamsForMessage(JSContext* aCx, return WriteStructuredClone(aCx, val, aBuffer, aClosure); } + +// nsISyncMessageSender + NS_IMETHODIMP nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName, const jsval& aObject, @@ -257,26 +281,30 @@ nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName, } nsresult -nsFrameMessageManager::SendAsyncMessageInternal(const nsAString& aMessage, - const StructuredCloneData& aData) +nsFrameMessageManager::DispatchAsyncMessageInternal(const nsAString& aMessage, + const StructuredCloneData& aData, + ShouldBroadcast aBroadcast) { if (mAsyncCallback) { NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED); mAsyncCallback(mCallbackData, aMessage, aData); } - int32_t len = mChildManagers.Count(); - for (int32_t i = 0; i < len; ++i) { - static_cast(mChildManagers[i])-> - SendAsyncMessageInternal(aMessage, aData); + if (aBroadcast == BROADCAST) { + PRInt32 len = mChildManagers.Count(); + for (PRInt32 i = 0; i < len; ++i) { + static_cast(mChildManagers[i])-> + DispatchAsyncMessageInternal(aMessage, aData, aBroadcast); + } } return NS_OK; } -NS_IMETHODIMP -nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, - const jsval& aObject, - JSContext* aCx, - uint8_t aArgc) +nsresult +nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, + const jsval& aObject, + JSContext* aCx, + uint8_t aArgc, + ShouldBroadcast aBroadcast) { StructuredCloneData data; JSAutoStructuredCloneBuffer buffer; @@ -289,9 +317,54 @@ nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, data.mData = buffer.data(); data.mDataLength = buffer.nbytes(); - return SendAsyncMessageInternal(aMessageName, data); + return DispatchAsyncMessageInternal(aMessageName, data, aBroadcast); } + +// nsIMessageSender + +NS_IMETHODIMP +nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, + const jsval& aObject, + JSContext* aCx, + uint8_t aArgc) +{ + return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, DONT_BROADCAST); +} + + +// nsIMessageBroadcaster + +NS_IMETHODIMP +nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName, + const jsval& aObject, + JSContext* aCx, + uint8_t aArgc) +{ + return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, BROADCAST); +} + +NS_IMETHODIMP +nsFrameMessageManager::GetChildCount(uint32_t* aChildCount) +{ + *aChildCount = static_cast(mChildManagers.Count()); + return NS_OK; +} + +NS_IMETHODIMP +nsFrameMessageManager::GetChildAt(uint32_t aIndex, + nsIMessageListenerManager** aMM) +{ + *aMM = nullptr; + nsCOMPtr mm = + do_QueryInterface(mChildManagers.SafeObjectAt(static_cast(aIndex))); + mm.swap(*aMM); + return NS_OK; +} + + +// nsIContentFrameMessageManager + NS_IMETHODIMP nsFrameMessageManager::Dump(const nsAString& aStr) { @@ -328,24 +401,6 @@ nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell) return NS_OK; } -NS_IMETHODIMP -nsFrameMessageManager::GetChildCount(uint32_t* aChildCount) -{ - *aChildCount = static_cast(mChildManagers.Count()); - return NS_OK; -} - -NS_IMETHODIMP -nsFrameMessageManager::GetChildAt(uint32_t aIndex, - nsITreeItemFrameMessageManager** aMM) -{ - *aMM = nullptr; - nsCOMPtr mm = - do_QueryInterface(mChildManagers.SafeObjectAt(static_cast(aIndex))); - mm.swap(*aMM); - return NS_OK; -} - NS_IMETHODIMP nsFrameMessageManager::Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String) @@ -360,6 +415,7 @@ nsFrameMessageManager::Atob(const nsAString& aAsciiString, return NS_OK; } + class MMListenerRemover { public: @@ -383,6 +439,9 @@ public: nsRefPtr mMM; }; + +// nsIMessageListener + nsresult nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage, @@ -591,17 +650,19 @@ nsFrameMessageManager::Disconnect(bool aRemoveFromParent) } nsresult -NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult) +NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult) { NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE); - nsFrameMessageManager* mm = new nsFrameMessageManager(true, + nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - true); + true /* aGlobal */, + false /* aProcessManager */, + true /* aBroadcaster */); NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY); return CallQueryInterface(mm, aResult); } @@ -1134,20 +1195,21 @@ bool SendAsyncMessageToSameProcessParent(void* aCallbackData, // This creates the global parent process message manager. nsresult -NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult) +NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult) { NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager, "Re-creating sParentProcessManager"); NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE); - nsRefPtr mm = new nsFrameMessageManager(true, + nsRefPtr mm = new nsFrameMessageManager(true /* aChrome */, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - false, - true); + false, /* aGlobal */ + true /* aProcessManager */, + true /* aBroadcaster */); NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY); nsFrameMessageManager::sParentProcessManager = mm; nsFrameMessageManager::NewProcessMessageManager(nullptr); // Create same process message manager. @@ -1158,11 +1220,11 @@ nsFrameMessageManager* nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aProcess) { if (!nsFrameMessageManager::sParentProcessManager) { - nsCOMPtr dummy; + nsCOMPtr dummy; NS_NewParentProcessMessageManager(getter_AddRefs(dummy)); } - nsFrameMessageManager* mm = new nsFrameMessageManager(true, + nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */, nullptr, aProcess ? SendAsyncMessageToChildProcess : SendAsyncMessageToSameProcessChild, @@ -1171,8 +1233,8 @@ nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aPr : static_cast(&nsFrameMessageManager::sChildProcessManager), nsFrameMessageManager::sParentProcessManager, nullptr, - false, - true); + false, /* aGlobal */ + true /* aProcessManager */); if (!aProcess) { sSameProcessParentManager = mm; } @@ -1185,7 +1247,7 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult) NS_ASSERTION(!nsFrameMessageManager::sChildProcessManager, "Re-creating sChildProcessManager"); bool isChrome = IsChromeProcess(); - nsFrameMessageManager* mm = new nsFrameMessageManager(false, + nsFrameMessageManager* mm = new nsFrameMessageManager(false /* aChrome */, isChrome ? SendSyncMessageToSameProcessParent : SendSyncMessageToParentProcess, isChrome ? SendAsyncMessageToSameProcessParent @@ -1194,8 +1256,8 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult) &nsFrameMessageManager::sChildProcessManager, nullptr, nullptr, - false, - true); + false /* aGlobal */, + true /* aProcessManager */); NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY); nsFrameMessageManager::sChildProcessManager = mm; return CallQueryInterface(mm, aResult); diff --git a/content/base/src/nsFrameMessageManager.h b/content/base/src/nsFrameMessageManager.h index 49ba8da84d1..42d2c931273 100644 --- a/content/base/src/nsFrameMessageManager.h +++ b/content/base/src/nsFrameMessageManager.h @@ -5,7 +5,7 @@ #ifndef nsFrameMessageManager_h__ #define nsFrameMessageManager_h__ -#include "nsIFrameMessageManager.h" +#include "nsIMessageManager.h" #include "nsIObserver.h" #include "nsCOMPtr.h" #include "nsAutoPtr.h" @@ -35,7 +35,7 @@ struct JSObject; struct nsMessageListenerInfo { - nsCOMPtr mListener; + nsCOMPtr mListener; nsCOMPtr mMessage; }; @@ -49,7 +49,8 @@ typedef bool (*nsAsyncMessageCallback)(void* aCallbackData, const mozilla::dom::StructuredCloneData& aData); class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager, - public nsIChromeFrameMessageManager + public nsIMessageBroadcaster, + public nsIFrameScriptLoader { typedef mozilla::dom::StructuredCloneData StructuredCloneData; public: @@ -61,10 +62,17 @@ public: nsFrameMessageManager* aParentManager, JSContext* aContext, bool aGlobal = false, - bool aProcessManager = false) - : mChrome(aChrome), mGlobal(aGlobal), mIsProcessManager(aProcessManager), - mHandlingMessage(false), mDisconnected(false), mParentManager(aParentManager), - mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback), + bool aProcessManager = false, + bool aBroadcaster = false) + : mChrome(aChrome), + mGlobal(aGlobal), + mIsProcessManager(aProcessManager), + mIsBroadcaster(aBroadcaster), + mHandlingMessage(false), + mDisconnected(false), + mParentManager(aParentManager), + mSyncCallback(aSyncCallback), + mAsyncCallback(aAsyncCallback), mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData), mContext(aContext) @@ -105,11 +113,12 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager, nsIContentFrameMessageManager) - NS_DECL_NSIFRAMEMESSAGEMANAGER + NS_DECL_NSIMESSAGELISTENERMANAGER + NS_DECL_NSIMESSAGESENDER + NS_DECL_NSIMESSAGEBROADCASTER NS_DECL_NSISYNCMESSAGESENDER NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER - NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER - NS_DECL_NSITREEITEMFRAMEMESSAGEMANAGER + NS_DECL_NSIFRAMESCRIPTLOADER static nsFrameMessageManager* NewProcessMessageManager(mozilla::dom::ContentParent* aProcess); @@ -130,8 +139,15 @@ public: void Disconnect(bool aRemoveFromParent = true); void SetCallbackData(void* aData, bool aLoadScripts = true); void* GetCallbackData() { return mCallbackData; } - nsresult SendAsyncMessageInternal(const nsAString& aMessage, - const StructuredCloneData& aData); + enum ShouldBroadcast { BROADCAST, DONT_BROADCAST }; + nsresult DispatchAsyncMessage(const nsAString& aMessageName, + const jsval& aObject, + JSContext* aCx, + PRUint8 aArgc, + ShouldBroadcast aBroadcast); + nsresult DispatchAsyncMessageInternal(const nsAString& aMessage, + const StructuredCloneData& aData, + ShouldBroadcast aBroadcast); JSContext* GetJSContext() { return mContext; } void SetJSContext(JSContext* aCx) { mContext = aCx; } void RemoveFromParent(); @@ -157,9 +173,10 @@ protected: friend class MMListenerRemover; nsTArray mListeners; nsCOMArray mChildManagers; - bool mChrome; - bool mGlobal; - bool mIsProcessManager; + bool mChrome; // true if we're in the chrome process + bool mGlobal; // true if + bool mIsProcessManager; // true if the message manager belongs to the process realm + bool mIsBroadcaster; // true if the message manager is a broadcaster bool mHandlingMessage; bool mDisconnected; nsFrameMessageManager* mParentManager; diff --git a/content/base/src/nsInProcessTabChildGlobal.cpp b/content/base/src/nsInProcessTabChildGlobal.cpp index bef5b15e363..f950caf4556 100644 --- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -126,7 +126,7 @@ nsInProcessTabChildGlobal::Init() InitTabChildGlobal(); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Couldn't initialize nsInProcessTabChildGlobal"); - mMessageManager = new nsFrameMessageManager(false, + mMessageManager = new nsFrameMessageManager(false, /* aChrome */ SendSyncMessageToParent, SendAsyncMessageToParent, nullptr, @@ -160,7 +160,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal) - NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager) + NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager) + NS_INTERFACE_MAP_ENTRY(nsIMessageSender) NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender) NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager) NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager) diff --git a/content/base/src/nsInProcessTabChildGlobal.h b/content/base/src/nsInProcessTabChildGlobal.h index c760bb0c257..53540458c57 100644 --- a/content/base/src/nsInProcessTabChildGlobal.h +++ b/content/base/src/nsInProcessTabChildGlobal.h @@ -33,7 +33,8 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper) - NS_FORWARD_SAFE_NSIFRAMEMESSAGEMANAGER(mMessageManager) + NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager) + NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager) NS_IMETHOD SendSyncMessage(const nsAString& aMessageName, const jsval& aObject, JSContext* aCx, diff --git a/content/base/test/chrome/file_bug549682.xul b/content/base/test/chrome/file_bug549682.xul index 16eee8d1463..667d8533604 100644 --- a/content/base/test/chrome/file_bug549682.xul +++ b/content/base/test/chrome/file_bug549682.xul @@ -13,9 +13,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=549682 diff --git a/dom/messages/SystemMessageInternal.js b/dom/messages/SystemMessageInternal.js index 9ebe4a4677d..ba2eb789df8 100644 --- a/dom/messages/SystemMessageInternal.js +++ b/dom/messages/SystemMessageInternal.js @@ -12,9 +12,9 @@ const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "ppmm", function() { - return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); -}); +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", + "@mozilla.org/parentprocessmessagemanager;1", + "nsIMessageBroadcaster"); // Limit the number of pending messages for a given page. let kMaxPendingMessages; @@ -42,9 +42,9 @@ function SystemMessageInternal() { SystemMessageInternal.prototype = { sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) { debug("Broadcasting " + aType + " " + JSON.stringify(aMessage)); - ppmm.sendAsyncMessage("SystemMessageManager:Message" , { type: aType, - msg: aMessage, - manifest: aManifestURI.spec }); + ppmm.broadcastAsyncMessage("SystemMessageManager:Message" , { type: aType, + msg: aMessage, + manifest: aManifestURI.spec }); // Queue the message for pages that registered an handler for this type. this._pages.forEach(function sendMess_openPage(aPage) { diff --git a/dom/messages/SystemMessageManager.js b/dom/messages/SystemMessageManager.js index 5800272370a..34bc3300dca 100644 --- a/dom/messages/SystemMessageManager.js +++ b/dom/messages/SystemMessageManager.js @@ -13,11 +13,9 @@ Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/ObjectWrapper.jsm"); -XPCOMUtils.defineLazyGetter(this, "cpmm", function() { - return Cc["@mozilla.org/childprocessmessagemanager;1"] - .getService(Ci.nsIFrameMessageManager) - .QueryInterface(Ci.nsISyncMessageSender); -}); +XPCOMUtils.defineLazyServiceGetter(this, "cpmm", + "@mozilla.org/childprocessmessagemanager;1", + "nsISyncMessageSender"); // Limit the number of pending messages for a given type. let kMaxPendingMessages; diff --git a/dom/permission/PermissionPromptHelper.jsm b/dom/permission/PermissionPromptHelper.jsm index 2e5970e7919..5ead93a5bf2 100644 --- a/dom/permission/PermissionPromptHelper.jsm +++ b/dom/permission/PermissionPromptHelper.jsm @@ -34,9 +34,9 @@ let EXPORTED_SYMBOLS = ["PermissionPromptHelper"]; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "ppmm", function() { - return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); -}); +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", + "@mozilla.org/parentprocessmessagemanager;1", + "nsIMessageListenerManager"); var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager); var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); @@ -77,7 +77,7 @@ let PermissionPromptHelper = { receiveMessage: function(aMessage) { debug("PermissionPromptHelper::receiveMessage " + aMessage.name); - let mm = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager); + let mm = aMessage.target; let msg = aMessage.data; let result; diff --git a/dom/settings/SettingsChangeNotifier.jsm b/dom/settings/SettingsChangeNotifier.jsm index a92c3b75441..b3f13d081a4 100644 --- a/dom/settings/SettingsChangeNotifier.jsm +++ b/dom/settings/SettingsChangeNotifier.jsm @@ -17,9 +17,9 @@ let EXPORTED_SYMBOLS = ["SettingsChangeNotifier"]; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "ppmm", function() { - return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); -}); +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", + "@mozilla.org/parentprocessmessagemanager;1", + "nsIMessageBroadcaster"); let SettingsChangeNotifier = { @@ -41,7 +41,7 @@ let SettingsChangeNotifier = { let msg = aMessage.json; switch (aMessage.name) { case "Settings:Changed": - ppmm.sendAsyncMessage("Settings:Change:Return:OK", { key: msg.key, value: msg.value }); + ppmm.broadcastAsyncMessage("Settings:Change:Return:OK", { key: msg.key, value: msg.value }); Services.obs.notifyObservers(this, "mozsettings-changed", JSON.stringify({ key: msg.key, value: msg.value diff --git a/dom/settings/SettingsManager.js b/dom/settings/SettingsManager.js index 9c2121d8434..14d515fc341 100644 --- a/dom/settings/SettingsManager.js +++ b/dom/settings/SettingsManager.js @@ -17,9 +17,9 @@ Cu.import("resource://gre/modules/SettingsDB.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "cpmm", function() { - return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); -}); +XPCOMUtils.defineLazyServiceGetter(this, "cpmm", + "@mozilla.org/childprocessmessagemanager;1", + "nsIMessageSender"); const nsIClassInfo = Ci.nsIClassInfo; const SETTINGSLOCK_CONTRACTID = "@mozilla.org/settingsLock;1"; diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js index e8984f0e9b0..8c45a535a0f 100644 --- a/dom/system/gonk/RILContentHelper.js +++ b/dom/system/gonk/RILContentHelper.js @@ -66,7 +66,7 @@ const kUssdReceivedTopic = "mobile-connection-ussd-received"; XPCOMUtils.defineLazyServiceGetter(this, "cpmm", "@mozilla.org/childprocessmessagemanager;1", - "nsIFrameMessageManager"); + "nsISyncMessageSender"); XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator", "@mozilla.org/uuid-generator;1", @@ -161,8 +161,7 @@ function RILContentHelper() { Services.obs.addObserver(this, "xpcom-shutdown", false); // Request initial context. - let rilContext = cpmm.QueryInterface(Ci.nsISyncMessageSender) - .sendSyncMessage("RIL:GetRilContext")[0]; + let rilContext = cpmm.sendSyncMessage("RIL:GetRilContext")[0]; if (!rilContext) { debug("Received null rilContext from chrome process."); @@ -508,7 +507,7 @@ RILContentHelper.prototype = { } }, - // nsIFrameMessageListener + // nsIMessageListener fireRequestSuccess: function fireRequestSuccess(requestId, result) { let request = this.takeRequest(requestId); diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index cf5d1e5b5de..d21a8e343b3 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -79,7 +79,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSmsDatabaseService", XPCOMUtils.defineLazyServiceGetter(this, "ppmm", "@mozilla.org/parentprocessmessagemanager;1", - "nsIFrameMessageManager"); + "nsIMessageBroadcaster"); XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService", "@mozilla.org/settingsService;1", @@ -376,7 +376,7 @@ RadioInterfaceLayer.prototype = { break; case "cardstatechange": this.rilContext.cardState = message.cardState; - ppmm.sendAsyncMessage("RIL:CardStateChanged", message); + ppmm.broadcastAsyncMessage("RIL:CardStateChanged", message); break; case "sms-received": this.handleSmsReceived(message); @@ -428,7 +428,7 @@ RadioInterfaceLayer.prototype = { } break; case "iccmbdn": - ppmm.sendAsyncMessage("RIL:VoicemailNumberChanged", message); + ppmm.broadcastAsyncMessage("RIL:VoicemailNumberChanged", message); break; case "ussdreceived": debug("ussdreceived " + JSON.stringify(message)); @@ -454,8 +454,7 @@ RadioInterfaceLayer.prototype = { return; } - let mm = msg.target.QueryInterface(Ci.nsIFrameMessageManager); - this._messageManagerByRequest[requestId] = mm; + this._messageManagerByRequest[requestId] = msg.target; }, _sendRequestResults: function _sendRequestResults(requestType, options) { @@ -466,7 +465,7 @@ RadioInterfaceLayer.prototype = { return; } - target.sendAsyncMessage(requestType, options); + target.syncAsyncMessage(requestType, options); }, updateNetworkInfo: function updateNetworkInfo(message) { @@ -499,10 +498,10 @@ RadioInterfaceLayer.prototype = { } if (voiceMessage || operatorMessage) { - ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice); + ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voice); } if (dataMessage || operatorMessage) { - ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); + ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data); } if (selectionMessage) { @@ -544,7 +543,7 @@ RadioInterfaceLayer.prototype = { } if (!newInfo.batch) { - ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); + ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); } }, @@ -574,7 +573,7 @@ RadioInterfaceLayer.prototype = { } if (!newInfo.batch) { - ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo); + ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", dataInfo); } if (!this.dataCallSettings["enabled"]) { @@ -600,7 +599,7 @@ RadioInterfaceLayer.prototype = { voiceInfo.relSignalStrength != message.gsmRelative) { voiceInfo.signalStrength = message.gsmDBM; voiceInfo.relSignalStrength = message.gsmRelative; - ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); + ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); } let dataInfo = this.rilContext.data; @@ -608,7 +607,7 @@ RadioInterfaceLayer.prototype = { dataInfo.relSignalStrength != message.gsmRelative) { dataInfo.signalStrength = message.gsmDBM; dataInfo.relSignalStrength = message.gsmRelative; - ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo); + ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", dataInfo); } }, @@ -626,12 +625,12 @@ RadioInterfaceLayer.prototype = { if (this.networkChanged(message, voice.network)) { voice.network = message; - ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice); + ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voice); } if (this.networkChanged(message, data.network)) { data.network = message; - ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); + ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data); } }, @@ -748,7 +747,7 @@ RadioInterfaceLayer.prototype = { this._activeCall = null; } this.updateCallAudioState(); - ppmm.sendAsyncMessage("RIL:CallStateChanged", call); + ppmm.broadcastAsyncMessage("RIL:CallStateChanged", call); }, /** @@ -761,7 +760,7 @@ RadioInterfaceLayer.prototype = { } this.updateCallAudioState(); call.state = nsIRadioInterfaceLayer.CALL_STATE_DISCONNECTED; - ppmm.sendAsyncMessage("RIL:CallStateChanged", call); + ppmm.broadcastAsyncMessage("RIL:CallStateChanged", call); }, /** @@ -789,7 +788,7 @@ RadioInterfaceLayer.prototype = { */ updateNetworkSelectionMode: function updateNetworkSelectionMode(message) { debug("updateNetworkSelectionMode: " + JSON.stringify(message)); - ppmm.sendAsyncMessage("RIL:NetworkSelectionModeChanged", message); + ppmm.broadcastAsyncMessage("RIL:NetworkSelectionModeChanged", message); }, /** @@ -812,7 +811,7 @@ RadioInterfaceLayer.prototype = { * Handle call error. */ handleCallError: function handleCallError(message) { - ppmm.sendAsyncMessage("RIL:CallError", message); + ppmm.broadcastAsyncMessage("RIL:CallError", message); }, /** @@ -873,7 +872,7 @@ RadioInterfaceLayer.prototype = { if (mwi) { mwi.returnNumber = message.sender || null; mwi.returnMessage = message.fullBody || null; - ppmm.sendAsyncMessage("RIL:VoicemailNotification", mwi); + ppmm.broadcastAsyncMessage("RIL:VoicemailNotification", mwi); return; } @@ -975,7 +974,7 @@ RadioInterfaceLayer.prototype = { if (datacall.ifname) { data.connected = (datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED); - ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); + ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data); } this._deliverDataCallCallback("dataCallStateChanged", @@ -996,7 +995,7 @@ RadioInterfaceLayer.prototype = { handleUSSDReceived: function handleUSSDReceived(ussd) { debug("handleUSSDReceived " + JSON.stringify(ussd)); - ppmm.sendAsyncMessage("RIL:UssdReceived", ussd); + ppmm.broadcastAsyncMessage("RIL:UssdReceived", ussd); }, handleSendUSSD: function handleSendUSSD(message) { diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 54d14ea18fb..e6994396e4d 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -296,7 +296,6 @@ var interfaceNamesInGlobalScope = "SVGPathSegLinetoHorizontalAbs", "SVGAnimatedRect", "SVGTextContentElement", - "SyncMessageSender", "WebGLRenderbuffer", "TreeColumn", "WebGLExtensionStandardDerivatives", @@ -402,7 +401,6 @@ var interfaceNamesInGlobalScope = "SVGStyleElement", "XULContainerElement", "DOMTokenList", - "FrameMessageManager", "HTMLHRElement", "HTMLFontElement", "SVGFEFloodElement", @@ -490,7 +488,6 @@ var interfaceNamesInGlobalScope = "MutationObserver", "RequestService", "Counter", - "ContentFrameMessageManager", "SVGAnimatedAngle", "SVGPathSegList", "SVGFEFuncAElement", diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js index 3398ec5dc78..7cf28f8b0ac 100644 --- a/dom/wifi/WifiWorker.js +++ b/dom/wifi/WifiWorker.js @@ -1326,7 +1326,8 @@ let netFromDOM; function WifiWorker() { var self = this; - this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); + this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); const messages = ["WifiManager:setEnabled", "WifiManager:getNetworks", "WifiManager:associate", "WifiManager:forget", "WifiManager:wps", "WifiManager:getState", @@ -1889,7 +1890,7 @@ WifiWorker.prototype = { receiveMessage: function MessageManager_receiveMessage(aMessage) { let msg = aMessage.json || {}; - msg.manager = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager); + msg.manager = aMessage.target; switch (aMessage.name) { case "WifiManager:setEnabled": diff --git a/extensions/cookie/test/unit_ipc/test_parent.js b/extensions/cookie/test/unit_ipc/test_parent.js index 5c773566443..fb217d76ae3 100644 --- a/extensions/cookie/test/unit_ipc/test_parent.js +++ b/extensions/cookie/test/unit_ipc/test_parent.js @@ -27,7 +27,7 @@ function run_test() { pm.addFromPrincipal(getPrincipalForURI("http://mozilla.net"), "cookie3", pm.ALLOW_ACTION, pm.EXPIRE_TIME, Date.now() + 1000*60*60*24); var mM = Cc["@mozilla.org/parentprocessmessagemanager;1"]. - getService(Ci.nsIFrameMessageManager); + getService(Ci.nsIMessageBroadcaster); var messageListener = { receiveMessage: function(aMessage) { @@ -37,7 +37,7 @@ function run_test() { pm.addFromPrincipal(getPrincipalForURI("http://firefox.org"), "cookie1", pm.ALLOW_ACTION, pm.EXPIRE_NEVER, 0); pm.addFromPrincipal(getPrincipalForURI("http://firefox.com"), "cookie2", pm.DENY_ACTION, pm.EXPIRE_SESSION, 0); pm.addFromPrincipal(getPrincipalForURI("http://firefox.net"), "cookie3", pm.ALLOW_ACTION, pm.EXPIRE_TIME, Date.now() + 1000*60*60*24); - mM.sendAsyncMessage("TESTING:Stage2A"); + mM.broadcastAsyncMessage("TESTING:Stage2A"); break; case "TESTING:Stage3": diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index e02d3a29f86..b6c89640bc7 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -58,7 +58,7 @@ #include "nsTransitionManager.h" #include "nsAnimationManager.h" #include "mozilla/dom/Element.h" -#include "nsIFrameMessageManager.h" +#include "nsIMessageManager.h" #include "FrameLayerBuilder.h" #include "nsDOMMediaQueryList.h" #include "nsSMILAnimationController.h" diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 9ef9fc79131..d643db6647d 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -54,7 +54,7 @@ #include "mozilla/Attributes.h" #include "nsIEventListenerService.h" -#include "nsIFrameMessageManager.h" +#include "nsIMessageManager.h" // Transformiix stuff #include "nsXPathEvaluator.h" @@ -422,8 +422,8 @@ nsresult NS_NewTextEncoder(nsIDocumentEncoder** aResult); nsresult NS_NewContentPolicy(nsIContentPolicy** aResult); nsresult NS_NewEventListenerService(nsIEventListenerService** aResult); -nsresult NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult); -nsresult NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult); +nsresult NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult); +nsresult NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult); nsresult NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult); nsresult NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult); @@ -519,9 +519,9 @@ MAKE_CTOR(CreateXMLContentBuilder, nsIXMLContentBuilder, NS_NewXML #endif MAKE_CTOR(CreateContentDLF, nsIDocumentLoaderFactory, NS_NewContentDocumentLoaderFactory) MAKE_CTOR(CreateEventListenerService, nsIEventListenerService, NS_NewEventListenerService) -MAKE_CTOR(CreateGlobalMessageManager, nsIChromeFrameMessageManager,NS_NewGlobalMessageManager) -MAKE_CTOR(CreateParentMessageManager, nsIFrameMessageManager,NS_NewParentProcessMessageManager) -MAKE_CTOR(CreateChildMessageManager, nsISyncMessageSender,NS_NewChildProcessMessageManager) +MAKE_CTOR(CreateGlobalMessageManager, nsIMessageBroadcaster, NS_NewGlobalMessageManager) +MAKE_CTOR(CreateParentMessageManager, nsIMessageBroadcaster, NS_NewParentProcessMessageManager) +MAKE_CTOR(CreateChildMessageManager, nsISyncMessageSender, NS_NewChildProcessMessageManager) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoDataProtocolContentPolicy) MAKE_CTOR(CreatePluginDocument, nsIDocument, NS_NewPluginDocument) diff --git a/layout/ipc/test-ipcbrowser-chrome.js b/layout/ipc/test-ipcbrowser-chrome.js index 1acd42a5a55..02258ec2de9 100644 --- a/layout/ipc/test-ipcbrowser-chrome.js +++ b/layout/ipc/test-ipcbrowser-chrome.js @@ -36,29 +36,29 @@ function loadURL(url) { } function scrollContentBy(dx, dy) { - messageManager.sendAsyncMessage("scrollBy", - { dx: dx, dy: dy }); + messageManager.broadcastAsyncMessage("scrollBy", + { dx: dx, dy: dy }); } function scrollContentTo(x, y) { - messageManager.sendAsyncMessage("scrollTo", - { x: x, y: y }); + messageManager.broadcastAsyncMessage("scrollTo", + { x: x, y: y }); } function setContentViewport(w, h) { - messageManager.sendAsyncMessage("setViewport", - { w: w, h: h }); + messageManager.broadcastAsyncMessage("setViewport", + { w: w, h: h }); } function setContentDisplayPort(x, y, w, h) { - messageManager.sendAsyncMessage("setDisplayPort", - { x: x, y: y, w: w, h: h }); + messageManager.broadcastAsyncMessage("setDisplayPort", + { x: x, y: y, w: w, h: h }); } function setContentResolution(xres, yres) { - messageManager.sendAsyncMessage("setResolution", - { xres: xres, yres: yres }); + messageManager.broadcastAsyncMessage("setResolution", + { xres: xres, yres: yres }); } // Functions affecting . @@ -107,8 +107,8 @@ function startAnimatedScrollBy(dx, dy) { rootView().scrollBy(ddx, ddy); if (!sentScrollBy && 100 <= (now - start)) { - messageManager.sendAsyncMessage("scrollBy", - { dx: dx, dy: dy }); + messageManager.broadcastAsyncMessage("scrollBy", + { dx: dx, dy: dy }); sentScrollBy = true; } diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index e72bba20179..2a6ea880ceb 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -262,7 +262,7 @@ function OnRefTestLoad(win) #endif gBrowserMessageManager = gBrowser.QueryInterface(CI.nsIFrameLoaderOwner) - .frameLoader.messageManager; + .frameLoader.messageManager; // The content script waits for the initial onload, then notifies // us. RegisterMessageListenersAndLoadContentScript(); diff --git a/mobile/xul/chrome/content/CapturePickerUI.js b/mobile/xul/chrome/content/CapturePickerUI.js index 4a8f8c3195f..cb747d78c79 100644 --- a/mobile/xul/chrome/content/CapturePickerUI.js +++ b/mobile/xul/chrome/content/CapturePickerUI.js @@ -4,7 +4,8 @@ var CapturePickerUI = { init: function() { - this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); + this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); this.messageManager.addMessageListener("CapturePicker:Show", this); }, diff --git a/mobile/xul/chrome/content/WebappsUI.js b/mobile/xul/chrome/content/WebappsUI.js index d822414c820..31bd49acd29 100644 --- a/mobile/xul/chrome/content/WebappsUI.js +++ b/mobile/xul/chrome/content/WebappsUI.js @@ -11,7 +11,8 @@ var WebappsUI = { init: function() { Cu.import("resource://gre/modules/OpenWebapps.jsm"); - this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager); + this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"] + .getService(Ci.nsIMessageBroadcaster); this.messageManager.addMessageListener("OpenWebapps:Install", this); this.messageManager.addMessageListener("OpenWebapps:GetInstalledBy", this); this.messageManager.addMessageListener("OpenWebapps:AmInstalled", this); @@ -96,51 +97,51 @@ var WebappsUI = { }, receiveMessage: function(aMessage) { - this._browser = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager); + this._browser = aMessage.target.QueryInterface(Ci.nsIMessageSender); switch(aMessage.name) { case "OpenWebapps:Install": WebappsUI.show(WebappsUI.convertManifest(aMessage.json)); break; case "OpenWebapps:GetInstalledBy": let apps = OpenWebapps.getInstalledBy(aMessage.json.storeURI); - this._browser.sendAsyncMessage("OpenWebapps:GetInstalledBy:Return", + this._browser.broadcastAsyncMessage("OpenWebapps:GetInstalledBy:Return", { apps: apps, callbackID: aMessage.json.callbackID }); break; case "OpenWebapps:AmInstalled": let app = OpenWebapps.amInstalled(aMessage.json.appURI); - this._browser.sendAsyncMessage("OpenWebapps:AmInstalled:Return", + this._browser.broadcastAsyncMessage("OpenWebapps:AmInstalled:Return", { installed: app != null, app: app, callbackID: aMessage.json.callbackID }); break; case "OpenWebapps:MgmtList": this.askPermission(aMessage, "openWebappsManage", { cancel: function() { - WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtList:Return", + WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtList:Return", { ok: false, callbackID: aMessage.json.callbackID }); }, allow: function() { let list = OpenWebapps.mgmtList(); - WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtList:Return", + WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtList:Return", { ok: true, apps: list, callbackID: aMessage.json.callbackID }); } }); break; case "OpenWebapps:MgmtLaunch": let res = OpenWebapps.mgmtLaunch(aMessage.json.origin); - this._browser.sendAsyncMessage("OpenWebapps:MgmtLaunch:Return", + this._browser.broadcastAsyncMessage("OpenWebapps:MgmtLaunch:Return", { ok: res, callbackID: aMessage.json.callbackID }); break; case "OpenWebapps:MgmtUninstall": this.askPermission(aMessage, "openWebappsManage", { cancel: function() { - WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtUninstall:Return", + WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtUninstall:Return", { ok: false, callbackID: aMessage.json.callbackID }); }, allow: function() { let app = OpenWebapps.amInstalled(aMessage.json.origin); let uninstalled = OpenWebapps.mgmtUninstall(aMessage.json.origin); - WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtUninstall:Return", + WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtUninstall:Return", { ok: uninstalled, app: app, callbackID: aMessage.json.callbackID }); } }); @@ -196,7 +197,7 @@ var WebappsUI = { hide: function hide() { this.close(); - this._browser.sendAsyncMessage("OpenWebapps:InstallAborted", { callbackID: this._application.callbackID }); + this._browser.broadcastAsyncMessage("OpenWebapps:InstallAborted", { callbackID: this._application.callbackID }); }, close: function close() { @@ -239,7 +240,7 @@ var WebappsUI = { try { OpenWebapps.install(this._application); let app = OpenWebapps.amInstalled(this._application.appURI); - this.messageManager.sendAsyncMessage("OpenWebapps:InstallDone", { app: app, callbackID: this._application.callbackID }); + this.messageManager.broadcastAsyncMessage("OpenWebapps:InstallDone", { app: app, callbackID: this._application.callbackID }); } catch(e) { Cu.reportError(e); } diff --git a/mobile/xul/chrome/content/bindings/browser.xml b/mobile/xul/chrome/content/bindings/browser.xml index ba085870893..964572eb288 100644 --- a/mobile/xul/chrome/content/bindings/browser.xml +++ b/mobile/xul/chrome/content/bindings/browser.xml @@ -14,7 +14,7 @@ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - + null - + Date: Mon, 27 Aug 2012 10:20:46 -0400 Subject: [PATCH 21/21] Bug 785772 - Don't use -O0 during stage1 on darwin. r=rail. We only need to build stage1 with -O0 on linux because of a bug in the gcc 4.5 we use. --- build/unix/build-clang/build-clang.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/unix/build-clang/build-clang.py b/build/unix/build-clang/build-clang.py index 23cd7aac85c..0df4e827955 100755 --- a/build/unix/build-clang/build-clang.py +++ b/build/unix/build-clang/build-clang.py @@ -70,6 +70,8 @@ def build_one_stage(env, stage_dir, is_stage_one): build_one_stage_aux(stage_dir, is_stage_one) with_env(env, f) +isDarwin = platform.system() == "Darwin" + def build_one_stage_aux(stage_dir, is_stage_one): os.mkdir(stage_dir) @@ -80,12 +82,11 @@ def build_one_stage_aux(stage_dir, is_stage_one): "--disable-assertions", "--prefix=%s" % inst_dir, "--with-gcc-toolchain=/tools/gcc-4.5-0moz3"] - if is_stage_one: + if is_stage_one and not isDarwin: configure_opts.append("--with-optimize-option=-O0") build_package(llvm_source_dir, build_dir, configure_opts) -isDarwin = platform.system() == "Darwin" if isDarwin: os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'