From ff3e7f88a3f55affe6aff87eb094f08351e29af3 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 30 Jan 2014 18:40:23 +1300 Subject: [PATCH 01/88] Bug 965030 - Pass the correct positioned frame to PushAbsoluteContainingBlock. r=roc --- layout/base/nsCSSFrameConstructor.cpp | 2 +- layout/reftests/svg/foreignObject-fixedpos-02.html | 9 +++++++++ layout/reftests/svg/foreignObject-fixedpos-ref.html | 4 ++++ layout/reftests/svg/reftest.list | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 layout/reftests/svg/foreignObject-fixedpos-02.html create mode 100644 layout/reftests/svg/foreignObject-fixedpos-ref.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index cccaa5279aa0..57f5730005f5 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -3659,7 +3659,7 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt (maybeAbsoluteContainingBlockDisplay->HasTransformStyle() && cb->IsFrameOfType(nsIFrame::eSupportsCSSTransforms))) && !cb->IsSVGText()) { - aState.PushAbsoluteContainingBlock(cb, primaryFrame, absoluteSaveState); + aState.PushAbsoluteContainingBlock(cb, cb, absoluteSaveState); } } diff --git a/layout/reftests/svg/foreignObject-fixedpos-02.html b/layout/reftests/svg/foreignObject-fixedpos-02.html new file mode 100644 index 000000000000..c4047625c00c --- /dev/null +++ b/layout/reftests/svg/foreignObject-fixedpos-02.html @@ -0,0 +1,9 @@ + +
+
+ + +
+
+
+
diff --git a/layout/reftests/svg/foreignObject-fixedpos-ref.html b/layout/reftests/svg/foreignObject-fixedpos-ref.html new file mode 100644 index 000000000000..da29d249b478 --- /dev/null +++ b/layout/reftests/svg/foreignObject-fixedpos-ref.html @@ -0,0 +1,4 @@ + +
+
+
diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index 8e0eff4d88d9..023175d6b41c 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -172,6 +172,7 @@ skip-if(B2G) == foreignObject-start-hidden-02.svg pass.svg skip-if(B2G) == foreignObject-style-change-01.svg pass.svg == foreignObject-dynamic-abspos-01.html foreignObject-dynamic-abspos-01-ref.html fuzzy-if(Android,18,600) == foreignObject-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html +== foreignObject-fixedpos-02.html foreignObject-fixedpos-ref.html == foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html == g-transform-01.svg pass.svg == getElementById-a-element-01.svg pass.svg From a3449e66b6b507cf02e37215eab4351b76e929b3 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 30 Jan 2014 18:41:17 +1300 Subject: [PATCH 02/88] Bug 946952 - Run a 'compressed' paint up to 1 second after skipping the ColorLayer optimization. r=roc --- layout/base/FrameLayerBuilder.cpp | 16 ++++++++++- layout/base/FrameLayerBuilder.h | 10 +++++++ layout/base/nsDisplayList.cpp | 4 +++ layout/base/nsDisplayList.h | 6 +++- layout/base/nsIPresShell.h | 9 +++++- layout/base/nsLayoutUtils.cpp | 3 ++ layout/base/nsLayoutUtils.h | 5 +++- layout/base/nsPresShell.cpp | 47 +++++++++++++++++++++++++++++-- layout/base/nsPresShell.h | 8 +++++- layout/generic/nsFrame.cpp | 13 +++++++-- layout/generic/nsIFrame.h | 11 +++++--- 11 files changed, 117 insertions(+), 15 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 46dc9050cba3..21ef0979a9aa 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -1759,7 +1759,7 @@ ContainerState::PopThebesLayerData() nsRefPtr imageContainer = data->CanOptimizeImageLayer(mBuilder); if ((data->mIsSolidColorInVisibleRegion || imageContainer) && - data->mLayer->GetValidRegion().IsEmpty()) { + (data->mLayer->GetValidRegion().IsEmpty() || mLayerBuilder->CheckInLayerTreeCompressionMode())) { NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer), "Can't be a solid color as well as an image!"); if (imageContainer) { @@ -2817,6 +2817,20 @@ FrameLayerBuilder::SaveLastPaintOffset(ThebesLayer* aLayer) } } +bool +FrameLayerBuilder::CheckInLayerTreeCompressionMode() +{ + if (mInLayerTreeCompressionMode) { + return true; + } + + // If we wanted to be in layer tree compression mode, but weren't, then scheduled + // a delayed repaint where we will be. + mRootPresContext->PresShell()->GetRootFrame()->SchedulePaint(nsIFrame::PAINT_DELAYED_COMPRESS); + + return false; +} + void ContainerState::CollectOldLayers() { diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 806b7f5e46fd..65ed8c9281f2 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -152,6 +152,7 @@ public: mRetainingManager(nullptr), mDetectedDOMModification(false), mInvalidateAllLayers(false), + mInLayerTreeCompressionMode(false), mContainerLayerGeneration(0), mMaxContainerLayerGeneration(0) { @@ -591,6 +592,13 @@ public: return mContainingThebesLayer; } + /** + * Attempt to build the most compressed layer tree possible, even if it means + * throwing away existing retained buffers. + */ + void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; } + bool CheckInLayerTreeCompressionMode(); + protected: void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer, bool aRemoveThebesItems, @@ -652,6 +660,8 @@ protected: */ bool mInvalidateAllLayers; + bool mInLayerTreeCompressionMode; + uint32_t mContainerLayerGeneration; uint32_t mMaxContainerLayerGeneration; }; diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 10b9afc05184..b0f66285afc5 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1124,6 +1124,10 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, FrameLayerBuilder *layerBuilder = new FrameLayerBuilder(); layerBuilder->Init(aBuilder, layerManager); + if (aFlags & PAINT_COMPRESSED) { + layerBuilder->SetLayerTreeCompressionMode(); + } + if (aFlags & PAINT_FLUSH_LAYERS) { FrameLayerBuilder::InvalidateAllLayers(layerManager); } diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 1fb41c635fd1..7183b6715502 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1512,6 +1512,9 @@ public: * layer manager has already had BeginTransaction() called on it and * we should not call it again. * + * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode + * to avoid short cut optimizations. + * * ComputeVisibility must be called before Paint. * * This must only be called on the root display list of the display list @@ -1522,7 +1525,8 @@ public: PAINT_USE_WIDGET_LAYERS = 0x01, PAINT_FLUSH_LAYERS = 0x02, PAINT_EXISTING_TRANSACTION = 0x04, - PAINT_NO_COMPOSITE = 0x08 + PAINT_NO_COMPOSITE = 0x08, + PAINT_COMPRESSED = 0x10 }; void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, uint32_t aFlags) const; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index c333a4be3be8..7cc1a10ed84b 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1322,8 +1322,15 @@ public: /** * Ensures that the refresh driver is running, and schedules a view * manager flush on the next tick. + * + * @param aType PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and + * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations. */ - virtual void ScheduleViewManagerFlush() = 0; + enum PaintType { + PAINT_DEFAULT, + PAINT_DELAYED_COMPRESS + }; + virtual void ScheduleViewManagerFlush(PaintType aType = PAINT_DEFAULT) = 0; virtual void ClearMouseCaptureOnView(nsView* aView) = 0; virtual bool IsVisible() = 0; virtual void DispatchSynthMouseMove(mozilla::WidgetGUIEvent* aEvent, diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 265c2a64f948..6b5cc7bd5f4f 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2335,6 +2335,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram if (aFlags & PAINT_NO_COMPOSITE) { flags |= nsDisplayList::PAINT_NO_COMPOSITE; } + if (aFlags & PAINT_COMPRESSED) { + flags |= nsDisplayList::PAINT_COMPRESSED; + } list.PaintRoot(&builder, aRenderingContext, flags); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index d5c8c1787529..6e89a7e24e8c 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -768,7 +768,8 @@ public: PAINT_ALL_CONTINUATIONS = 0x40, PAINT_TO_WINDOW = 0x80, PAINT_EXISTING_TRANSACTION = 0x100, - PAINT_NO_COMPOSITE = 0x200 + PAINT_NO_COMPOSITE = 0x200, + PAINT_COMPRESSED = 0x400 }; /** @@ -799,6 +800,8 @@ public: * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already * been called on aFrame's widget's layer manager and should not be * called again. + * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode + * to avoid short cut optimizations. * * So there are three possible behaviours: * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index ceefdb30d6ae..2610753371e7 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1056,6 +1056,11 @@ PresShell::Destroy() mReflowContinueTimer = nullptr; } + if (mDelayedPaintTimer) { + mDelayedPaintTimer->Cancel(); + mDelayedPaintTimer = nullptr; + } + mSynthMouseMoveEvent.Revoke(); mUpdateImageVisibilityEvent.Revoke(); @@ -3541,9 +3546,41 @@ PresShell::GetRectVisibility(nsIFrame* aFrame, return nsRectVisibility_kVisible; } -void -PresShell::ScheduleViewManagerFlush() +class PaintTimerCallBack MOZ_FINAL : public nsITimerCallback { +public: + PaintTimerCallBack(PresShell* aShell) : mShell(aShell) {} + + NS_DECL_ISUPPORTS + + NS_IMETHODIMP Notify(nsITimer* aTimer) MOZ_FINAL + { + mShell->SetNextPaintCompressed(); + mShell->AddInvalidateHiddenPresShellObserver(mShell->GetPresContext()->RefreshDriver()); + mShell->ScheduleViewManagerFlush(); + return NS_OK; + } + +private: + PresShell* mShell; +}; + +NS_IMPL_ISUPPORTS1(PaintTimerCallBack, nsITimerCallback) + +void +PresShell::ScheduleViewManagerFlush(PaintType aType) +{ + if (aType == PAINT_DELAYED_COMPRESS) { + // Delay paint for 1 second. + static const uint32_t kPaintDelayPeriod = 1000; + if (!mDelayedPaintTimer) { + mDelayedPaintTimer = do_CreateInstance(NS_TIMER_CONTRACTID); + nsRefPtr cb = new PaintTimerCallBack(this); + mDelayedPaintTimer->InitWithCallback(cb, kPaintDelayPeriod, nsITimer::TYPE_ONE_SHOT); + } + return; + } + nsPresContext* presContext = GetPresContext(); if (presContext) { presContext->RefreshDriver()->ScheduleViewManagerFlush(); @@ -5800,7 +5837,8 @@ PresShell::Paint(nsView* aViewToPaint, layerManager->BeginTransaction(); } - if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) { + if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE) && + !mNextPaintCompressed) { NotifySubDocInvalidationFunc computeInvalidFunc = presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0; bool computeInvalidRect = computeInvalidFunc || @@ -5851,6 +5889,9 @@ PresShell::Paint(nsView* aViewToPaint, if (!(aFlags & PAINT_COMPOSITE)) { flags |= nsLayoutUtils::PAINT_NO_COMPOSITE; } + if (mNextPaintCompressed) { + flags |= nsLayoutUtils::PAINT_COMPRESSED; + } if (frame) { // We can paint directly into the widget using its layer manager. diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index 0b6b0b37a786..f8db3a80cb8e 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -201,7 +201,7 @@ public: virtual void WillPaint() MOZ_OVERRIDE; virtual void WillPaintWindow() MOZ_OVERRIDE; virtual void DidPaintWindow() MOZ_OVERRIDE; - virtual void ScheduleViewManagerFlush() MOZ_OVERRIDE; + virtual void ScheduleViewManagerFlush(PaintType aType = PAINT_DEFAULT) MOZ_OVERRIDE; virtual void DispatchSynthMouseMove(mozilla::WidgetGUIEvent* aEvent, bool aFlushOnHoverChange) MOZ_OVERRIDE; virtual void ClearMouseCaptureOnView(nsView* aView) MOZ_OVERRIDE; @@ -351,6 +351,8 @@ public: virtual void RestyleShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot); + void SetNextPaintCompressed() { mNextPaintCompressed = true; } + protected: virtual ~PresShell(); @@ -762,6 +764,8 @@ protected: // moving/sizing loop is running, see bug 491700 for details. nsCOMPtr mReflowContinueTimer; + nsCOMPtr mDelayedPaintTimer; + // The `performance.now()` value when we last started to process reflows. DOMHighResTimeStamp mLastReflowStart; @@ -802,6 +806,8 @@ protected: bool mImageVisibilityVisited : 1; + bool mNextPaintCompressed : 1; + static bool sDisableNonTestMouseEvents; }; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 142208d09f63..22f4294a0807 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4886,7 +4886,7 @@ nsIFrame::IsInvalid(nsRect& aRect) } void -nsIFrame::SchedulePaint(uint32_t aFlags) +nsIFrame::SchedulePaint(PaintType aType) { nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this); nsPresContext *pres = displayRoot->PresContext()->GetRootPresContext(); @@ -4897,8 +4897,15 @@ nsIFrame::SchedulePaint(uint32_t aFlags) return; } - pres->PresShell()->ScheduleViewManagerFlush(); - if (!(aFlags & PAINT_COMPOSITE_ONLY)) { + pres->PresShell()->ScheduleViewManagerFlush(aType == PAINT_DELAYED_COMPRESS ? + nsIPresShell::PAINT_DELAYED_COMPRESS : + nsIPresShell::PAINT_DEFAULT); + + if (aType == PAINT_DELAYED_COMPRESS) { + return; + } + + if (aType == PAINT_DEFAULT) { displayRoot->AddStateBits(NS_FRAME_UPDATE_LAYER_TREE); } nsIPresShell* shell = PresContext()->PresShell(); diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 18f93c581c9d..9c09e8d8d19e 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2328,15 +2328,18 @@ public: * do not trigger a reflow should have this called for them by * DoApplyRenderingChangeToTree. * - * @param aFlags PAINT_COMPOSITE_ONLY : No changes have been made + * @param aType PAINT_COMPOSITE_ONLY : No changes have been made * that require a layer tree update, so only schedule a layer * tree composite. + * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and + * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations. */ - enum { + enum PaintType { PAINT_DEFAULT = 0, - PAINT_COMPOSITE_ONLY = 1 << 0 + PAINT_COMPOSITE_ONLY, + PAINT_DELAYED_COMPRESS }; - void SchedulePaint(uint32_t aFlags = PAINT_DEFAULT); + void SchedulePaint(PaintType aType = PAINT_DEFAULT); /** * Checks if the layer tree includes a dedicated layer for this From 924bb34c92017a87bf521043d95c28598ee0083b Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 29 Jan 2014 13:10:33 +1300 Subject: [PATCH 03/88] Bug 962786 - Convert nsDragService to use Moz2D. r=roc * * * Bug 962786 - Bustage fix on a CLOSED TREE --- layout/base/nsIPresShell.h | 30 +++++++++++-------- layout/base/nsPresShell.cpp | 18 ++++++++---- layout/base/nsPresShell.h | 18 ++++++------ widget/cocoa/nsDragService.mm | 21 +++++++++----- widget/gtk/nsDragService.cpp | 38 +++++++++++++++--------- widget/gtk/nsDragService.h | 16 +++++++---- widget/gtk/nsImageToPixbuf.cpp | 34 ---------------------- widget/gtk/nsImageToPixbuf.h | 2 -- widget/windows/nsDragService.cpp | 28 +++++++++++++----- widget/xpwidgets/nsBaseDragService.cpp | 40 ++++++++++++-------------- widget/xpwidgets/nsBaseDragService.h | 13 +++++++-- 11 files changed, 141 insertions(+), 117 deletions(-) diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 7cc1a10ed84b..3f9117f25b61 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -103,9 +103,13 @@ class Touch; class ShadowRoot; } // namespace dom -namespace layers{ +namespace layers { class LayerManager; } // namespace layers + +namespace gfx { +class SourceSurface; +} // namespace gfx } // namespace mozilla // Flags to pass to SetCapturingContent @@ -128,11 +132,10 @@ typedef struct CapturingContentInfo { nsIContent* mContent; } CapturingContentInfo; - -// db8d5e1e-6392-4ec1-9a29-18ee2ec0889b +//bccc1c01-5123-4f49-9572-c0bf506b6418 #define NS_IPRESSHELL_IID \ -{ 0xdb8d5e1e, 0x6392, 0x4ec1, \ - {0x9a, 0x29, 0x18, 0xee, 0x2e, 0xc0, 0x88, 0x9b}} +{ 0xbccc1c01, 0x5123, 0x4f49, \ + {0x95, 0x72, 0xc0, 0xbf, 0x50, 0x6b, 0x64, 0x18}} // debug VerifyReflow flags #define VERIFY_REFLOW_ON 0x01 @@ -178,6 +181,7 @@ class nsIPresShell : public nsIPresShell_base { protected: typedef mozilla::layers::LayerManager LayerManager; + typedef mozilla::gfx::SourceSurface SourceSurface; enum eRenderFlag { STATE_IGNORING_VIEWPORT_SCROLLING = 0x1, @@ -1031,10 +1035,11 @@ public: * edge of the presshell area. The aPoint, aScreenRect and aSurface * arguments function in a similar manner as RenderSelection. */ - virtual already_AddRefed RenderNode(nsIDOMNode* aNode, - nsIntRegion* aRegion, - nsIntPoint& aPoint, - nsIntRect* aScreenRect) = 0; + virtual mozilla::TemporaryRef + RenderNode(nsIDOMNode* aNode, + nsIntRegion* aRegion, + nsIntPoint& aPoint, + nsIntRect* aScreenRect) = 0; /** * Renders a selection to a surface and returns it. This method is primarily @@ -1051,9 +1056,10 @@ public: * the original. When scaling does not occur, the mouse point isn't used * as the position can be determined from the displayed frames. */ - virtual already_AddRefed RenderSelection(nsISelection* aSelection, - nsIntPoint& aPoint, - nsIntRect* aScreenRect) = 0; + virtual mozilla::TemporaryRef + RenderSelection(nsISelection* aSelection, + nsIntPoint& aPoint, + nsIntRect* aScreenRect) = 0; void AddWeakFrameInternal(nsWeakFrame* aWeakFrame); virtual void AddWeakFrameExternal(nsWeakFrame* aWeakFrame); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 2610753371e7..22a1222b56f1 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -165,6 +165,7 @@ #include "nsIDOMHTMLElement.h" #include "nsIDragSession.h" #include "nsIFrameInlines.h" +#include "mozilla/gfx/2D.h" #ifdef ANDROID #include "nsIDocShellTreeOwner.h" @@ -177,6 +178,7 @@ using namespace mozilla; using namespace mozilla::css; using namespace mozilla::dom; using namespace mozilla::layers; +using namespace mozilla::gfx; CapturingContentInfo nsIPresShell::gCaptureInfo = { false /* mAllowed */, false /* mPointerLock */, false /* mRetargetToElement */, @@ -4846,7 +4848,7 @@ PresShell::CreateRangePaintInfo(nsIDOMRange* aRange, return info; } -already_AddRefed +TemporaryRef PresShell::PaintRangePaintInfo(nsTArray >* aItems, nsISelection* aSelection, nsIntRegion* aRegion, @@ -4915,8 +4917,14 @@ PresShell::PaintRangePaintInfo(nsTArray >* aItems, context.Rectangle(gfxRect(0, 0, pixelArea.width, pixelArea.height)); context.Fill(); + + RefPtr dt = + gfxPlatform::GetPlatform()-> + CreateDrawTargetForSurface(surface, gfx::IntSize(pixelArea.width, pixelArea.height)); + + nsRefPtr ctx = new gfxContext(dt); nsRefPtr rc = new nsRenderingContext(); - rc->Init(deviceContext, surface); + rc->Init(deviceContext, ctx); if (aRegion) { // Convert aRegion from CSS pixels to dev pixels @@ -4964,10 +4972,10 @@ PresShell::PaintRangePaintInfo(nsTArray >* aItems, // restore the old selection display state frameSelection->SetDisplaySelection(oldDisplaySelection); - return surface.forget(); + return dt->Snapshot(); } -already_AddRefed +TemporaryRef PresShell::RenderNode(nsIDOMNode* aNode, nsIntRegion* aRegion, nsIntPoint& aPoint, @@ -5013,7 +5021,7 @@ PresShell::RenderNode(nsIDOMNode* aNode, aScreenRect); } -already_AddRefed +TemporaryRef PresShell::RenderSelection(nsISelection* aSelection, nsIntPoint& aPoint, nsIntRect* aScreenRect) diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index f8db3a80cb8e..c70f311f5bbd 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -162,14 +162,16 @@ public: nscolor aBackgroundColor, gfxContext* aThebesContext) MOZ_OVERRIDE; - virtual already_AddRefed RenderNode(nsIDOMNode* aNode, - nsIntRegion* aRegion, - nsIntPoint& aPoint, - nsIntRect* aScreenRect) MOZ_OVERRIDE; + virtual mozilla::TemporaryRef + RenderNode(nsIDOMNode* aNode, + nsIntRegion* aRegion, + nsIntPoint& aPoint, + nsIntRect* aScreenRect) MOZ_OVERRIDE; - virtual already_AddRefed RenderSelection(nsISelection* aSelection, - nsIntPoint& aPoint, - nsIntRect* aScreenRect) MOZ_OVERRIDE; + virtual mozilla::TemporaryRef + RenderSelection(nsISelection* aSelection, + nsIntPoint& aPoint, + nsIntRect* aScreenRect) MOZ_OVERRIDE; virtual already_AddRefed GetRootWindow() MOZ_OVERRIDE; @@ -504,7 +506,7 @@ protected: * aScreenRect - [out] set to the area of the screen the painted area should * be displayed at */ - already_AddRefed + mozilla::TemporaryRef PaintRangePaintInfo(nsTArray >* aItems, nsISelection* aSelection, nsIntRegion* aRegion, diff --git a/widget/cocoa/nsDragService.mm b/widget/cocoa/nsDragService.mm index 89f0656f14d2..4aa1cd5d8d72 100644 --- a/widget/cocoa/nsDragService.mm +++ b/widget/cocoa/nsDragService.mm @@ -30,6 +30,11 @@ #include "gfxASurface.h" #include "gfxContext.h" #include "nsCocoaUtils.h" +#include "mozilla/gfx/2D.h" +#include "gfxPlatform.h" + +using namespace mozilla; +using namespace mozilla::gfx; #ifdef PR_LOGGING extern PRLogModuleInfo* sCocoaLog; @@ -141,12 +146,12 @@ nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode, CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView); - nsRefPtr surface; + RefPtr surface; nsPresContext* pc; nsresult rv = DrawDrag(aDOMNode, aRegion, NSToIntRound(screenPoint.x), NSToIntRound(screenPoint.y), - aDragRect, getter_AddRefs(surface), &pc); + aDragRect, &surface, &pc); if (!aDragRect->width || !aDragRect->height) { // just use some suitable defaults int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor); @@ -166,13 +171,15 @@ nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode, if (!imgSurface) return nil; - nsRefPtr context = new gfxContext(imgSurface); - if (!context) + RefPtr dt = + gfxPlatform::GetPlatform()-> + CreateDrawTargetForSurface(imgSurface, IntSize(width, height)); + if (!dt) return nil; - context->SetOperator(gfxContext::OPERATOR_SOURCE); - context->SetSource(surface); - context->Paint(); + dt->FillRect(gfx::Rect(0, 0, width, height), + SurfacePattern(surface, ExtendMode::CLAMP), + DrawOptions(1.0f, CompositionOp::OP_SOURCE)); uint32_t* imageData = (uint32_t*)imgSurface->Data(); int32_t stride = imgSurface->Stride(); diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp index 7049dd6b75b4..e44f2c63189c 100644 --- a/widget/gtk/nsDragService.cpp +++ b/widget/gtk/nsDragService.cpp @@ -36,6 +36,11 @@ #include "nsViewManager.h" #include "nsIFrame.h" #include "nsGtkUtils.h" +#include "mozilla/gfx/2D.h" +#include "gfxPlatform.h" + +using namespace mozilla; +using namespace mozilla::gfx; // This sets how opaque the drag image is #define DRAG_IMAGE_ALPHA_LEVEL 0.5 @@ -390,11 +395,11 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, } bool -nsDragService::SetAlphaPixmap(gfxASurface *aSurface, - GdkDragContext *aContext, - int32_t aXOffset, - int32_t aYOffset, - const nsIntRect& dragRect) +nsDragService::SetAlphaPixmap(SourceSurface *aSurface, + GdkDragContext *aContext, + int32_t aXOffset, + int32_t aYOffset, + const nsIntRect& dragRect) { #if (MOZ_WIDGET_GTK == 2) GdkScreen* screen = gtk_widget_get_screen(mHiddenWidget); @@ -422,16 +427,21 @@ nsDragService::SetAlphaPixmap(gfxASurface *aSurface, if (!xPixmapSurface) return false; - nsRefPtr xPixmapCtx = new gfxContext(xPixmapSurface); + RefPtr dt = + gfxPlatform::GetPlatform()-> + CreateDrawTargetForSurface(xPixmapSurface, IntSize(dragRect.width, dragRect.height)); + if (!dt) + return false; // Clear it... - xPixmapCtx->SetOperator(gfxContext::OPERATOR_CLEAR); - xPixmapCtx->Paint(); + dt->ClearRect(Rect(0, 0, dragRect.width, dragRect.height)); // ...and paint the drag image with translucency - xPixmapCtx->SetOperator(gfxContext::OPERATOR_SOURCE); - xPixmapCtx->SetSource(aSurface); - xPixmapCtx->Paint(DRAG_IMAGE_ALPHA_LEVEL); + dt->DrawSurface(aSurface, + Rect(0, 0, dragRect.width, dragRect.height), + Rect(0, 0, dragRect.width, dragRect.height), + DrawSurfaceOptions(), + DrawOptions(DRAG_IMAGE_ALPHA_LEVEL, CompositionOp::OP_SOURCE)); // The drag transaction addrefs the pixmap, so we can just unref it from us here gtk_drag_set_icon_pixmap(aContext, alphaColormap, pixmap, nullptr, @@ -1565,9 +1575,9 @@ void nsDragService::SetDragIcon(GdkDragContext* aContext) nsIntRect dragRect; nsPresContext* pc; - nsRefPtr surface; + RefPtr surface; DrawDrag(mSourceNode, mSourceRegion, mScreenX, mScreenY, - &dragRect, getter_AddRefs(surface), &pc); + &dragRect, &surface, &pc); if (!pc) return; @@ -1597,7 +1607,7 @@ void nsDragService::SetDragIcon(GdkDragContext* aContext) else if (surface) { if (!SetAlphaPixmap(surface, aContext, offsetX, offsetY, dragRect)) { GdkPixbuf* dragPixbuf = - nsImageToPixbuf::SurfaceToPixbuf(surface, dragRect.width, dragRect.height); + nsImageToPixbuf::SourceSurfaceToPixbuf(surface, dragRect.width, dragRect.height); if (dragPixbuf) { gtk_drag_set_icon_pixbuf(aContext, dragPixbuf, offsetX, offsetY); g_object_unref(dragPixbuf); diff --git a/widget/gtk/nsDragService.h b/widget/gtk/nsDragService.h index c1a96ad81213..d4507be6dc16 100644 --- a/widget/gtk/nsDragService.h +++ b/widget/gtk/nsDragService.h @@ -14,6 +14,12 @@ class nsWindow; +namespace mozilla { +namespace gfx { +class SourceSurface; +} +} + #ifndef HAVE_NSGOBJECTREFTRAITS #define HAVE_NSGOBJECTREFTRAITS template @@ -183,11 +189,11 @@ private: // attempts to create a semi-transparent drag image. Returns TRUE if // successful, FALSE if not - bool SetAlphaPixmap(gfxASurface *aPixbuf, - GdkDragContext *aContext, - int32_t aXOffset, - int32_t aYOffset, - const nsIntRect &dragRect); + bool SetAlphaPixmap(SourceSurface *aPixbuf, + GdkDragContext *aContext, + int32_t aXOffset, + int32_t aYOffset, + const nsIntRect &dragRect); gboolean Schedule(DragTask aTask, nsWindow *aWindow, GdkDragContext *aDragContext, diff --git a/widget/gtk/nsImageToPixbuf.cpp b/widget/gtk/nsImageToPixbuf.cpp index 1b11612c7aeb..bc5456302132 100644 --- a/widget/gtk/nsImageToPixbuf.cpp +++ b/widget/gtk/nsImageToPixbuf.cpp @@ -129,37 +129,3 @@ nsImageToPixbuf::SourceSurfaceToPixbuf(SourceSurface* aSurface, return pixbuf; } -GdkPixbuf* -nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, int32_t aWidth, int32_t aHeight) -{ - if (aSurface->CairoStatus()) { - NS_ERROR("invalid surface"); - return nullptr; - } - - nsRefPtr imgSurface; - if (aSurface->GetType() == gfxSurfaceType::Image) { - imgSurface = static_cast - (static_cast(aSurface)); - } else { - imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight), - gfxImageFormat::ARGB32); - - if (!imgSurface) - return nullptr; - - nsRefPtr context = new gfxContext(imgSurface); - if (!context) - return nullptr; - - context->SetOperator(gfxContext::OPERATOR_SOURCE); - context->SetSource(aSurface); - context->Paint(); - } - - RefPtr surface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, - imgSurface); - - return SourceSurfaceToPixbuf(surface, aWidth, aHeight); -} diff --git a/widget/gtk/nsImageToPixbuf.h b/widget/gtk/nsImageToPixbuf.h index 2146dd670933..d7cf1056be56 100644 --- a/widget/gtk/nsImageToPixbuf.h +++ b/widget/gtk/nsImageToPixbuf.h @@ -33,8 +33,6 @@ class nsImageToPixbuf MOZ_FINAL : public nsIImageToPixbuf { * released as needed by the caller using g_object_unref. */ static GdkPixbuf* ImageToPixbuf(imgIContainer * aImage); - static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface, - int32_t aWidth, int32_t aHeight); static GdkPixbuf* SourceSurfaceToPixbuf(SourceSurface* aSurface, int32_t aWidth, int32_t aHeight); diff --git a/widget/windows/nsDragService.cpp b/widget/windows/nsDragService.cpp index 61851c79bee1..53320f306b69 100644 --- a/widget/windows/nsDragService.cpp +++ b/widget/windows/nsDragService.cpp @@ -40,6 +40,10 @@ #include "nsRect.h" #include "nsMathUtils.h" #include "gfxWindowsPlatform.h" +#include "mozilla/gfx/2D.h" + +using namespace mozilla; +using namespace mozilla::gfx; //------------------------------------------------------------------------- // @@ -75,11 +79,11 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode, // Prepare the drag image nsIntRect dragRect; - nsRefPtr surface; + RefPtr surface; nsPresContext* pc; DrawDrag(aDOMNode, aRegion, mScreenX, mScreenY, - &dragRect, getter_AddRefs(surface), &pc); + &dragRect, &surface, &pc); if (!surface) return false; @@ -90,19 +94,27 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode, psdi->crColorKey = CLR_NONE; + RefPtr data = surface->GetDataSurface(); + DataSourceSurface::MappedSurface map; + if (!data->Map(DataSourceSurface::READ, &map)) { + return false; + } + nsRefPtr imgSurface = new gfxImageSurface( gfxIntSize(bmWidth, bmHeight), gfxImageFormat::ARGB32); if (!imgSurface) return false; - nsRefPtr context = new gfxContext(imgSurface); - if (!context) + RefPtr dt = + gfxPlatform::GetPlatform()-> + CreateDrawTargetForSurface(imgSurface, IntSize(bmWidth, bmHeight)); + if (!dt) return false; - context->SetOperator(gfxContext::OPERATOR_SOURCE); - context->SetSource(surface); - context->Paint(); + dt->FillRect(Rect(0, 0, bmWidth, bmHeight), + SurfacePattern(surface, ExtendMode::CLAMP), + DrawOptions(1.0f, CompositionOp::OP_SOURCE)); BITMAPV5HEADER bmih; memset((void*)&bmih, 0, sizeof(BITMAPV5HEADER)); @@ -144,6 +156,8 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode, DeleteDC(hdcSrc); } + data->Unmap(); + return psdi->hbmpDragImage != nullptr; } diff --git a/widget/xpwidgets/nsBaseDragService.cpp b/widget/xpwidgets/nsBaseDragService.cpp index 15b01cea613c..36ee5b604afc 100644 --- a/widget/xpwidgets/nsBaseDragService.cpp +++ b/widget/xpwidgets/nsBaseDragService.cpp @@ -34,12 +34,14 @@ #include "nsMenuPopupFrame.h" #include "mozilla/MouseEvents.h" #include "mozilla/Preferences.h" +#include "mozilla/gfx/2D.h" #include "gfxContext.h" #include "gfxPlatform.h" #include using namespace mozilla; +using namespace mozilla::gfx; #define DRAGIMAGES_PREF "nglayout.enable_drag_images" @@ -426,7 +428,7 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode, nsIScriptableRegion* aRegion, int32_t aScreenX, int32_t aScreenY, nsIntRect* aScreenDragRect, - gfxASurface** aSurface, + RefPtr* aSurface, nsPresContext** aPresContext) { *aSurface = nullptr; @@ -497,9 +499,7 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode, // draw the image for selections if (mSelection) { nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y); - nsRefPtr surface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect); - *aSurface = surface; - NS_IF_ADDREF(*aSurface); + *aSurface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect); return NS_OK; } @@ -532,7 +532,6 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode, } } - nsRefPtr surface; if (!mDragPopup) { // otherwise, just draw the node nsIntRegion clipRegion; @@ -541,8 +540,8 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode, } nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y); - surface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr, - pnt, aScreenDragRect); + *aSurface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr, + pnt, aScreenDragRect); } // if an image was specified, reposition the drag rectangle to @@ -552,9 +551,6 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode, aScreenDragRect->y = sy - mImageY; } - *aSurface = surface; - NS_IF_ADDREF(*aSurface); - return NS_OK; } @@ -564,7 +560,7 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext, nsICanvasElementExternal* aCanvas, int32_t aScreenX, int32_t aScreenY, nsIntRect* aScreenDragRect, - gfxASurface** aSurface) + RefPtr* aSurface) { nsCOMPtr imgContainer; if (aImageLoader) { @@ -620,19 +616,19 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext, aScreenDragRect->height = destSize.height; } - nsRefPtr surface = - gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(destSize.width, destSize.height), - gfxContentType::COLOR_ALPHA); - if (!surface) + RefPtr dt = + gfxPlatform::GetPlatform()-> + CreateOffscreenContentDrawTarget(IntSize(destSize.width, destSize.height), + + SurfaceFormat::B8G8R8A8); + if (!dt) return NS_ERROR_FAILURE; - nsRefPtr ctx = new gfxContext(surface); + nsRefPtr ctx = new gfxContext(dt); if (!ctx) return NS_ERROR_FAILURE; - *aSurface = surface; - NS_ADDREF(*aSurface); - + nsresult result = NS_OK; if (aImageLoader) { gfxRect outRect(0, 0, destSize.width, destSize.height); gfxMatrix scale = @@ -641,10 +637,12 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext, imgContainer->Draw(ctx, GraphicsFilter::FILTER_GOOD, scale, outRect, imgSize, destSize, nullptr, imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); - return NS_OK; } else { - return aCanvas->RenderContextsExternal(ctx, GraphicsFilter::FILTER_GOOD); + result = aCanvas->RenderContextsExternal(ctx, GraphicsFilter::FILTER_GOOD); } + + *aSurface = dt->Snapshot(); + return result; } void diff --git a/widget/xpwidgets/nsBaseDragService.h b/widget/xpwidgets/nsBaseDragService.h index e46edc0c689e..2d1ef6b002d2 100644 --- a/widget/xpwidgets/nsBaseDragService.h +++ b/widget/xpwidgets/nsBaseDragService.h @@ -13,6 +13,7 @@ #include "nsIDOMDataTransfer.h" #include "nsCOMPtr.h" #include "nsPoint.h" +#include "mozilla/RefPtr.h" #include "gfxImageSurface.h" @@ -26,6 +27,12 @@ class nsPresContext; class nsIImageLoadingContent; class nsICanvasElementExternal; +namespace mozilla { +namespace gfx { +class SourceSurface; +} +} + /** * XP DragService wrapper base class */ @@ -35,6 +42,8 @@ class nsBaseDragService : public nsIDragService, { public: + typedef mozilla::gfx::SourceSurface SourceSurface; + nsBaseDragService(); virtual ~nsBaseDragService(); @@ -77,7 +86,7 @@ protected: nsIScriptableRegion* aRegion, int32_t aScreenX, int32_t aScreenY, nsIntRect* aScreenDragRect, - gfxASurface** aSurface, + mozilla::RefPtr* aSurface, nsPresContext **aPresContext); /** @@ -89,7 +98,7 @@ protected: nsICanvasElementExternal* aCanvas, int32_t aScreenX, int32_t aScreenY, nsIntRect* aScreenDragRect, - gfxASurface** aSurface); + mozilla::RefPtr* aSurface); /** * Convert aScreenX and aScreenY from CSS pixels into unscaled device pixels. From 760e2f37109d278eb129a2c12c94b6f170ddb20e Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:32:57 -0800 Subject: [PATCH 04/88] Bug 964891. Don't put up a slow script dialog for no-longer-current inners. Just kill the script instead. r=smaug --- dom/base/nsGlobalWindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index ec4bdd43adbb..bde85d7d8aaf 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -10491,6 +10491,11 @@ nsGlobalWindow::ShowSlowScriptDialog() return KillSlowScript; } + // If our document is not active, just kill the script: we've been unloaded + if (!HasActiveDocument()) { + return KillSlowScript; + } + // Get the nsIPrompt interface from the docshell nsCOMPtr ds = GetDocShell(); NS_ENSURE_TRUE(ds, KillSlowScript); From 8f926f8c8b2764161dcda360e6036cbcc4c64d86 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:03 -0800 Subject: [PATCH 05/88] Bug 963895. Add threadsafe versions of AutoJSContext/AutoSafeJSContext. r=bholley --- dom/bindings/Exceptions.cpp | 8 ++---- js/xpconnect/src/moz.build | 1 + js/xpconnect/src/nsCxPusher.cpp | 45 +++++++++++++++++++++++++++++++++ js/xpconnect/src/nsCxPusher.h | 31 +++++++++++++++++++++++ 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/dom/bindings/Exceptions.cpp b/dom/bindings/Exceptions.cpp index c080c2865247..f471a5e259fb 100644 --- a/dom/bindings/Exceptions.cpp +++ b/dom/bindings/Exceptions.cpp @@ -378,10 +378,7 @@ NS_IMETHODIMP JSStackFrame::GetFilename(nsACString& aFilename) if (!mFilenameInitialized) { JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex); if (desc.script()) { - // This cx dance is silly, since JS_GetScriptFilename ignores - // its cx argument. - JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); - JSAutoRequest ar(cx); + ThreadsafeAutoSafeJSContext cx; JSAutoCompartment ac(cx, desc.script()); const char* filename = JS_GetScriptFilename(cx, desc.script()); if (filename) { @@ -407,8 +404,7 @@ NS_IMETHODIMP JSStackFrame::GetName(nsACString& aFunction) if (!mFunnameInitialized) { JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex); if (desc.fun() && desc.script()) { - JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); - JSAutoRequest ar(cx); + ThreadsafeAutoSafeJSContext cx; JSAutoCompartment ac(cx, desc.script()); JS::Rooted fun(cx, desc.fun()); JS::Rooted funid(cx, JS_GetFunctionDisplayId(fun)); diff --git a/js/xpconnect/src/moz.build b/js/xpconnect/src/moz.build index 5d7844070ae4..a48887d0242e 100644 --- a/js/xpconnect/src/moz.build +++ b/js/xpconnect/src/moz.build @@ -91,6 +91,7 @@ LOCAL_INCLUDES += [ '/content/svg/content/src', '/dom/base', '/dom/events', + '/dom/workers', '/js/ipc', '/layout/base', '/layout/style', diff --git a/js/xpconnect/src/nsCxPusher.cpp b/js/xpconnect/src/nsCxPusher.cpp index 2215a2a5f489..c206d171cbea 100644 --- a/js/xpconnect/src/nsCxPusher.cpp +++ b/js/xpconnect/src/nsCxPusher.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/EventTarget.h" #include "nsDOMJSUtils.h" #include "xpcprivate.h" +#include "WorkerPrivate.h" using mozilla::dom::EventTarget; using mozilla::DebugOnly; @@ -198,11 +199,55 @@ AutoJSContext::operator JSContext*() const return mCx; } +ThreadsafeAutoJSContext::ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) +{ + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + + if (NS_IsMainThread()) { + mCx = nullptr; + mAutoJSContext.construct(); + } else { + mCx = mozilla::dom::workers::GetCurrentThreadJSContext(); + mRequest.construct(mCx); + } +} + +ThreadsafeAutoJSContext::operator JSContext*() const +{ + if (mCx) { + return mCx; + } else { + return mAutoJSContext.ref(); + } +} + AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) : AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) { } +ThreadsafeAutoSafeJSContext::ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) +{ + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + + if (NS_IsMainThread()) { + mCx = nullptr; + mAutoSafeJSContext.construct(); + } else { + mCx = mozilla::dom::workers::GetCurrentThreadJSContext(); + mRequest.construct(mCx); + } +} + +ThreadsafeAutoSafeJSContext::operator JSContext*() const +{ + if (mCx) { + return mCx; + } else { + return mAutoSafeJSContext.ref(); + } +} + AutoPushJSContext::AutoPushJSContext(JSContext *aCx) : mCx(aCx) { if (mCx && mCx != nsXPConnect::XPConnect()->GetCurrentJSContext()) { diff --git a/js/xpconnect/src/nsCxPusher.h b/js/xpconnect/src/nsCxPusher.h index a08c8f23aaaf..0517147b1e88 100644 --- a/js/xpconnect/src/nsCxPusher.h +++ b/js/xpconnect/src/nsCxPusher.h @@ -114,6 +114,22 @@ private: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; +/** + * Use ThreadsafeAutoJSContext when you want an AutoJSContext but might be + * running on a worker thread. + */ +class MOZ_STACK_CLASS ThreadsafeAutoJSContext { +public: + ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM); + operator JSContext*() const; + +private: + JSContext* mCx; // Used on workers. Null means mainthread. + Maybe mRequest; // Used on workers. + Maybe mAutoJSContext; // Used on main thread. + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + /** * AutoSafeJSContext is similar to AutoJSContext but will only return the safe * JS context. That means it will never call ::GetCurrentJSContext(). @@ -123,6 +139,21 @@ public: AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM); }; +/** + * Like AutoSafeJSContext but can be used safely on worker threads. + */ +class MOZ_STACK_CLASS ThreadsafeAutoSafeJSContext { +public: + ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM); + operator JSContext*() const; + +private: + JSContext* mCx; // Used on workers. Null means mainthread. + Maybe mRequest; // Used on workers. + Maybe mAutoSafeJSContext; // Used on main thread. + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + /** * Use AutoPushJSContext when you want to use a specific JSContext that may or * may not be already on the stack. This differs from nsCxPusher in that it only From fdd4a7a9e4c8781d4bc36f7fd734f728d3aedea7 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:10 -0800 Subject: [PATCH 06/88] Bug 962290. Remove support for the JavaScript-global-dynamic-nameset category as a way to install lazy properties on the global. r=peterv --- dom/base/nsDOMClassInfo.cpp | 13 ------------- dom/base/nsIScriptNameSpaceManager.h | 3 --- dom/base/nsScriptNameSpaceManager.cpp | 5 ----- dom/base/nsScriptNameSpaceManager.h | 1 - 4 files changed, 22 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 5c8cd1544e1b..3173d95eac16 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -3079,19 +3079,6 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, return ok ? NS_OK : NS_ERROR_FAILURE; } - if (name_struct->mType == nsGlobalNameStruct::eTypeDynamicNameSet) { - nsCOMPtr nameset = - do_CreateInstance(name_struct->mCID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsIScriptContext *context = aWin->GetContext(); - NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED); - - rv = nameset->InitializeNameSet(context); - - *did_resolve = true; - } - return rv; } diff --git a/dom/base/nsIScriptNameSpaceManager.h b/dom/base/nsIScriptNameSpaceManager.h index a4f89fc81736..6787dd01cde4 100644 --- a/dom/base/nsIScriptNameSpaceManager.h +++ b/dom/base/nsIScriptNameSpaceManager.h @@ -25,9 +25,6 @@ #define JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY \ "JavaScript-global-static-nameset" -#define JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY \ - "JavaScript-global-dynamic-nameset" - #define JAVASCRIPT_DOM_CLASS \ "JavaScript-DOM-class" diff --git a/dom/base/nsScriptNameSpaceManager.cpp b/dom/base/nsScriptNameSpaceManager.cpp index 75af51a35fd8..47a425892edd 100644 --- a/dom/base/nsScriptNameSpaceManager.cpp +++ b/dom/base/nsScriptNameSpaceManager.cpp @@ -369,9 +369,6 @@ nsScriptNameSpaceManager::Init() rv = FillHash(cm, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY); NS_ENSURE_SUCCESS(rv, rv); - rv = FillHash(cm, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY); - NS_ENSURE_SUCCESS(rv, rv); - rv = FillHash(cm, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY); NS_ENSURE_SUCCESS(rv, rv); @@ -626,8 +623,6 @@ nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategory type = nsGlobalNameStruct::eTypeNavigatorProperty; } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY) == 0) { type = nsGlobalNameStruct::eTypeStaticNameSet; - } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY) == 0) { - type = nsGlobalNameStruct::eTypeDynamicNameSet; } else { return NS_OK; } diff --git a/dom/base/nsScriptNameSpaceManager.h b/dom/base/nsScriptNameSpaceManager.h index 2a511b99e912..9baa5d14f400 100644 --- a/dom/base/nsScriptNameSpaceManager.h +++ b/dom/base/nsScriptNameSpaceManager.h @@ -50,7 +50,6 @@ struct nsGlobalNameStruct eTypeNavigatorProperty, eTypeExternalConstructor, eTypeStaticNameSet, - eTypeDynamicNameSet, eTypeClassConstructor, eTypeClassProto, eTypeExternalClassInfoCreator, From ce4a66f630ef67e966bc6a21ed5b69e432fcd260 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:20 -0800 Subject: [PATCH 07/88] Bug 945416 part 1. Move the Components shim into GlobalResolve. r=bholley --- dom/base/nsDOMClassInfo.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 3173d95eac16..680b568acdbc 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2800,12 +2800,20 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct, return true; } +static nsresult +DefineComponentsShim(JSContext *cx, JS::Handle global, nsPIDOMWindow *win); + // static nsresult nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, JS::Handle obj, JS::Handle id, bool *did_resolve) { + if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) { + *did_resolve = true; + return DefineComponentsShim(cx, obj, aWin); + } + *did_resolve = false; nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); @@ -3258,11 +3266,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); MOZ_ASSERT(win->IsInnerWindow()); - if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) { - *objp = obj; - return DefineComponentsShim(cx, obj, win); - } - // Don't resolve standard classes on XrayWrappers, only resolve them if we're // resolving on the real global object. bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj); From 754f19089bd63903625340176c7a2f54fdca4ee0 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:22 -0800 Subject: [PATCH 08/88] Bug 945416 part 2. When invoking a DoNewResolve hook on an Xray, make sure to first invoke it on the underlying object. r=bholley,peterv --- dom/base/nsDOMClassInfo.cpp | 52 ++++++++++++++++++++----------------- dom/bindings/Codegen.py | 23 ++++++++++++++++ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 680b568acdbc..909b943f26df 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2846,26 +2846,23 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, name_struct->mType == nsGlobalNameStruct::eTypeClassProto || name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { // Lookup new DOM bindings. - mozilla::dom::DefineInterface define = + DefineInterface getOrCreateInterfaceObject = name_struct->mDefineDOMInterface; - if (define) { + if (getOrCreateInterfaceObject) { if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor && !OldBindingConstructorEnabled(name_struct, aWin, cx)) { return NS_OK; } + ConstructorEnabled* checkEnabledForScope = name_struct->mConstructorEnabled; + if (checkEnabledForScope && !checkEnabledForScope(cx, obj)) { + return NS_OK; + } + Maybe ac; JS::Rooted global(cx); - bool defineOnXray = xpc::WrapperFactory::IsXrayWrapper(obj); - if (defineOnXray) { - // Check whether to define this property on the Xray first. This allows - // consumers to opt in to defining on the xray even if they don't want - // to define on the underlying global. - if (name_struct->mConstructorEnabled && - !(*name_struct->mConstructorEnabled)(cx, obj)) { - return NS_OK; - } - + bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj); + if (isXray) { global = js::CheckedUnwrap(obj, /* stopAtOuter = */ false); if (!global) { return NS_ERROR_DOM_SECURITY_ERR; @@ -2875,22 +2872,13 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, global = obj; } - // Check whether to define on the global too. Note that at this point cx - // is in the compartment of global even if we were coming in via an Xray. - bool defineOnGlobal = !name_struct->mConstructorEnabled || - (*name_struct->mConstructorEnabled)(cx, global); - - if (!defineOnGlobal && !defineOnXray) { - return NS_OK; - } - - JS::Rooted interfaceObject(cx, define(cx, global, id, - defineOnGlobal)); + JS::Rooted interfaceObject(cx, + getOrCreateInterfaceObject(cx, global, id, !isXray)); if (!interfaceObject) { return NS_ERROR_FAILURE; } - if (defineOnXray) { + if (isXray) { // This really should be handled by the Xray for the window. ac.destroy(); if (!JS_WrapObject(cx, &interfaceObject) || @@ -3342,6 +3330,22 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } + if (isXray) { + // We promise to resolve on the underlying object first. That will create + // the actual interface object if needed and store it in a data structure + // hanging off the global. Then our second call will wrap up in an Xray as + // needed. We do things this way because we use the existence of the + // object in that data structure as a flag that indicates that its name + // (and any relevant named constructor names) has been resolved before; + // this allows us to avoid re-resolving in the Xray case if the property is + // deleted by page script. + bool ignored; + JS::Rooted global(cx, + js::UncheckedUnwrap(obj, /* stopAtOuter = */ false)); + JSAutoCompartment ac(cx, global); + nsresult rv = GlobalResolve(win, cx, global, id, &ignored); + NS_ENSURE_SUCCESS(rv, rv); + } bool did_resolve = false; nsresult rv = GlobalResolve(win, cx, obj, id, &did_resolve); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 4e858001fe1e..78005a60137c 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -7732,6 +7732,29 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod): callArgs="") def generate_code(self): return CGIndenter(CGGeneric( + "{\n" + " // Since we're dealing with an Xray, do the resolve on the\n" + " // underlying object first. That gives it a chance to\n" + " // define properties on the actual object as needed, and\n" + " // then use the fact that it created the objects as a flag\n" + " // o avoid re-resolving the properties if someone deletes\n" + " // them.\n" + " JSAutoCompartment ac(cx, obj);\n" + " JS::Rooted objDesc(cx);\n" + " if (!self->DoNewResolve(cx, obj, id, &objDesc)) {\n" + " return false;\n" + " }\n" + " // If desc.value() is undefined, then the DoNewResolve call\n" + " // has already defined the property on the object. Don't\n" + " // try to also define it.\n" + " if (objDesc.object() &&\n" + " !objDesc.value().isUndefined() &&\n" + " !JS_DefinePropertyById(cx, obj, id, objDesc.value(),\n" + " objDesc.getter(), objDesc.setter(),\n" + " objDesc.attributes())) {\n" + " return false;\n" + " }\n" + "}\n" "return self->DoNewResolve(cx, wrapper, id, desc);")) class CGEnumerateOwnProperties(CGAbstractStaticMethod): From d3046577a3a17ce10ecc8b26ab4dda497057b0ec Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:23 -0800 Subject: [PATCH 09/88] Bug 945416 part 3. Make GlobalResolve fill in a JSPropertyDescriptor that nsWindowSH::NewResolve then uses to actually define the property. r=bholley,peterv --- dom/base/nsDOMClassInfo.cpp | 280 ++++++++++++++++++------------- dom/base/nsDOMClassInfo.h | 2 +- dom/bindings/DOMJSProxyHandler.h | 12 ++ 3 files changed, 181 insertions(+), 113 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 909b943f26df..974a16be61d4 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1630,8 +1630,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, const nsDOMClassInfoData *ci_data, const nsGlobalNameStruct *name_struct, nsScriptNameSpaceManager *nameSpaceManager, - JSObject *dot_prototype, bool install, bool *did_resolve); - + JSObject *dot_prototype, + JS::MutableHandle ctorDesc); NS_IMETHODIMP nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto) @@ -1727,19 +1727,30 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto) } // Don't overwrite a property set by content. - bool found; + bool contentDefinedProperty; if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast(mData->mNameUTF16), - NS_strlen(mData->mNameUTF16), &found)) { + NS_strlen(mData->mNameUTF16), + &contentDefinedProperty)) { return NS_ERROR_FAILURE; } nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); NS_ENSURE_TRUE(nameSpaceManager, NS_OK); - bool unused; - return ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16, - mData, nullptr, nameSpaceManager, proto, !found, - &unused); + JS::Rooted desc(cx); + nsresult rv = ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16, + mData, nullptr, nameSpaceManager, proto, + &desc); + NS_ENSURE_SUCCESS(rv, rv); + if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() && + !JS_DefineUCProperty(cx, global, mData->mNameUTF16, + NS_strlen(mData->mNameUTF16), + desc.value(), desc.getter(), desc.setter(), + desc.attributes())) { + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; } // static @@ -2181,20 +2192,6 @@ public: JS::Handle obj, const jsval &val, bool *bp, bool *_retval); - nsresult Install(JSContext *cx, JS::Handle target, - JS::Handle aThisAsVal) - { - JS::Rooted thisAsVal(cx, aThisAsVal); - // The 'attrs' argument used to be JSPROP_PERMANENT. See bug 628612. - bool ok = JS_WrapValue(cx, &thisAsVal) && - ::JS_DefineUCProperty(cx, target, - reinterpret_cast(mClassName), - NS_strlen(mClassName), thisAsVal, JS_PropertyStub, - JS_StrictPropertyStub, 0); - - return ok ? NS_OK : NS_ERROR_UNEXPECTED; - } - nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle obj); private: @@ -2616,7 +2613,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, const nsDOMClassInfoData *ci_data, const nsGlobalNameStruct *name_struct, nsScriptNameSpaceManager *nameSpaceManager, - JSObject* aDot_prototype, bool install, bool *did_resolve) + JSObject* aDot_prototype, + JS::MutableHandle ctorDesc) { JS::Rooted dot_prototype(cx, aDot_prototype); NS_ASSERTION(ci_data || @@ -2635,9 +2633,12 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, false, &v); NS_ENSURE_SUCCESS(rv, rv); - if (install) { - rv = constructor->Install(cx, obj, v); - NS_ENSURE_SUCCESS(rv, rv); + FillPropertyDescriptor(ctorDesc, obj, 0, v); + // And make sure we wrap the value into the right compartment. Note that we + // do this with ctorDesc.value(), not with v, because we need v to be in the + // right compartment (that of the reflector of |constructor|) below. + if (!JS_WrapValue(cx, ctorDesc.value())) { + return NS_ERROR_UNEXPECTED; } JS::Rooted class_obj(cx, &v.toObject()); @@ -2766,8 +2767,6 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, return NS_ERROR_UNEXPECTED; } - *did_resolve = true; - return NS_OK; } @@ -2801,21 +2800,20 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct, } static nsresult -DefineComponentsShim(JSContext *cx, JS::Handle global, nsPIDOMWindow *win); +LookupComponentsShim(JSContext *cx, JS::Handle global, + nsPIDOMWindow *win, + JS::MutableHandle desc); // static nsresult nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, JS::Handle obj, JS::Handle id, - bool *did_resolve) + JS::MutableHandle desc) { if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) { - *did_resolve = true; - return DefineComponentsShim(cx, obj, aWin); + return LookupComponentsShim(cx, obj, aWin, desc); } - *did_resolve = false; - nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); @@ -2829,6 +2827,9 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, return NS_OK; } + // The class_name had better match our name + MOZ_ASSERT(name.Equals(class_name)); + NS_ENSURE_TRUE(class_name, NS_ERROR_UNEXPECTED); nsresult rv = NS_OK; @@ -2859,39 +2860,73 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, return NS_OK; } - Maybe ac; - JS::Rooted global(cx); - bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj); - if (isXray) { - global = js::CheckedUnwrap(obj, /* stopAtOuter = */ false); + // The DOM constructor resolve machinery interacts with Xrays in tricky + // ways, and there are some asymmetries that are important to understand. + // + // In the regular (non-Xray) case, we only want to resolve constructors + // once (so that if they're deleted, they don't reappear). We do this by + // stashing the constructor in a slot on the global, such that we can see + // during resolve whether we've created it already. This is rather + // memory-intensive, so we don't try to maintain these semantics when + // manipulating a global over Xray (so the properties just re-resolve if + // they've been deleted). + // + // Unfortunately, there's a bit of an impedance-mismatch between the Xray + // and non-Xray machinery. The Xray machinery wants an API that returns a + // JSPropertyDescriptor, so that the resolve hook doesn't have to get + // snared up with trying to define a property on the Xray holder. At the + // same time, the DefineInterface callbacks are set up to define things + // directly on the global. And re-jiggering them to return property + // descriptors is tricky, because some DefineInterface callbacks define + // multiple things (like the Image() alias for HTMLImageElement). + // + // So the setup is as-follows: + // + // * The resolve function takes a JSPropertyDescriptor, but in the + // non-Xray case, callees may define things directly on the global, and + // set the value on the property descriptor to |undefined| to indicate + // that there's nothing more for the caller to do. We assert against + // this behavior in the Xray case. + // + // * We make sure that we do a non-Xray resolve first, so that all the + // slots are set up. In the Xray case, this means unwrapping and doing + // a non-Xray resolve before doing the Xray resolve. + // + // This all could use some grand refactoring, but for now we just limp + // along. + if (xpc::WrapperFactory::IsXrayWrapper(obj)) { + JS::Rooted global(cx, + js::CheckedUnwrap(obj, /* stopAtOuter = */ false)); if (!global) { return NS_ERROR_DOM_SECURITY_ERR; } - ac.construct(cx, global); - } else { - global = obj; - } - - JS::Rooted interfaceObject(cx, - getOrCreateInterfaceObject(cx, global, id, !isXray)); - if (!interfaceObject) { - return NS_ERROR_FAILURE; - } - - if (isXray) { - // This really should be handled by the Xray for the window. - ac.destroy(); - if (!JS_WrapObject(cx, &interfaceObject) || - !JS_DefinePropertyById(cx, obj, id, - JS::ObjectValue(*interfaceObject), JS_PropertyStub, - JS_StrictPropertyStub, 0)) { + JS::Rooted interfaceObject(cx); + { + JSAutoCompartment ac(cx, global); + interfaceObject = getOrCreateInterfaceObject(cx, global, id, false); + } + if (NS_WARN_IF(!interfaceObject)) { + return NS_ERROR_FAILURE; + } + if (!JS_WrapObject(cx, &interfaceObject)) { return NS_ERROR_FAILURE; } + FillPropertyDescriptor(desc, obj, 0, JS::ObjectValue(*interfaceObject)); + } else { + JS::Rooted interfaceObject(cx, + getOrCreateInterfaceObject(cx, obj, id, true)); + if (NS_WARN_IF(!interfaceObject)) { + return NS_ERROR_FAILURE; + } + // We've already defined the property. We indicate this to the caller + // by filling a property descriptor with JS::UndefinedValue() as the + // value. We still have to fill in a property descriptor, though, so + // that the caller knows the property is in fact on this object. It + // doesn't matter what we pass for the "readonly" argument here. + FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false); } - *did_resolve = true; - return NS_OK; } } @@ -2912,20 +2947,22 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, false, &v); NS_ENSURE_SUCCESS(rv, rv); - rv = constructor->Install(cx, obj, v); - NS_ENSURE_SUCCESS(rv, rv); - JS::Rooted class_obj(cx, &v.toObject()); // ... and define the constants from the DOM interface on that // constructor object. - JSAutoCompartment ac(cx, class_obj); - rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID); - NS_ENSURE_SUCCESS(rv, rv); + { + JSAutoCompartment ac(cx, class_obj); + rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID); + NS_ENSURE_SUCCESS(rv, rv); + } - *did_resolve = true; + if (!JS_WrapValue(cx, &v)) { + return NS_ERROR_UNEXPECTED; + } + FillPropertyDescriptor(desc, obj, 0, v); return NS_OK; } @@ -2936,38 +2973,42 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, } // Create the XPConnect prototype for our classinfo, PostCreateProto will - // set up the prototype chain. + // set up the prototype chain. This will go ahead and define things on the + // actual window's global. nsCOMPtr proto_holder; rv = GetXPCProto(sXPConnect, cx, aWin, name_struct, getter_AddRefs(proto_holder)); - - if (NS_SUCCEEDED(rv) && obj != aWin->GetGlobalJSObject()) { - JS::Rooted dot_prototype(cx, proto_holder->GetJSObject()); - NS_ENSURE_STATE(dot_prototype); - - const nsDOMClassInfoData *ci_data; - if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { - ci_data = &sClassInfoData[name_struct->mDOMClassInfoID]; - } else { - ci_data = name_struct->mData; - } - - return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data, - name_struct, nameSpaceManager, dot_prototype, - true, did_resolve); + NS_ENSURE_SUCCESS(rv, rv); + bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj); + MOZ_ASSERT_IF(obj != aWin->GetGlobalJSObject(), isXray); + if (!isXray) { + // GetXPCProto already defined the property for us + FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false); + return NS_OK; } - *did_resolve = NS_SUCCEEDED(rv); + // This is the Xray case. Look up the constructor object for this + // prototype. + JS::Rooted dot_prototype(cx, proto_holder->GetJSObject()); + NS_ENSURE_STATE(dot_prototype); - return rv; + const nsDOMClassInfoData *ci_data; + if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { + ci_data = &sClassInfoData[name_struct->mDOMClassInfoID]; + } else { + ci_data = name_struct->mData; + } + + return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data, + name_struct, nameSpaceManager, dot_prototype, + desc); } if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) { // We don't have a XPConnect prototype object, let ResolvePrototype create // one. return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nullptr, - name_struct, nameSpaceManager, nullptr, true, - did_resolve); + name_struct, nameSpaceManager, nullptr, desc); } if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) { @@ -2996,8 +3037,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, } return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data, - name_struct, nameSpaceManager, nullptr, true, - did_resolve); + name_struct, nameSpaceManager, nullptr, desc); } if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) { @@ -3009,15 +3049,12 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, JS::Rooted val(cx); rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), - false, &val); - NS_ENSURE_SUCCESS(rv, rv); - - rv = constructor->Install(cx, obj, val); + true, &val); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(val.isObject(), "Why didn't we get a JSObject?"); - *did_resolve = true; + FillPropertyDescriptor(desc, obj, 0, val); return NS_OK; } @@ -3066,13 +3103,9 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, return NS_ERROR_UNEXPECTED; } - bool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val, - JS_PropertyStub, JS_StrictPropertyStub, - JSPROP_ENUMERATE); + FillPropertyDescriptor(desc, obj, prop_val, false); - *did_resolve = true; - - return ok ? NS_OK : NS_ERROR_FAILURE; + return NS_OK; } return rv; @@ -3184,7 +3217,9 @@ const InterfaceShimEntry kInterfaceShimMap[] = { "nsIDOMXPathResult", "XPathResult" } }; static nsresult -DefineComponentsShim(JSContext *cx, JS::Handle global, nsPIDOMWindow *win) +LookupComponentsShim(JSContext *cx, JS::Handle global, + nsPIDOMWindow *win, + JS::MutableHandle desc) { // Keep track of how often this happens. Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true); @@ -3198,16 +3233,14 @@ DefineComponentsShim(JSContext *cx, JS::Handle global, nsPIDOMWindow // Create a fake Components object. JS::Rooted components(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), global)); NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY); - bool ok = JS_DefineProperty(cx, global, "Components", JS::ObjectValue(*components), - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE); - NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); // Create a fake interfaces object. JS::Rooted interfaces(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), global)); NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY); - ok = JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces), - JS_PropertyStub, JS_StrictPropertyStub, - JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); + bool ok = + JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces), + JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM @@ -3234,6 +3267,8 @@ DefineComponentsShim(JSContext *cx, JS::Handle global, nsPIDOMWindow NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); } + FillPropertyDescriptor(desc, global, JS::ObjectValue(*components), false); + return NS_OK; } @@ -3339,18 +3374,39 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // (and any relevant named constructor names) has been resolved before; // this allows us to avoid re-resolving in the Xray case if the property is // deleted by page script. - bool ignored; JS::Rooted global(cx, js::UncheckedUnwrap(obj, /* stopAtOuter = */ false)); JSAutoCompartment ac(cx, global); - nsresult rv = GlobalResolve(win, cx, global, id, &ignored); + JS::Rooted desc(cx); + nsresult rv = GlobalResolve(win, cx, global, id, &desc); NS_ENSURE_SUCCESS(rv, rv); + // If we have an object here, that means we resolved the property. + // But if the value is undefined, that means that GlobalResolve + // also already defined it, so we don't have to. + if (desc.object() && !desc.value().isUndefined() && + !JS_DefinePropertyById(cx, global, id, desc.value(), + desc.getter(), desc.setter(), + desc.attributes())) { + return NS_ERROR_FAILURE; + } } - bool did_resolve = false; - nsresult rv = GlobalResolve(win, cx, obj, id, &did_resolve); - NS_ENSURE_SUCCESS(rv, rv); - if (did_resolve) { + JS::Rooted desc(cx); + nsresult rv = GlobalResolve(win, cx, obj, id, &desc); + NS_ENSURE_SUCCESS(rv, rv); + if (desc.object()) { + // If we have an object here, that means we resolved the property. + // But if the value is undefined, that means that GlobalResolve + // also already defined it, so we don't have to. Note that in the + // Xray case we should never see undefined. + MOZ_ASSERT_IF(isXray, !desc.value().isUndefined()); + if (!desc.value().isUndefined() && + !JS_DefinePropertyById(cx, obj, id, desc.value(), + desc.getter(), desc.setter(), + desc.attributes())) { + return NS_ERROR_FAILURE; + } + *objp = obj; return NS_OK; } diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index f0ab3c3f9a5f..d4d586127844 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -256,7 +256,7 @@ protected: static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, JS::Handle obj, JS::Handle id, - bool *did_resolve); + JS::MutableHandle desc); public: NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx, diff --git a/dom/bindings/DOMJSProxyHandler.h b/dom/bindings/DOMJSProxyHandler.h index 891f4d87533a..0c442c9768e1 100644 --- a/dom/bindings/DOMJSProxyHandler.h +++ b/dom/bindings/DOMJSProxyHandler.h @@ -165,6 +165,18 @@ FillPropertyDescriptor(JS::MutableHandle desc, JSObject* o FillPropertyDescriptor(desc, obj, readonly); } +inline void +FillPropertyDescriptor(JS::MutableHandle desc, + JSObject* obj, unsigned attributes, JS::Value v) +{ + desc.object().set(obj); + desc.value().set(v); + desc.setAttributes(attributes); + desc.setGetter(nullptr); + desc.setSetter(nullptr); + desc.setShortId(0); +} + } // namespace dom } // namespace mozilla From c044a6c065e15431f4842a057565530da69a4ad4 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:25 -0800 Subject: [PATCH 10/88] Bug 945416 part 4. Introduce a DoNewResolve method on nsGlobalWindow and call it from nsWindowSH::NewResolve. r=peterv --- dom/base/nsDOMClassInfo.cpp | 14 ++++++++------ dom/base/nsDOMClassInfo.h | 1 + dom/base/nsGlobalWindow.cpp | 19 +++++++++++++++++++ dom/base/nsGlobalWindow.h | 4 ++++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 974a16be61d4..fc848ce7ff47 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -3378,8 +3378,9 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, js::UncheckedUnwrap(obj, /* stopAtOuter = */ false)); JSAutoCompartment ac(cx, global); JS::Rooted desc(cx); - nsresult rv = GlobalResolve(win, cx, global, id, &desc); - NS_ENSURE_SUCCESS(rv, rv); + if (!win->DoNewResolve(cx, global, id, &desc)) { + return NS_ERROR_FAILURE; + } // If we have an object here, that means we resolved the property. // But if the value is undefined, that means that GlobalResolve // also already defined it, so we don't have to. @@ -3392,8 +3393,9 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } JS::Rooted desc(cx); - nsresult rv = GlobalResolve(win, cx, obj, id, &desc); - NS_ENSURE_SUCCESS(rv, rv); + if (!win->DoNewResolve(cx, obj, id, &desc)) { + return NS_ERROR_FAILURE; + } if (desc.object()) { // If we have an object here, that means we resolved the property. // But if the value is undefined, that means that GlobalResolve @@ -3414,8 +3416,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, if (!(flags & JSRESOLVE_ASSIGNING) && sDocument_id == id) { nsCOMPtr document = win->GetDoc(); JS::Rooted v(cx); - rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), document, document, - &NS_GET_IID(nsIDOMDocument), &v, false); + nsresult rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), document, document, + &NS_GET_IID(nsIDOMDocument), &v, false); NS_ENSURE_SUCCESS(rv, rv); // nsIDocument::WrapObject will handle defining the property. diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index d4d586127844..70beca7a75d8 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -258,6 +258,7 @@ protected: JS::Handle obj, JS::Handle id, JS::MutableHandle desc); + friend class nsGlobalWindow; public: NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index bde85d7d8aaf..a65f6592bdf3 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4052,6 +4052,25 @@ nsGlobalWindow::GetSupportedNames(nsTArray& aNames) } } +bool +nsGlobalWindow::DoNewResolve(JSContext* aCx, JS::Handle aObj, + JS::Handle aId, + JS::MutableHandle aDesc) +{ + MOZ_ASSERT(IsInnerWindow()); + + if (!JSID_IS_STRING(aId)) { + return true; + } + + nsresult rv = nsWindowSH::GlobalResolve(this, aCx, aObj, aId, aDesc); + if (NS_FAILED(rv)) { + return Throw(aCx, rv); + } + + return true; +} + nsIDOMOfflineResourceList* nsGlobalWindow::GetApplicationCache(ErrorResult& aError) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index b703c3cb6ec4..a9df979ad0d7 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -475,6 +475,10 @@ public: void GetSupportedNames(nsTArray& aNames); + bool DoNewResolve(JSContext* aCx, JS::Handle aObj, + JS::Handle aId, + JS::MutableHandle aDesc); + // Object Management nsGlobalWindow(nsGlobalWindow *aOuterWindow); From 4a2e39fc36db13beb2826b7926cef07c1b0fc0bd Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:27 -0800 Subject: [PATCH 11/88] Bug 945416 part 5. Implement nsGlobalWindow::GetOwnPropertyNames and flag the interface as NeedNewResolve. r=peterv --- dom/base/nsGlobalWindow.cpp | 19 +++++++++++++++++++ dom/base/nsGlobalWindow.h | 3 +++ dom/webidl/Window.webidl | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index a65f6592bdf3..8050d9659ba5 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -34,6 +34,7 @@ #include "nsIScriptContext.h" #include "nsIScriptTimeoutHandler.h" #include "nsIController.h" +#include "nsScriptNameSpaceManager.h" // Helper Classes #include "nsJSUtils.h" @@ -4071,6 +4072,24 @@ nsGlobalWindow::DoNewResolve(JSContext* aCx, JS::Handle aObj, return true; } +static PLDHashOperator +EnumerateGlobalName(const nsAString& aName, void* aClosure) +{ + nsTArray* arr = static_cast*>(aClosure); + arr->AppendElement(aName); + return PL_DHASH_NEXT; +} + +void +nsGlobalWindow::GetOwnPropertyNames(JSContext* aCx, nsTArray& aNames, + ErrorResult& aRv) +{ + nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager(); + if (nameSpaceManager) { + nameSpaceManager->EnumerateGlobalNames(EnumerateGlobalName, &aNames); + } +} + nsIDOMOfflineResourceList* nsGlobalWindow::GetApplicationCache(ErrorResult& aError) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index a9df979ad0d7..24057e7ae1ee 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -479,6 +479,9 @@ public: JS::Handle aId, JS::MutableHandle aDesc); + void GetOwnPropertyNames(JSContext* aCx, nsTArray& aNames, + mozilla::ErrorResult& aRv); + // Object Management nsGlobalWindow(nsGlobalWindow *aOuterWindow); diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index cdeca1e6e023..b783e5a7c70c 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -22,7 +22,7 @@ interface Pkcs11; typedef any Transferable; // http://www.whatwg.org/specs/web-apps/current-work/ -[Global] +[Global, NeedNewResolve] /*sealed*/ interface Window : EventTarget { // the current browsing context [Unforgeable, Throws, From 9363c07116f38a548ec8587de52d95ee8387a6ab Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:33 -0800 Subject: [PATCH 12/88] Bug 945416 part 6. Fix the resolve/enumerate hooks in WebIDL bindings in the [Global] case to handle standard classes. r=peterv --- dom/bindings/BindingUtils.cpp | 2 +- dom/bindings/BindingUtils.h | 2 +- dom/bindings/Codegen.py | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index fd0ce3f04039..baa7e45755d3 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -2168,7 +2168,7 @@ FinalizeGlobal(JSFreeOp* aFreeOp, JSObject* aObj) bool ResolveGlobal(JSContext* aCx, JS::Handle aObj, - JS::MutableHandle aId, unsigned aFlags, + JS::Handle aId, unsigned aFlags, JS::MutableHandle aObjp) { bool resolved; diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 0e732d2e1842..0ec6fafcea49 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -2357,7 +2357,7 @@ FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj); bool ResolveGlobal(JSContext* aCx, JS::Handle aObj, - JS::MutableHandle aId, unsigned aFlags, + JS::Handle aId, unsigned aFlags, JS::MutableHandle aObjp); bool diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 78005a60137c..36e3831ea80f 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -6021,6 +6021,20 @@ class CGNewResolveHook(CGAbstractBindingMethod): "objp.set(obj);\n" "return true;")) + def definition_body(self): + if self.descriptor.interface.getExtendedAttribute("Global"): + # Resolve standard classes + prefix = CGIndenter(CGGeneric( + "if (!ResolveGlobal(cx, obj, id, flags, objp)) {\n" + " return false;\n" + "}\n" + "if (objp) {\n" + " return true;\n" + "}\n\n")).define() + else: + prefix = "" + return prefix + CGAbstractBindingMethod.definition_body(self) + class CGEnumerateHook(CGAbstractBindingMethod): """ Enumerate hook for objects with custom hooks. @@ -6052,6 +6066,17 @@ class CGEnumerateHook(CGAbstractBindingMethod): "}\n" "return true;")) + def definition_body(self): + if self.descriptor.interface.getExtendedAttribute("Global"): + # Enumerate standard classes + prefix = CGIndenter(CGGeneric( + "if (!EnumerateGlobal(cx, obj)) {\n" + " return false;\n" + "}\n\n")).define() + else: + prefix = "" + return prefix + CGAbstractBindingMethod.definition_body(self) + class CppKeywords(): """ A class for checking if method names declared in webidl From b819d8db86a03fac7dbf2bba31c3c64992507eae Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:33:50 -0800 Subject: [PATCH 13/88] Bug 965477. Enter the compartment of obj in ClearCached*Value in the StoreInSlot case. r=bholley --- dom/bindings/Codegen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 36e3831ea80f..5ced4d5426c1 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2477,6 +2477,7 @@ class CGClearCachedValueMethod(CGAbstractMethod): regetMember = ("\n" "JS::Rooted temp(aCx);\n" "JSJitGetterCallArgs args(&temp);\n" + "JSAutoCompartment ac(aCx, obj);\n" "if (!get_%s(aCx, obj, aObject, args)) {\n" " js::SetReservedSlot(obj, %s, oldValue);\n" " nsJSUtils::ReportPendingException(aCx);\n" From 0ec24be88bb28fe17e9edc38580d6c65f1131d71 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:34:25 -0800 Subject: [PATCH 14/88] Bug 965144. Make the Window-specific bits of XrayWrapper work with WebIDL windows. r=bholley --- js/xpconnect/wrappers/XrayWrapper.cpp | 74 ++++++++++++++++++++------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index efa48edc2198..7b7d15650302 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -1,3 +1,4 @@ + /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=99 ft=cpp: * @@ -21,6 +22,7 @@ #include "nsJSUtils.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/WindowBinding.h" #include "nsGlobalWindow.h" using namespace mozilla::dom; @@ -663,20 +665,26 @@ XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, HandleOb return true; } -template -static T* -As(JSObject *wrapper) +static nsGlobalWindow* +AsWindow(JSContext *cx, JSObject *wrapper) { - XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper); - nsCOMPtr native = do_QueryWrappedNative(wn); - return native; + nsGlobalWindow* win; + // We want to use our target object here, since we don't want to be + // doing a security check while unwrapping. + JSObject* target = XrayTraits::getTargetObject(wrapper); + nsresult rv = UNWRAP_OBJECT(Window, target, win); + if (NS_SUCCEEDED(rv)) + return win; + + nsCOMPtr piWin = do_QueryInterface( + nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, target)); + return static_cast(piWin.get()); } -template static bool -Is(JSObject *wrapper) +IsWindow(JSContext *cx, JSObject *wrapper) { - return !!As(wrapper); + return !!AsWindow(cx, wrapper); } static nsQueryInterface @@ -721,7 +729,7 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr nsGlobalWindow *win = nullptr; if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONTROLLERS) && AccessCheck::isChrome(wrapper) && - (win = static_cast(As(wrapper)))) + (win = AsWindow(cx, wrapper))) { nsCOMPtr c; nsresult rv = win->GetControllers(getter_AddRefs(c)); @@ -889,8 +897,7 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper // Check for indexed access on a window. int32_t index = GetArrayIndexFromId(cx, id); if (IsArrayIndex(index)) { - nsGlobalWindow* win = - static_cast(As(wrapper)); + nsGlobalWindow* win = AsWindow(cx, wrapper); // Note: As() unwraps outer windows to get to the inner window. if (win) { bool unused; @@ -904,7 +911,7 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper return xpc::Throw(cx, NS_ERROR_FAILURE); } desc.value().setObject(*obj); - mozilla::dom::FillPropertyDescriptor(desc, wrapper, true); + FillPropertyDescriptor(desc, wrapper, true); return JS_WrapPropertyDescriptor(cx, desc); } } @@ -979,7 +986,7 @@ XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, // Check for an indexed property on a Window. If that's happening, do // nothing but claim we defined it so it won't get added as an expando. int32_t index = GetArrayIndexFromId(cx, id); - if (IsArrayIndex(index) && Is(wrapper)) { + if (IsArrayIndex(index) && IsWindow(cx, wrapper)) { *defined = true; return true; } @@ -1102,6 +1109,29 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObjec if (!ok || desc.object()) return ok; + // Check for indexed access on a window. + int32_t index = GetArrayIndexFromId(cx, id); + if (IsArrayIndex(index)) { + nsGlobalWindow* win = AsWindow(cx, wrapper); + // Note: As() unwraps outer windows to get to the inner window. + if (win) { + bool unused; + nsCOMPtr subframe = win->IndexedGetter(index, unused); + if (subframe) { + nsGlobalWindow* global = static_cast(subframe.get()); + global->EnsureInnerWindow(); + JSObject* obj = global->FastGetGlobalJSObject(); + if (MOZ_UNLIKELY(!obj)) { + // It's gone? + return xpc::Throw(cx, NS_ERROR_FAILURE); + } + desc.value().setObject(*obj); + FillPropertyDescriptor(desc, wrapper, true); + return JS_WrapPropertyDescriptor(cx, desc); + } + } + } + RootedObject obj(cx, getTargetObject(wrapper)); if (!XrayResolveOwnProperty(cx, wrapper, obj, id, desc, flags)) return false; @@ -1119,6 +1149,14 @@ DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, if (!existingDesc.object()) return true; + // Check for an indexed property on a Window. If that's happening, do + // nothing but claim we defined it so it won't get added as an expando. + int32_t index = GetArrayIndexFromId(cx, id); + if (IsArrayIndex(index) && IsWindow(cx, wrapper)) { + *defined = true; + return true; + } + JS::Rooted obj(cx, getTargetObject(wrapper)); return XrayDefineProperty(cx, wrapper, obj, id, desc, defined); } @@ -1470,9 +1508,8 @@ XrayWrapper::getPropertyDescriptor(JSContext *cx, HandleObject wra // named access. So we just handle it separately here. nsGlobalWindow *win = nullptr; if (!desc.object() && - (Traits::Type == XrayForWrappedNative) && JSID_IS_STRING(id) && - (win = static_cast(As(wrapper)))) + (win = AsWindow(cx, wrapper))) { nsDependentJSString name(id); nsCOMPtr childDOMWin = win->GetChildWindow(name); @@ -1481,9 +1518,8 @@ XrayWrapper::getPropertyDescriptor(JSContext *cx, HandleObject wra JSObject *childObj = cwin->FastGetGlobalJSObject(); if (MOZ_UNLIKELY(!childObj)) return xpc::Throw(cx, NS_ERROR_FAILURE); - mozilla::dom::FillPropertyDescriptor(desc, wrapper, - ObjectValue(*childObj), - /* readOnly = */ true); + FillPropertyDescriptor(desc, wrapper, ObjectValue(*childObj), + /* readOnly = */ true); return JS_WrapPropertyDescriptor(cx, desc); } } From e153d57ee249825551b5b7bf1926ada9dc0d8091 Mon Sep 17 00:00:00 2001 From: Oleg Romashin Date: Wed, 29 Jan 2014 23:01:16 -0800 Subject: [PATCH 15/88] Bug 840874 - Get Skia backend working on Qt port. r=bas --- gfx/thebes/gfxAndroidPlatform.cpp | 9 +-------- gfx/thebes/gfxPlatform.cpp | 13 +++++++++++++ gfx/thebes/gfxPlatform.h | 3 +++ gfx/thebes/gfxPlatformGtk.cpp | 11 +---------- gfx/thebes/gfxQtPlatform.cpp | 9 +++++++++ gfx/thebes/gfxQtPlatform.h | 3 +++ 6 files changed, 30 insertions(+), 18 deletions(-) diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp index a987d05f351d..001a32fc23a7 100644 --- a/gfx/thebes/gfxAndroidPlatform.cpp +++ b/gfx/thebes/gfxAndroidPlatform.cpp @@ -354,14 +354,7 @@ gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, TemporaryRef gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { - NativeFont nativeFont; - if (aTarget->GetType() == BackendType::CAIRO || aTarget->GetType() == BackendType::SKIA) { - nativeFont.mType = NativeFontType::CAIRO_FONT_FACE; - nativeFont.mFont = aFont->GetCairoScaledFont(); - return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize()); - } - - return nullptr; + return GetScaledFontForFontWithCairoSkia(aTarget, aFont); } bool diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index f856c89e95fe..bdb0f43b9fcc 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -2263,3 +2263,16 @@ gfxPlatform::AsyncVideoEnabled() return Preferences::GetBool("layers.async-video.enabled", false); #endif } + +TemporaryRef +gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont) +{ + NativeFont nativeFont; + if (aTarget->GetType() == BackendType::CAIRO || aTarget->GetType() == BackendType::SKIA) { + nativeFont.mType = NativeFontType::CAIRO_FONT_FACE; + nativeFont.mFont = aFont->GetCairoScaledFont(); + return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize()); + } + + return nullptr; +} diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 79c0266f0017..fd11c39900e6 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -686,6 +686,9 @@ protected: return mContentBackend; } + static mozilla::TemporaryRef + GetScaledFontForFontWithCairoSkia(mozilla::gfx::DrawTarget* aTarget, gfxFont* aFont); + int8_t mAllowDownloadableFonts; int8_t mGraphiteShapingEnabled; int8_t mOpenTypeSVGEnabled; diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 7d1b0e75c579..375c04775e2f 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -452,14 +452,5 @@ gfxPlatformGtk::GetGdkDrawable(cairo_surface_t *target) TemporaryRef gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) { - NativeFont nativeFont; - - if (aTarget->GetType() == BackendType::CAIRO || aTarget->GetType() == BackendType::SKIA) { - nativeFont.mType = NativeFontType::CAIRO_FONT_FACE; - nativeFont.mFont = aFont->GetCairoScaledFont(); - return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize()); - } - - return nullptr; - + return GetScaledFontForFontWithCairoSkia(aTarget, aFont); } diff --git a/gfx/thebes/gfxQtPlatform.cpp b/gfx/thebes/gfxQtPlatform.cpp index 25a652c04f9c..cbcea267b746 100644 --- a/gfx/thebes/gfxQtPlatform.cpp +++ b/gfx/thebes/gfxQtPlatform.cpp @@ -109,6 +109,10 @@ gfxQtPlatform::gfxQtPlatform() if (pixmap.paintEngine()) sDefaultQtPaintEngineType = pixmap.paintEngine()->type(); #endif + uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA); + uint32_t contentMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA); + InitBackendPrefs(canvasMask, BackendType::CAIRO, + contentMask, BackendType::CAIRO); } gfxQtPlatform::~gfxQtPlatform() @@ -306,3 +310,8 @@ gfxQtPlatform::GetScreenDepth() const return mScreenDepth; } +TemporaryRef +gfxQtPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont* aFont) +{ + return GetScaledFontForFontWithCairoSkia(aTarget, aFont); +} diff --git a/gfx/thebes/gfxQtPlatform.h b/gfx/thebes/gfxQtPlatform.h index a8fd572fa0ac..e4810bd363a8 100644 --- a/gfx/thebes/gfxQtPlatform.h +++ b/gfx/thebes/gfxQtPlatform.h @@ -41,6 +41,9 @@ public: already_AddRefed CreateOffscreenSurface(const gfxIntSize& size, gfxContentType contentType); + mozilla::TemporaryRef + GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont); + nsresult GetFontList(nsIAtom *aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts); From 4b41dadb7e5d1fc9521e3d2dfca0428db86202c2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 16 Jan 2014 00:08:20 +1300 Subject: [PATCH 16/88] Bug 952893. Part 1: Block the AudioDestinationNode when it's the only node in the AudioContext. r=padenot,karlt --- content/media/AudioNodeStream.cpp | 7 +- content/media/AudioNodeStream.h | 5 +- .../media/webaudio/AudioBufferSourceNode.cpp | 5 +- content/media/webaudio/AudioContext.cpp | 26 ++++++- content/media/webaudio/AudioContext.h | 18 +++++ .../media/webaudio/AudioDestinationNode.cpp | 75 +++++++++++++++++++ content/media/webaudio/AudioDestinationNode.h | 15 ++++ content/media/webaudio/AudioNode.cpp | 7 ++ content/media/webaudio/AudioParam.h | 17 +++-- content/media/webaudio/OscillatorNode.cpp | 6 +- content/media/webaudio/moz.build | 1 + content/media/webaudio/test/webaudio.js | 9 ++- 12 files changed, 170 insertions(+), 21 deletions(-) diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index 4be1490f69f2..02147129a948 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -10,6 +10,7 @@ #include "ThreeDPoint.h" #include "AudioChannelFormat.h" #include "AudioParamTimeline.h" +#include "AudioContext.h" using namespace mozilla::dom; @@ -30,7 +31,7 @@ AudioNodeStream::~AudioNodeStream() } void -AudioNodeStream::SetStreamTimeParameter(uint32_t aIndex, MediaStream* aRelativeToStream, +AudioNodeStream::SetStreamTimeParameter(uint32_t aIndex, AudioContext* aContext, double aStreamTime) { class Message : public ControlMessage { @@ -50,7 +51,9 @@ AudioNodeStream::SetStreamTimeParameter(uint32_t aIndex, MediaStream* aRelativeT }; MOZ_ASSERT(this); - GraphImpl()->AppendMessage(new Message(this, aIndex, aRelativeToStream, aStreamTime)); + GraphImpl()->AppendMessage(new Message(this, aIndex, + aContext->DestinationStream(), + aContext->DOMTimeToStreamTime(aStreamTime))); } void diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h index b490a0c30b4a..ca768fe1d9bf 100644 --- a/content/media/AudioNodeStream.h +++ b/content/media/AudioNodeStream.h @@ -16,6 +16,7 @@ namespace dom { struct ThreeDPoint; class AudioParamTimeline; class DelayNodeEngine; +class AudioContext; } class ThreadSharedFloatArrayBufferList; @@ -33,6 +34,8 @@ class AudioNodeEngine; */ class AudioNodeStream : public ProcessedMediaStream { public: + typedef mozilla::dom::AudioContext AudioContext; + enum { AUDIO_TRACK = 1 }; typedef nsAutoTArray OutputChunks; @@ -66,7 +69,7 @@ public: * Sets a parameter that's a time relative to some stream's played time. * This time is converted to a time relative to this stream when it's set. */ - void SetStreamTimeParameter(uint32_t aIndex, MediaStream* aRelativeToStream, + void SetStreamTimeParameter(uint32_t aIndex, AudioContext* aContext, double aStreamTime); void SetDoubleParameter(uint32_t aIndex, double aValue); void SetInt32Parameter(uint32_t aIndex, int32_t aValue); diff --git a/content/media/webaudio/AudioBufferSourceNode.cpp b/content/media/webaudio/AudioBufferSourceNode.cpp index c322713345e2..ea5d3812d14c 100644 --- a/content/media/webaudio/AudioBufferSourceNode.cpp +++ b/content/media/webaudio/AudioBufferSourceNode.cpp @@ -532,7 +532,7 @@ AudioBufferSourceNode::Start(double aWhen, double aOffset, // Don't set parameter unnecessarily if (aWhen > 0.0) { - ns->SetStreamTimeParameter(START, Context()->DestinationStream(), aWhen); + ns->SetStreamTimeParameter(START, Context(), aWhen); } MarkActive(); @@ -616,8 +616,7 @@ AudioBufferSourceNode::Stop(double aWhen, ErrorResult& aRv) return; } - ns->SetStreamTimeParameter(STOP, Context()->DestinationStream(), - std::max(0.0, aWhen)); + ns->SetStreamTimeParameter(STOP, Context(), std::max(0.0, aWhen)); } void diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index d3b5d5f4e4be..773cab32ba52 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -84,6 +84,7 @@ AudioContext::AudioContext(nsPIDOMWindow* aWindow, : nsDOMEventTargetHelper(aWindow) , mSampleRate(GetSampleRateForAudioContext(aIsOffline, aSampleRate)) , mNumberOfChannels(aNumberOfChannels) + , mNodeCount(0) , mIsOffline(aIsOffline) , mIsStarted(!aIsOffline) , mIsShutDown(false) @@ -95,6 +96,10 @@ AudioContext::AudioContext(nsPIDOMWindow* aWindow, mDestination = new AudioDestinationNode(this, aIsOffline, aNumberOfChannels, aLength, aSampleRate); mDestination->Stream()->AddAudioOutput(&gWebAudioOutputKey); + // We skip calling SetIsOnlyNodeForContext during mDestination's constructor, + // because we can only call SetIsOnlyNodeForContext after mDestination has + // been set up. + mDestination->SetIsOnlyNodeForContext(true); } AudioContext::~AudioContext() @@ -543,7 +548,8 @@ AudioContext::DestinationStream() const double AudioContext::CurrentTime() const { - return MediaTimeToSeconds(Destination()->Stream()->GetCurrentTime()); + return MediaTimeToSeconds(Destination()->Stream()->GetCurrentTime()) + + ExtraCurrentTime(); } void @@ -589,6 +595,18 @@ AudioContext::Resume() } } +void +AudioContext::UpdateNodeCount(int32_t aDelta) +{ + bool firstNode = mNodeCount == 0; + mNodeCount += aDelta; + MOZ_ASSERT(mNodeCount >= 0); + // mDestinationNode may be null when we're destroying nodes unlinked by CC + if (!firstNode && mDestination) { + mDestination->SetIsOnlyNodeForContext(mNodeCount == 1); + } +} + JSContext* AudioContext::GetJSContext() const { @@ -679,5 +697,11 @@ AudioContext::CollectReports(nsIHandleReportCallback* aHandleReport, amount, "Memory used by AudioContext objects (Web Audio)."); } +double +AudioContext::ExtraCurrentTime() const +{ + return mDestination->ExtraCurrentTime(); +} + } } diff --git a/content/media/webaudio/AudioContext.h b/content/media/webaudio/AudioContext.h index d03aa3716944..88e6aa7b38e9 100644 --- a/content/media/webaudio/AudioContext.h +++ b/content/media/webaudio/AudioContext.h @@ -246,7 +246,23 @@ public: AudioChannel MozAudioChannelType() const; void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv); + void UpdateNodeCount(int32_t aDelta); + + double DOMTimeToStreamTime(double aTime) const + { + return aTime - ExtraCurrentTime(); + } + private: + /** + * Returns the amount of extra time added to the current time of the + * AudioDestinationNode's MediaStream to get this AudioContext's currentTime. + * Must be subtracted from all DOM API parameter times that are on the same + * timeline as AudioContext's currentTime to get times we can pass to the + * MediaStreamGraph. + */ + double ExtraCurrentTime() const; + void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob); void ShutdownDecoder(); @@ -272,6 +288,8 @@ private: nsTHashtable > mPannerNodes; // Number of channels passed in the OfflineAudioContext ctor. uint32_t mNumberOfChannels; + // Number of nodes that currently exist for this AudioContext + int32_t mNodeCount; bool mIsOffline; bool mIsStarted; bool mIsShutDown; diff --git a/content/media/webaudio/AudioDestinationNode.cpp b/content/media/webaudio/AudioDestinationNode.cpp index 464878969ca8..9ce18c21d234 100644 --- a/content/media/webaudio/AudioDestinationNode.cpp +++ b/content/media/webaudio/AudioDestinationNode.cpp @@ -17,6 +17,8 @@ #include "nsIPermissionManager.h" #include "nsIScriptObjectPrincipal.h" #include "nsServiceManagerUtils.h" +#include "nsIAppShell.h" +#include "nsWidgetsCID.h" namespace mozilla { namespace dom { @@ -217,6 +219,9 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext, , mAudioChannel(AudioChannel::Normal) , mIsOffline(aIsOffline) , mHasFinished(false) + , mExtraCurrentTime(0) + , mExtraCurrentTimeSinceLastStartedBlocking(0) + , mExtraCurrentTimeUpdatedSinceLastStableState(false) { MediaStreamGraph* graph = aIsOffline ? MediaStreamGraph::CreateNonRealtimeInstance() : @@ -486,6 +491,76 @@ AudioDestinationNode::CreateAudioChannelAgent() mAudioChannelAgent->StartPlaying(&state); SetCanPlay(state == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL); } + +void +AudioDestinationNode::NotifyStableState() +{ + mExtraCurrentTimeUpdatedSinceLastStableState = false; +} + +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + +void +AudioDestinationNode::ScheduleStableStateNotification() +{ + nsCOMPtr appShell = do_GetService(kAppShellCID); + if (appShell) { + nsCOMPtr event = + NS_NewRunnableMethod(this, &AudioDestinationNode::NotifyStableState); + appShell->RunInStableState(event); + } +} + +double +AudioDestinationNode::ExtraCurrentTime() +{ + if (!mStartedBlockingDueToBeingOnlyNode.IsNull() && + !mExtraCurrentTimeUpdatedSinceLastStableState) { + mExtraCurrentTimeUpdatedSinceLastStableState = true; + mExtraCurrentTimeSinceLastStartedBlocking = + (TimeStamp::Now() - mStartedBlockingDueToBeingOnlyNode).ToSeconds(); + ScheduleStableStateNotification(); + } + return mExtraCurrentTime + mExtraCurrentTimeSinceLastStartedBlocking; +} + +void +AudioDestinationNode::SetIsOnlyNodeForContext(bool aIsOnlyNode) +{ + if (!mStartedBlockingDueToBeingOnlyNode.IsNull() == aIsOnlyNode) { + // Nothing changed. + return; + } + + if (!mStream) { + // DestroyMediaStream has been called, presumably during CC Unlink(). + return; + } + + if (mIsOffline) { + // Don't block the destination stream for offline AudioContexts, since + // we expect the zero data produced when there are no other nodes to + // show up in its result buffer. Also, we would get confused by adding + // ExtraCurrentTime before StartRendering has even been called. + return; + } + + if (aIsOnlyNode) { + mStream->ChangeExplicitBlockerCount(1); + mStartedBlockingDueToBeingOnlyNode = TimeStamp::Now(); + mExtraCurrentTimeSinceLastStartedBlocking = 0; + // Don't do an update of mExtraCurrentTimeSinceLastStartedBlocking until the next stable state. + mExtraCurrentTimeUpdatedSinceLastStableState = true; + ScheduleStableStateNotification(); + } else { + // Force update of mExtraCurrentTimeSinceLastStartedBlocking if necessary + ExtraCurrentTime(); + mExtraCurrentTime += mExtraCurrentTimeSinceLastStartedBlocking; + mStream->ChangeExplicitBlockerCount(-1); + mStartedBlockingDueToBeingOnlyNode = TimeStamp(); + } +} + } } diff --git a/content/media/webaudio/AudioDestinationNode.h b/content/media/webaudio/AudioDestinationNode.h index 0ad575613011..3b78eec53d31 100644 --- a/content/media/webaudio/AudioDestinationNode.h +++ b/content/media/webaudio/AudioDestinationNode.h @@ -70,12 +70,22 @@ public: virtual void NotifyMainThreadStateChanged() MOZ_OVERRIDE; void FireOfflineCompletionEvent(); + // An amount that should be added to the MediaStream's current time to + // get the AudioContext.currentTime. + double ExtraCurrentTime(); + + // When aIsOnlyNode is true, this is the only node for the AudioContext. + void SetIsOnlyNodeForContext(bool aIsOnlyNode); + private: bool CheckAudioChannelPermissions(AudioChannel aValue); void CreateAudioChannelAgent(); void SetCanPlay(bool aCanPlay); + void NotifyStableState(); + void ScheduleStableStateNotification(); + SelfReference mOfflineRenderingRef; uint32_t mFramesToProduce; @@ -85,6 +95,11 @@ private: AudioChannel mAudioChannel; bool mIsOffline; bool mHasFinished; + + TimeStamp mStartedBlockingDueToBeingOnlyNode; + double mExtraCurrentTime; + double mExtraCurrentTimeSinceLastStartedBlocking; + bool mExtraCurrentTimeUpdatedSinceLastStableState; }; } diff --git a/content/media/webaudio/AudioNode.cpp b/content/media/webaudio/AudioNode.cpp index e98aa37ee015..f432ff3aa9ad 100644 --- a/content/media/webaudio/AudioNode.cpp +++ b/content/media/webaudio/AudioNode.cpp @@ -19,6 +19,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(AudioNode) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper) tmp->DisconnectFromGraph(); + tmp->mContext->UpdateNodeCount(-1); NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputParams) @@ -58,6 +59,9 @@ AudioNode::AudioNode(AudioContext* aContext, , mChannelInterpretation(aChannelInterpretation) { MOZ_ASSERT(aContext); + nsDOMEventTargetHelper::BindToOwner(aContext->GetParentObject()); + SetIsDOMBinding(); + aContext->UpdateNodeCount(1); } AudioNode::~AudioNode() @@ -65,6 +69,9 @@ AudioNode::~AudioNode() MOZ_ASSERT(mInputNodes.IsEmpty()); MOZ_ASSERT(mOutputNodes.IsEmpty()); MOZ_ASSERT(mOutputParams.IsEmpty()); + if (mContext) { + mContext->UpdateNodeCount(-1); + } } template diff --git a/content/media/webaudio/AudioParam.h b/content/media/webaudio/AudioParam.h index 877ee4a01f99..b875f3073593 100644 --- a/content/media/webaudio/AudioParam.h +++ b/content/media/webaudio/AudioParam.h @@ -42,6 +42,11 @@ public: return mNode->Context(); } + double DOMTimeToStreamTime(double aTime) const + { + return mNode->Context()->DOMTimeToStreamTime(aTime); + } + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; @@ -54,7 +59,7 @@ public: return; } AudioParamTimeline::SetValueCurveAtTime(aValues.Data(), aValues.Length(), - aStartTime, aDuration, aRv); + DOMTimeToStreamTime(aStartTime), aDuration, aRv); mCallback(mNode); } @@ -76,7 +81,7 @@ public: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } - AudioParamTimeline::SetValueAtTime(aValue, aStartTime, aRv); + AudioParamTimeline::SetValueAtTime(aValue, DOMTimeToStreamTime(aStartTime), aRv); mCallback(mNode); } void LinearRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv) @@ -85,7 +90,7 @@ public: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } - AudioParamTimeline::LinearRampToValueAtTime(aValue, aEndTime, aRv); + AudioParamTimeline::LinearRampToValueAtTime(aValue, DOMTimeToStreamTime(aEndTime), aRv); mCallback(mNode); } void ExponentialRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv) @@ -94,7 +99,7 @@ public: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } - AudioParamTimeline::ExponentialRampToValueAtTime(aValue, aEndTime, aRv); + AudioParamTimeline::ExponentialRampToValueAtTime(aValue, DOMTimeToStreamTime(aEndTime), aRv); mCallback(mNode); } void SetTargetAtTime(float aTarget, double aStartTime, double aTimeConstant, ErrorResult& aRv) @@ -104,7 +109,7 @@ public: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } - AudioParamTimeline::SetTargetAtTime(aTarget, aStartTime, aTimeConstant, aRv); + AudioParamTimeline::SetTargetAtTime(aTarget, DOMTimeToStreamTime(aStartTime), aTimeConstant, aRv); mCallback(mNode); } void SetTargetValueAtTime(float aTarget, double aStartTime, double aTimeConstant, ErrorResult& aRv) @@ -117,7 +122,7 @@ public: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } - AudioParamTimeline::CancelScheduledValues(aStartTime); + AudioParamTimeline::CancelScheduledValues(DOMTimeToStreamTime(aStartTime)); mCallback(mNode); } diff --git a/content/media/webaudio/OscillatorNode.cpp b/content/media/webaudio/OscillatorNode.cpp index a43f4b517e7b..d3b731239c28 100644 --- a/content/media/webaudio/OscillatorNode.cpp +++ b/content/media/webaudio/OscillatorNode.cpp @@ -578,8 +578,7 @@ OscillatorNode::Start(double aWhen, ErrorResult& aRv) // TODO: Perhaps we need to do more here. ns->SetStreamTimeParameter(OscillatorNodeEngine::START, - Context()->DestinationStream(), - aWhen); + Context(), aWhen); MarkActive(); } @@ -605,8 +604,7 @@ OscillatorNode::Stop(double aWhen, ErrorResult& aRv) // TODO: Perhaps we need to do more here. ns->SetStreamTimeParameter(OscillatorNodeEngine::STOP, - Context()->DestinationStream(), - std::max(0.0, aWhen)); + Context(), std::max(0.0, aWhen)); } void diff --git a/content/media/webaudio/moz.build b/content/media/webaudio/moz.build index 4599cc522c2f..5a609d6039f8 100644 --- a/content/media/webaudio/moz.build +++ b/content/media/webaudio/moz.build @@ -9,6 +9,7 @@ PARALLEL_DIRS += ['blink', 'test'] TEST_TOOL_DIRS += ['compiledtest'] EXPORTS += [ + 'AudioContext.h', 'AudioParamTimeline.h', 'MediaBufferDecoder.h', 'ThreeDPoint.h', diff --git a/content/media/webaudio/test/webaudio.js b/content/media/webaudio/test/webaudio.js index 146aa9ae005f..ee81ba3c2739 100644 --- a/content/media/webaudio/test/webaudio.js +++ b/content/media/webaudio/test/webaudio.js @@ -53,10 +53,11 @@ function compareChannels(buf1, buf2, } }; - is(difference, 0, "Found " + difference + " different samples, maxDifference: " + - maxDifference + ", first bad index: " + firstBadIndex + - " with source offset " + sourceOffset + " and destination offset " + - destOffset); + is(difference, 0, "maxDifference: " + maxDifference + + ", first bad index: " + firstBadIndex + + " with test-data offset " + sourceOffset + " and expected-data offset " + + destOffset + "; corresponding values " + buf1[firstBadIndex + sourceOffset] + + " and " + buf2[firstBadIndex + destOffset] + " --- differences"); } function compareBuffers(got, expected) { From 1161223f59ddc8e6ba60b5b386044181fedc30c5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 16 Jan 2014 00:13:07 +1300 Subject: [PATCH 17/88] Bug 952893. Part 2: When all streams in the MSG are blocked, allow the MSG to suspend indefinitely and pause AudioStream outputs while suspended. r=padenot --- content/media/MediaStreamGraph.cpp | 32 +++++++++++++++++++++++++--- content/media/MediaStreamGraphImpl.h | 8 +++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 00dd96821d84..27cdadb6e80f 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1116,6 +1116,28 @@ MediaStreamGraphImpl::AllFinishedStreamsNotified() return true; } +void +MediaStreamGraphImpl::PauseAllAudioOutputs() +{ + for (uint32_t i = 0; i < mStreams.Length(); ++i) { + MediaStream* s = mStreams[i]; + for (uint32_t j = 0; j < s->mAudioOutputStreams.Length(); ++j) { + s->mAudioOutputStreams[j].mStream->Pause(); + } + } +} + +void +MediaStreamGraphImpl::ResumeAllAudioOutputs() +{ + for (uint32_t i = 0; i < mStreams.Length(); ++i) { + MediaStream* s = mStreams[i]; + for (uint32_t j = 0; j < s->mAudioOutputStreams.Length(); ++j) { + s->mAudioOutputStreams[j].mStream->Resume(); + } + } +} + void MediaStreamGraphImpl::RunThread() { @@ -1180,7 +1202,6 @@ MediaStreamGraphImpl::RunThread() RecomputeBlocking(endBlockingDecisions); // Play stream contents. - uint32_t audioStreamsActive = 0; bool allBlockedForever = true; // True when we've done ProduceOutput for all processed streams. bool doneAllProducing = false; @@ -1221,7 +1242,6 @@ MediaStreamGraphImpl::RunThread() // Only playback audio and video in real-time mode CreateOrDestroyAudioStreams(prevComputedTime, stream); PlayAudio(stream, prevComputedTime, mStateComputedTime); - audioStreamsActive += stream->mAudioOutputStreams.Length(); PlayVideo(stream); } SourceMediaStream* is = stream->AsSourceStream(); @@ -1233,7 +1253,7 @@ MediaStreamGraphImpl::RunThread() allBlockedForever = false; } } - if (ensureNextIteration || !allBlockedForever || audioStreamsActive > 0) { + if (ensureNextIteration || !allBlockedForever) { EnsureNextIteration(); } @@ -1261,6 +1281,7 @@ MediaStreamGraphImpl::RunThread() if (mRealtime) { PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; TimeStamp now = TimeStamp::Now(); + bool pausedOutputs = false; if (mNeedAnotherIteration) { int64_t timeoutMS = MEDIA_GRAPH_TARGET_PERIOD_MS - int64_t((now - mCurrentTimeStamp).ToMilliseconds()); @@ -1273,6 +1294,8 @@ MediaStreamGraphImpl::RunThread() mWaitState = WAITSTATE_WAITING_FOR_NEXT_ITERATION; } else { mWaitState = WAITSTATE_WAITING_INDEFINITELY; + PauseAllAudioOutputs(); + pausedOutputs = true; } if (timeout > 0) { mMonitor.Wait(timeout); @@ -1280,6 +1303,9 @@ MediaStreamGraphImpl::RunThread() (TimeStamp::Now() - mInitialTimeStamp).ToSeconds(), (TimeStamp::Now() - now).ToSeconds())); } + if (pausedOutputs) { + ResumeAllAudioOutputs(); + } } mWaitState = WAITSTATE_RUNNING; mNeedAnotherIteration = false; diff --git a/content/media/MediaStreamGraphImpl.h b/content/media/MediaStreamGraphImpl.h index 98024e439d0f..6e9d0219c0e2 100644 --- a/content/media/MediaStreamGraphImpl.h +++ b/content/media/MediaStreamGraphImpl.h @@ -370,6 +370,14 @@ public: { mStreamOrderDirty = true; } + /** + * Pause all AudioStreams being written to by MediaStreams + */ + void PauseAllAudioOutputs(); + /** + * Resume all AudioStreams being written to by MediaStreams + */ + void ResumeAllAudioOutputs(); // Data members From cd547c4bb40a2a936f0cc1cce4ff3d390fbfc434 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 16 Jan 2014 00:13:08 +1300 Subject: [PATCH 18/88] Bug 952893. Part 3: Tighten TimeVarying invariants so that GetAt always returns an end time when the value actually changes. r=padenot --- content/media/TimeVarying.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/content/media/TimeVarying.h b/content/media/TimeVarying.h index c22a6f1251eb..c1a2ff032a36 100644 --- a/content/media/TimeVarying.h +++ b/content/media/TimeVarying.h @@ -44,6 +44,9 @@ protected: * The implementation records a mCurrent (the value at the current time) * and an array of "change times" (greater than the current time) and the * new value for each change time. This is a simple but dumb implementation. + * We maintain the invariant that each change entry in the array must have + * a different value to the value in the previous change entry (or, for + * the first change entry, mCurrent). */ template class TimeVarying : public TimeVaryingBase { @@ -79,6 +82,9 @@ public: } mChanges.RemoveElementAt(i); } + if (mCurrent == aValue) { + return; + } mChanges.InsertElementAt(0, Entry(aTime, aValue)); } /** From 01f6728b1624cf8541c45577c053a40d22bf8532 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 18 Dec 2013 00:19:31 +1300 Subject: [PATCH 19/88] Bug 946502. Part 2: Remove unimplemented, unused function. r=mattwoodrow --HG-- extra : rebase_source : fbc4a398d1554ffc668a18bd667b6b90fdace15f --- layout/base/nsDisplayList.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 7183b6715502..3778d82abcdd 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -372,18 +372,6 @@ public: */ void SetInTransform(bool aInTransform) { mInTransform = aInTransform; } - /** - * Determines if this item is scrolled by content-document display-port - * scrolling. aAnimatedGeometryRoot will be set to the animated geometry root - * of the item. This may not necessarily correspond to the animated geometry - * root of the item's underlying frame. - * If specified, aOverrideAnimatedGeometryRoot will be treated as the active - * scrolled root. - */ - bool IsFixedItem(nsDisplayItem* aItem, - const nsIFrame** aAnimatedGeometryRoot = nullptr, - const nsIFrame* aOverrideAnimatedGeometryScrolledRoot = nullptr); - /** * @return true if images have been set to decode synchronously. */ From 2a1134e322fc178563d78a6213059bc78e59e2b3 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 18 Dec 2013 00:30:21 +1300 Subject: [PATCH 20/88] Bug 946502. Part 3: Extend FrameLayerBuilder to set fixed-pos metadata on layers created for background-attachment:fixed content. r=mattwoodrow --HG-- extra : rebase_source : dbaab718d7a358bfaa40124913bcd5acf0255aa1 --- layout/base/FrameLayerBuilder.cpp | 93 ++++++++++++++++++-------- layout/base/nsDisplayList.cpp | 6 +- layout/base/nsLayoutUtils.cpp | 107 +++++++++++++++++------------- layout/base/nsLayoutUtils.h | 19 +++++- 4 files changed, 145 insertions(+), 80 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 21ef0979a9aa..dee39e7d1168 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -607,6 +607,8 @@ protected: * has a displayport. Updates *aVisibleRegion to be the intersection of * aDrawRegion and the displayport, and updates *aIsSolidColorInVisibleRegion * (if non-null) to false if the visible region grows. + * This can return the actual viewport frame for layers whose display items + * are directly on the viewport (e.g. background-attachment:fixed backgrounds). */ const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot, const nsIntRegion& aDrawRegion, @@ -1661,31 +1663,44 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR nsIntRegion* aVisibleRegion, bool* aIsSolidColorInVisibleRegion) { - nsIFrame *viewport = mContainerFrame->PresContext()->PresShell()->GetRootFrame(); - - // Viewports with no fixed-pos frames are not relevant. - if (!viewport->GetFirstChild(nsIFrame::kFixedList)) { - return nullptr; - } + nsPresContext* presContext = mContainerFrame->PresContext(); + nsIFrame* viewport = presContext->PresShell()->GetRootFrame(); + const nsIFrame* result = nullptr; nsRect displayPort; - for (const nsIFrame* f = aAnimatedGeometryRoot; f; f = f->GetParent()) { - if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(f, &displayPort)) { - // Display ports are relative to the viewport, convert it to be relative - // to our reference frame. - displayPort += viewport->GetOffsetToCrossDoc(mContainerReferenceFrame); - nsIntRegion newVisibleRegion; - newVisibleRegion.And(ScaleToOutsidePixels(displayPort, false), - aDrawRegion); - if (!aVisibleRegion->Contains(newVisibleRegion)) { - if (aIsSolidColorInVisibleRegion) { - *aIsSolidColorInVisibleRegion = false; - } - *aVisibleRegion = newVisibleRegion; + + if (viewport == aAnimatedGeometryRoot && + nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort)) { + // Probably a background-attachment:fixed item + result = viewport; + } else { + // Viewports with no fixed-pos frames are not relevant. + if (!viewport->GetFirstChild(nsIFrame::kFixedList)) { + return nullptr; + } + for (const nsIFrame* f = aAnimatedGeometryRoot; f; f = f->GetParent()) { + if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(f, &displayPort)) { + result = f; + break; } - return f; + } + if (!result) { + return nullptr; } } - return nullptr; + + // Display ports are relative to the viewport, convert it to be relative + // to our reference frame. + displayPort += viewport->GetOffsetToCrossDoc(mContainerReferenceFrame); + nsIntRegion newVisibleRegion; + newVisibleRegion.And(ScaleToOutsidePixels(displayPort, false), + aDrawRegion); + if (!aVisibleRegion->Contains(newVisibleRegion)) { + if (aIsSolidColorInVisibleRegion) { + *aIsSolidColorInVisibleRegion = false; + } + *aVisibleRegion = newVisibleRegion; + } + return result; } void @@ -1697,19 +1712,31 @@ ContainerState::SetFixedPositionLayerData(Layer* aLayer, return; } - nsIFrame* viewportFrame = aFixedPosFrame->GetParent(); nsPresContext* presContext = aFixedPosFrame->PresContext(); - // Fixed position frames are reflowed into the scroll-port size if one has - // been set. - nsSize viewportSize = viewportFrame->GetSize(); - if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) { - viewportSize = presContext->PresShell()-> - GetScrollPositionClampingScrollPortSize(); + const nsIFrame* viewportFrame = aFixedPosFrame->GetParent(); + // anchorRect will be in the container's coordinate system (aLayer's parent layer). + // This is the same as the display items' reference frame. + nsRect anchorRect; + if (viewportFrame) { + // Fixed position frames are reflowed into the scroll-port size if one has + // been set. + if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) { + anchorRect.SizeTo(presContext->PresShell()->GetScrollPositionClampingScrollPortSize()); + } else { + anchorRect.SizeTo(viewportFrame->GetSize()); + } + } else { + // A display item directly attached to the viewport. + // For background-attachment:fixed items, the anchor point is always the + // top-left of the viewport currently. + viewportFrame = aFixedPosFrame; } + // The anchorRect top-left is always the viewport top-left. + anchorRect.MoveTo(viewportFrame->GetOffsetToCrossDoc(mContainerReferenceFrame)); nsLayoutUtils::SetFixedPositionLayerData(aLayer, - viewportFrame, viewportSize, aFixedPosFrame, presContext, mParameters); + viewportFrame, anchorRect, aFixedPosFrame, presContext, mParameters); } static gfx3DMatrix @@ -2131,6 +2158,14 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem, thebesLayerData->mLayer = layer; thebesLayerData->mAnimatedGeometryRoot = aActiveScrolledRoot; thebesLayerData->mReferenceFrame = aItem->ReferenceFrame(); + if (!aActiveScrolledRoot->GetParent() && + nsLayoutUtils::ViewportHasDisplayPort(aActiveScrolledRoot->PresContext())) { + // The active scrolled root is the viewport, so this is background-attachment:fixed + // or fixed-pos elements or something like that. Async scrolling may + // do magic things to move these layers, so don't allow any regular content + // to be pushed to layers below them; that might turn out to be incorrect. + thebesLayerData->SetAllDrawingAbove(); + } NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???"); *mNewChildLayers.AppendElement() = layer.forget(); diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index b0f66285afc5..c04f20a7136f 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -3455,9 +3455,9 @@ nsDisplayStickyPosition::BuildLayer(nsDisplayListBuilder* aBuilder, GetScrollPositionClampingScrollPortSize(); } - nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame, scrollFrameSize, - mStickyPosFrame, - presContext, aContainerParameters); + nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame, + nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), scrollFrameSize), + mStickyPosFrame, presContext, aContainerParameters); ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor( stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent()); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 6b5cc7bd5f4f..858d1f7e8473 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1203,7 +1203,7 @@ nsLayoutUtils::GetScrollableFrameFor(const nsIFrame *aScrolledFrame) /* static */ void nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame, - nsSize aViewportSize, + const nsRect& aAnchorRect, const nsIFrame* aFixedPosFrame, nsPresContext* aPresContext, const ContainerLayerParameters& aContainerParameters) { @@ -1211,41 +1211,31 @@ nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer, // This, in conjunction with the container scale, will correspond to the // coordinate-space of the built layer. float factor = aPresContext->AppUnitsPerDevPixel(); - nsPoint origin = aViewportFrame->GetOffsetToCrossDoc(aFixedPosFrame); - LayerRect anchorRect(NSAppUnitsToFloatPixels(origin.x, factor) * - aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(origin.y, factor) * - aContainerParameters.mYScale, - NSAppUnitsToFloatPixels(aViewportSize.width, factor) * - aContainerParameters.mXScale, - NSAppUnitsToFloatPixels(aViewportSize.height, factor) * - aContainerParameters.mYScale); + Rect anchorRect(NSAppUnitsToFloatPixels(aAnchorRect.x, factor) * + aContainerParameters.mXScale, + NSAppUnitsToFloatPixels(aAnchorRect.y, factor) * + aContainerParameters.mYScale, + NSAppUnitsToFloatPixels(aAnchorRect.width, factor) * + aContainerParameters.mXScale, + NSAppUnitsToFloatPixels(aAnchorRect.height, factor) * + aContainerParameters.mYScale); + // Need to transform anchorRect from the container layer's coordinate system + // into aLayer's coordinate system. + Matrix transform2d; + if (aLayer->GetTransform().Is2D(&transform2d)) { + transform2d.Invert(); + anchorRect = transform2d.TransformBounds(anchorRect); + } else { + NS_ERROR("3D transform found between fixedpos content and its viewport (should never happen)"); + anchorRect = Rect(0,0,0,0); + } // Work out the anchor point for this fixed position layer. We assume that // any positioning set (left/top/right/bottom) indicates that the // corresponding side of its container should be the anchor point, // defaulting to top-left. - LayerPoint anchor = anchorRect.TopLeft(); - - const nsStylePosition* position = aFixedPosFrame->StylePosition(); - if (position->mOffset.GetRightUnit() != eStyleUnit_Auto) { - if (position->mOffset.GetLeftUnit() != eStyleUnit_Auto) { - anchor.x = anchorRect.x + anchorRect.width / 2.f; - } else { - anchor.x = anchorRect.XMost(); - } - } - if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto) { - if (position->mOffset.GetTopUnit() != eStyleUnit_Auto) { - anchor.y = anchorRect.y + anchorRect.height / 2.f; - } else { - anchor.y = anchorRect.YMost(); - } - } - - aLayer->SetFixedPositionAnchor(anchor); - - // Also make sure the layer is aware of any fixed position margins that have + LayerPoint anchor(anchorRect.x, anchorRect.y); + // Make sure the layer is aware of any fixed position margins that have // been set. nsMargin fixedMargins = aPresContext->PresShell()->GetContentDocumentFixedPositionMargins(); LayerMargin fixedLayerMargins(NSAppUnitsToFloatPixels(fixedMargins.top, factor) * @@ -1257,21 +1247,49 @@ nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer, NSAppUnitsToFloatPixels(fixedMargins.left, factor) * aContainerParameters.mXScale); - // If the frame is auto-positioned on either axis, set the top/left layer - // margins to -1, to indicate to the compositor that this layer is - // unaffected by fixed margins. - if (position->mOffset.GetLeftUnit() == eStyleUnit_Auto && - position->mOffset.GetRightUnit() == eStyleUnit_Auto) { - fixedLayerMargins.left = -1; - } - if (position->mOffset.GetTopUnit() == eStyleUnit_Auto && - position->mOffset.GetBottomUnit() == eStyleUnit_Auto) { - fixedLayerMargins.top = -1; + if (aFixedPosFrame != aViewportFrame) { + const nsStylePosition* position = aFixedPosFrame->StylePosition(); + if (position->mOffset.GetRightUnit() != eStyleUnit_Auto) { + if (position->mOffset.GetLeftUnit() != eStyleUnit_Auto) { + anchor.x = anchorRect.x + anchorRect.width / 2.f; + } else { + anchor.x = anchorRect.XMost(); + } + } + if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto) { + if (position->mOffset.GetTopUnit() != eStyleUnit_Auto) { + anchor.y = anchorRect.y + anchorRect.height / 2.f; + } else { + anchor.y = anchorRect.YMost(); + } + } + + // If the frame is auto-positioned on either axis, set the top/left layer + // margins to -1, to indicate to the compositor that this layer is + // unaffected by fixed margins. + if (position->mOffset.GetLeftUnit() == eStyleUnit_Auto && + position->mOffset.GetRightUnit() == eStyleUnit_Auto) { + fixedLayerMargins.left = -1; + } + if (position->mOffset.GetTopUnit() == eStyleUnit_Auto && + position->mOffset.GetBottomUnit() == eStyleUnit_Auto) { + fixedLayerMargins.top = -1; + } } + aLayer->SetFixedPositionAnchor(anchor); aLayer->SetFixedPositionMargins(fixedLayerMargins); } +bool +nsLayoutUtils::ViewportHasDisplayPort(nsPresContext* aPresContext, nsRect* aDisplayPort) +{ + nsIFrame* rootScrollFrame = + aPresContext->PresShell()->GetRootScrollFrame(); + return rootScrollFrame && + nsLayoutUtils::GetDisplayPort(rootScrollFrame->GetContent(), aDisplayPort); +} + bool nsLayoutUtils::IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, nsRect* aDisplayPort) { @@ -1283,12 +1301,7 @@ nsLayoutUtils::IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, nsRect* aDis aFrame->StyleDisplay()->mPosition != NS_STYLE_POSITION_FIXED) { return false; } - nsIFrame* rootScrollFrame = - aFrame->PresContext()->PresShell()->GetRootScrollFrame(); - // Treat a fixed-pos frame as an animated geometry root if it belongs to - // a viewport which has a scrollframe and a displayport. - return rootScrollFrame && - nsLayoutUtils::GetDisplayPort(rootScrollFrame->GetContent(), aDisplayPort); + return ViewportHasDisplayPort(aFrame->PresContext(), aDisplayPort); } nsIFrame* diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 6e89a7e24e8c..9adc72f22d8b 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -375,12 +375,29 @@ public: static bool IsAncestorFrameCrossDoc(const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, const nsIFrame* aCommonAncestor = nullptr); + /** + * Sets the fixed-pos metadata properties on aLayer. + * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a viewport + * frame, then we pick a corner of aAnchorRect to as the anchor point for the + * fixed-pos layer (i.e. the point to remain stable during zooming), based + * on which of the fixed-pos frame's CSS absolute positioning offset + * properties (top, left, right, bottom) are auto. aAnchorRect is in the + * coordinate space of aLayer's container layer (i.e. relative to the reference + * frame of the display item which is building aLayer's container layer). + */ static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame, - nsSize aViewportSize, + const nsRect& aAnchorRect, const nsIFrame* aFixedPosFrame, nsPresContext* aPresContext, const ContainerLayerParameters& aContainerParameters); + /** + * Return true if aPresContext's viewport has a displayport. + * Fills in aDisplayPort with the displayport rectangle if non-null. + */ + static bool ViewportHasDisplayPort(nsPresContext* aPresContext, + nsRect* aDisplayPort = nullptr); + /** * Return true if aFrame is a fixed-pos frame and is a child of a viewport * which has a displayport. These frames get special treatment from the compositor. From 7a45ea7b6c2c860dabab8e23d732fa927c9bd42f Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Sat, 4 Jan 2014 18:14:27 +1300 Subject: [PATCH 21/88] Bug 946502. Part 4: Remove mStickyPosFrame. r=mattwoodrow --HG-- extra : rebase_source : 71bcbd246cf6806196a3e64d32fdde169bddfa07 --- layout/base/nsDisplayList.cpp | 7 +++---- layout/base/nsDisplayList.h | 5 +---- layout/generic/nsFrame.cpp | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index c04f20a7136f..2a0bf6b82ed0 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -3417,10 +3417,9 @@ nsDisplayResolution::BuildLayer(nsDisplayListBuilder* aBuilder, nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - nsIFrame* aStickyPosFrame, nsDisplayList* aList) : nsDisplayOwnLayer(aBuilder, aFrame, aList) - , mStickyPosFrame(aStickyPosFrame) { +{ MOZ_COUNT_CTOR(nsDisplayStickyPosition); } @@ -3457,7 +3456,7 @@ nsDisplayStickyPosition::BuildLayer(nsDisplayListBuilder* aBuilder, nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame, nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), scrollFrameSize), - mStickyPosFrame, presContext, aContainerParameters); + mFrame, presContext, aContainerParameters); ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor( stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent()); @@ -3492,7 +3491,7 @@ bool nsDisplayStickyPosition::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplay return false; // Items with the same fixed position frame can be merged. nsDisplayStickyPosition* other = static_cast(aItem); - if (other->mStickyPosFrame != mStickyPosFrame) + if (other->mFrame != mFrame) return false; if (aItem->GetClip() != GetClip()) return false; diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 3778d82abcdd..2cf7118ea43a 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2720,7 +2720,7 @@ public: class nsDisplayStickyPosition : public nsDisplayOwnLayer { public: nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - nsIFrame* aStickyPosFrame, nsDisplayList* aList); + nsDisplayList* aList); #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayStickyPosition(); #endif @@ -2736,9 +2736,6 @@ public: return mozilla::LAYER_ACTIVE; } virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; - -protected: - nsIFrame* mStickyPosFrame; }; /** diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 22f4294a0807..c693e2bcd4ed 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1996,8 +1996,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, */ if (useStickyPosition) { resultList.AppendNewToTop( - new (aBuilder) nsDisplayStickyPosition(aBuilder, this, this, - &resultList)); + new (aBuilder) nsDisplayStickyPosition(aBuilder, this, &resultList)); } /* If we're going to apply a transformation and don't have preserve-3d set, wrap From b1a631635aea158beeb3b7b6f930bb1cd7f7b6ba Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 13 Dec 2013 01:33:01 +1300 Subject: [PATCH 22/88] Bug 634982. Reftest. r=jrmuizel --HG-- extra : rebase_source : 1ffa269abef40fc16b08c6a34c6bb87906112a82 --- layout/reftests/css-gradients/reftest.list | 1 + .../repeated-final-stop-1-ref.html | 19 +++++++++++++++++++ .../css-gradients/repeated-final-stop-1.html | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 layout/reftests/css-gradients/repeated-final-stop-1-ref.html create mode 100644 layout/reftests/css-gradients/repeated-final-stop-1.html diff --git a/layout/reftests/css-gradients/reftest.list b/layout/reftests/css-gradients/reftest.list index c8be9e346bbe..3618ec7e5a85 100644 --- a/layout/reftests/css-gradients/reftest.list +++ b/layout/reftests/css-gradients/reftest.list @@ -85,6 +85,7 @@ fuzzy-if(Android,17,13320) == radial-shape-farthest-side-1c.html radial-shape-fa == radial-zero-length-1h.html radial-zero-length-1-ref.html == radial-zero-length-1i.html radial-zero-length-1-ref.html == radial-zero-length-1j.html radial-zero-length-1-ref.html +== repeated-final-stop-1.html repeated-final-stop-1-ref.html == repeating-linear-1a.html repeating-linear-1-ref.html == repeating-linear-1b.html repeating-linear-1-ref.html == repeating-linear-2a.html repeating-linear-2-ref.html diff --git a/layout/reftests/css-gradients/repeated-final-stop-1-ref.html b/layout/reftests/css-gradients/repeated-final-stop-1-ref.html new file mode 100644 index 000000000000..be4f97dd7b49 --- /dev/null +++ b/layout/reftests/css-gradients/repeated-final-stop-1-ref.html @@ -0,0 +1,19 @@ + + + + + + +
+ + diff --git a/layout/reftests/css-gradients/repeated-final-stop-1.html b/layout/reftests/css-gradients/repeated-final-stop-1.html new file mode 100644 index 000000000000..35cc594b63dd --- /dev/null +++ b/layout/reftests/css-gradients/repeated-final-stop-1.html @@ -0,0 +1,18 @@ + + + + + + +
+ + From 3292b0bf93ec36010866f6ee0dca1a52211cea8b Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 15 Jan 2014 23:07:30 +1300 Subject: [PATCH 23/88] Bug 941873. Blocked AudioNodeStreams should not run processing. r=karl --HG-- extra : rebase_source : 122b7c48df42f78e9f7d2b8176ff6bc1ca14ad28 --- content/media/AudioNodeStream.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index 02147129a948..30d5faad4039 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -410,7 +410,12 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) uint16_t outputCount = std::max(uint16_t(1), mEngine->OutputCount()); mLastChunks.SetLength(outputCount); - if (mMuted || IsFinishedOnGraphThread()) { + // Consider this stream blocked if it has already finished output. Normally + // mBlocked would reflect this, but due to rounding errors our audio track may + // appear to extend slightly beyond aFrom, so we might not be blocked yet. + bool blocked = mFinished || mBlocked.GetAt(aFrom); + // If the stream has finished at this time, it will be blocked. + if (mMuted || blocked) { for (uint16_t i = 0; i < outputCount; ++i) { mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE); } @@ -442,16 +447,16 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) if (finished) { mMarkAsFinishedAfterThisBlock = true; } - } - if (mDisabledTrackIDs.Contains(static_cast(AUDIO_TRACK))) { - for (uint32_t i = 0; i < mLastChunks.Length(); ++i) { - mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE); + if (mDisabledTrackIDs.Contains(static_cast(AUDIO_TRACK))) { + for (uint32_t i = 0; i < outputCount; ++i) { + mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE); + } } } - if (!IsFinishedOnGraphThread()) { - // Don't output anything after we've finished! + if (!blocked) { + // Don't output anything while blocked AdvanceOutputSegment(); if (mMarkAsFinishedAfterThisBlock && (aFlags & ALLOW_FINISH)) { // This stream was finished the last time that we looked at it, and all From da30bcc53b397be603a6c1a228fef4973af391f8 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 30 Jan 2014 18:50:17 +1300 Subject: [PATCH 24/88] Bug 961996 - restore mForceShutDown check before MediaStreamGraphShutDownRunnable dispatch r=roc This check was dropped in 1ebe4da27dd5. --HG-- extra : rebase_source : 495d81cff39f2ee074effe6bef06caf6b2ac3161 --- content/media/MediaStreamGraph.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 27cdadb6e80f..8121d7450f2a 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1557,7 +1557,8 @@ MediaStreamGraphImpl::RunInStableState() } } - if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) { + if (mForceShutDown && + mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) { // Defer calls to RunDuringShutdown() to happen while mMonitor is not held. for (uint32_t i = 0; i < mMessageQueue.Length(); ++i) { MessageBlock& mb = mMessageQueue[i]; From 97762164c1803220c7d1b8a4530caacb9c34a193 Mon Sep 17 00:00:00 2001 From: Nicholas Cameron Date: Thu, 30 Jan 2014 22:39:11 +1300 Subject: [PATCH 25/88] Bug 959781. Ensure we are using the correct content type in BeginPaint and BorrowDrawTargetForPainting. r=mattwoodrow --- gfx/layers/RotatedBuffer.cpp | 22 +++++++++------------- gfx/layers/RotatedBuffer.h | 2 ++ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/gfx/layers/RotatedBuffer.cpp b/gfx/layers/RotatedBuffer.cpp index c038b10418b3..8476c16b2ad0 100644 --- a/gfx/layers/RotatedBuffer.cpp +++ b/gfx/layers/RotatedBuffer.cpp @@ -412,7 +412,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, nsIntRegion validRegion = aLayer->GetValidRegion(); bool canUseOpaqueSurface = aLayer->CanUseOpaqueSurface(); - ContentType contentType = + ContentType layerContentType = canUseOpaqueSurface ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA; @@ -425,6 +425,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, mode = aLayer->GetSurfaceMode(); neededRegion = aLayer->GetVisibleRegion(); canReuseBuffer = HaveBuffer() && BufferSizeOkFor(neededRegion.GetBounds().Size()); + result.mContentType = layerContentType; if (canReuseBuffer) { if (mBufferRect.Contains(neededRegion.GetBounds())) { @@ -454,7 +455,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, !gfxPlatform::ComponentAlphaEnabled()) { mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA; } else { - contentType = gfxContentType::COLOR; + result.mContentType = gfxContentType::COLOR; } #endif } @@ -464,7 +465,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, neededRegion.GetNumRects() > 1)) { // The area we add to neededRegion might not be painted opaquely if (mode == SurfaceMode::SURFACE_OPAQUE) { - contentType = gfxContentType::COLOR_ALPHA; + result.mContentType = gfxContentType::COLOR_ALPHA; mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA; } @@ -476,7 +477,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, // If we have an existing buffer, but the content type has changed or we // have transitioned into/out of component alpha, then we need to recreate it. if (HaveBuffer() && - (contentType != BufferContentType() || + (result.mContentType != BufferContentType() || (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) != HaveBufferOnWhite())) { // We're effectively clearing the valid region, so we need to draw @@ -497,7 +498,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, result.mRegionToDraw.Sub(neededRegion, validRegion); - // Do not modify result.mRegionToDraw after this call. + // Do not modify result.mRegionToDraw or result.mContentType after this call. // Do not modify mBufferRect, mBufferRotation, or mDidSelfCopy, // or call CreateBuffer before this call. FinalizeFrame(result.mRegionToDraw); @@ -594,7 +595,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, if (!result.mDidSelfCopy) { destBufferRect = ComputeBufferRect(neededRegion.GetBounds()); - CreateBuffer(contentType, destBufferRect, bufferFlags, + CreateBuffer(result.mContentType, destBufferRect, bufferFlags, &destDTBuffer, &destDTBufferOnWhite); if (!destDTBuffer) { return result; @@ -614,7 +615,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, } } else { // The buffer's not big enough, so allocate a new one - CreateBuffer(contentType, destBufferRect, bufferFlags, + CreateBuffer(result.mContentType, destBufferRect, bufferFlags, &destDTBuffer, &destDTBufferOnWhite); if (!destDTBuffer) { return result; @@ -682,11 +683,6 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(ThebesLayer* aLayer, DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(), BUFFER_BOTH); - bool canUseOpaqueSurface = aLayer->CanUseOpaqueSurface(); - ContentType contentType = - canUseOpaqueSurface ? gfxContentType::COLOR : - gfxContentType::COLOR_ALPHA; - if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) { MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite); nsIntRegionRectIterator iter(aPaintState.mRegionToDraw); @@ -697,7 +693,7 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(ThebesLayer* aLayer, mDTBufferOnWhite->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0))); } - } else if (contentType == gfxContentType::COLOR_ALPHA && HaveBuffer()) { + } else if (aPaintState.mContentType == gfxContentType::COLOR_ALPHA && HaveBuffer()) { // HaveBuffer() => we have an existing buffer that we must clear nsIntRegionRectIterator iter(aPaintState.mRegionToDraw); const nsIntRect *iterRect; diff --git a/gfx/layers/RotatedBuffer.h b/gfx/layers/RotatedBuffer.h index a5a4876e63b7..aaa896b8b988 100644 --- a/gfx/layers/RotatedBuffer.h +++ b/gfx/layers/RotatedBuffer.h @@ -214,6 +214,7 @@ public: struct PaintState { PaintState() : mMode(SurfaceMode::SURFACE_NONE) + , mContentType(gfxContentType::SENTINEL) , mDidSelfCopy(false) {} @@ -221,6 +222,7 @@ public: nsIntRegion mRegionToInvalidate; SurfaceMode mMode; DrawRegionClip mClip; + ContentType mContentType; bool mDidSelfCopy; }; From 1d0a8b5151e6cade745208c5c814159ca33139c7 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 30 Jan 2014 09:48:20 +0000 Subject: [PATCH 26/88] bug 964240 - update harfbuzz to pick up Hangul shaper improvements and other fixes. r=jdaggett --- gfx/harfbuzz/src/Makefile.am | 9 +- gfx/harfbuzz/src/hb-blob.cc | 1 - gfx/harfbuzz/src/hb-buffer-private.hh | 1 - gfx/harfbuzz/src/hb-buffer-serialize.cc | 2 +- gfx/harfbuzz/src/hb-common.cc | 2 - gfx/harfbuzz/src/hb-common.h | 8 +- gfx/harfbuzz/src/hb-coretext.cc | 22 +- gfx/harfbuzz/src/hb-face-private.hh | 1 - gfx/harfbuzz/src/hb-face.cc | 1 - gfx/harfbuzz/src/hb-fallback-shape.cc | 5 +- gfx/harfbuzz/src/hb-font-private.hh | 7 +- gfx/harfbuzz/src/hb-font.cc | 1 - gfx/harfbuzz/src/hb-graphite2.cc | 4 +- gfx/harfbuzz/src/hb-open-type-private.hh | 4 +- gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh | 28 +- gfx/harfbuzz/src/hb-ot-layout-private.hh | 2 - gfx/harfbuzz/src/hb-ot-layout.h | 5 - .../src/hb-ot-shape-complex-arabic.cc | 3 +- .../src/hb-ot-shape-complex-default.cc | 184 +------- .../src/hb-ot-shape-complex-hangul.cc | 417 ++++++++++++++++++ .../src/hb-ot-shape-complex-hebrew.cc | 172 ++++++++ gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc | 8 +- .../src/hb-ot-shape-complex-myanmar.cc | 9 +- .../src/hb-ot-shape-complex-private.hh | 38 +- gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc | 9 +- gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc | 4 +- .../src/hb-ot-shape-complex-tibetan.cc | 61 +++ gfx/harfbuzz/src/hb-ot-shape-fallback.cc | 6 +- .../src/hb-ot-shape-normalize-private.hh | 3 +- gfx/harfbuzz/src/hb-ot-shape-normalize.cc | 36 +- gfx/harfbuzz/src/hb-ot-shape-private.hh | 15 + gfx/harfbuzz/src/hb-ot-shape.cc | 58 ++- gfx/harfbuzz/src/hb-ot-shape.h | 54 +++ gfx/harfbuzz/src/hb-ot-tag.cc | 1 - gfx/harfbuzz/src/hb-ot.h | 9 +- gfx/harfbuzz/src/hb-private.hh | 6 + gfx/harfbuzz/src/hb-set-private.hh | 1 - gfx/harfbuzz/src/hb-shape-plan-private.hh | 1 - gfx/harfbuzz/src/hb-shaper-list.hh | 2 + gfx/harfbuzz/src/hb-tt-font.cc | 2 - gfx/harfbuzz/src/hb-unicode-private.hh | 23 +- gfx/harfbuzz/src/hb-uniscribe.cc | 17 +- gfx/harfbuzz/src/hb-version.h | 4 +- gfx/harfbuzz/src/moz.build | 4 + 44 files changed, 920 insertions(+), 330 deletions(-) create mode 100644 gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc create mode 100644 gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc create mode 100644 gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc create mode 100644 gfx/harfbuzz/src/hb-ot-shape.h diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am index 81802252fd7c..e2790a0d86b1 100644 --- a/gfx/harfbuzz/src/Makefile.am +++ b/gfx/harfbuzz/src/Makefile.am @@ -27,7 +27,6 @@ HBSOURCES = \ hb-buffer.cc \ hb-cache-private.hh \ hb-common.cc \ - hb-fallback-shape.cc \ hb-face-private.hh \ hb-face.cc \ hb-font-private.hh \ @@ -92,6 +91,8 @@ HBSOURCES += \ hb-ot-shape-complex-arabic-fallback.hh \ hb-ot-shape-complex-arabic-table.hh \ hb-ot-shape-complex-default.cc \ + hb-ot-shape-complex-hangul.cc \ + hb-ot-shape-complex-hebrew.cc \ hb-ot-shape-complex-indic.cc \ hb-ot-shape-complex-indic-machine.hh \ hb-ot-shape-complex-indic-private.hh \ @@ -101,6 +102,7 @@ HBSOURCES += \ hb-ot-shape-complex-sea.cc \ hb-ot-shape-complex-sea-machine.hh \ hb-ot-shape-complex-thai.cc \ + hb-ot-shape-complex-tibetan.cc \ hb-ot-shape-complex-private.hh \ hb-ot-shape-normalize-private.hh \ hb-ot-shape-normalize.cc \ @@ -111,10 +113,15 @@ HBSOURCES += \ HBHEADERS += \ hb-ot.h \ hb-ot-layout.h \ + hb-ot-shape.h \ hb-ot-tag.h \ $(NULL) endif +if HAVE_FALLBACK +HBSOURCES += hb-fallback-shape.cc +endif + if HAVE_PTHREAD HBCFLAGS += $(PTHREAD_CFLAGS) HBLIBS += $(PTHREAD_LIBS) diff --git a/gfx/harfbuzz/src/hb-blob.cc b/gfx/harfbuzz/src/hb-blob.cc index 7a659b26b971..d6acca0fca5e 100644 --- a/gfx/harfbuzz/src/hb-blob.cc +++ b/gfx/harfbuzz/src/hb-blob.cc @@ -29,7 +29,6 @@ #include "hb-private.hh" -#include "hb-blob.h" #include "hb-object-private.hh" #ifdef HAVE_SYS_MMAN_H diff --git a/gfx/harfbuzz/src/hb-buffer-private.hh b/gfx/harfbuzz/src/hb-buffer-private.hh index 49773f1c99b0..3a2b9ab48160 100644 --- a/gfx/harfbuzz/src/hb-buffer-private.hh +++ b/gfx/harfbuzz/src/hb-buffer-private.hh @@ -31,7 +31,6 @@ #define HB_BUFFER_PRIVATE_HH #include "hb-private.hh" -#include "hb-buffer.h" #include "hb-object-private.hh" #include "hb-unicode-private.hh" diff --git a/gfx/harfbuzz/src/hb-buffer-serialize.cc b/gfx/harfbuzz/src/hb-buffer-serialize.cc index 4541db23bd23..263bc81dc466 100644 --- a/gfx/harfbuzz/src/hb-buffer-serialize.cc +++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc @@ -204,7 +204,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, *p++ = '+'; p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); - if (pos->y_advance) + if (pos[i].y_advance) p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc index cf24660f7983..0fd790bc0420 100644 --- a/gfx/harfbuzz/src/hb-common.cc +++ b/gfx/harfbuzz/src/hb-common.cc @@ -28,8 +28,6 @@ #include "hb-private.hh" -#include "hb-version.h" - #include "hb-mutex-private.hh" #include "hb-object-private.hh" diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h index e445504550b0..c8bfd8825a23 100644 --- a/gfx/harfbuzz/src/hb-common.h +++ b/gfx/harfbuzz/src/hb-common.h @@ -94,6 +94,7 @@ typedef uint32_t hb_tag_t; #define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) #define HB_TAG_NONE HB_TAG(0,0,0,0) +#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff) /* len=-1 means str is NUL-terminated. */ hb_tag_t @@ -270,7 +271,12 @@ typedef enum /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /* No script set. */ - /*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE + /*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE, + + /* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t + * without risking undefined behavior. */ + /*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX + } hb_script_t; /* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */ diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc index 25e4055b0113..87dd77975165 100644 --- a/gfx/harfbuzz/src/hb-coretext.cc +++ b/gfx/harfbuzz/src/hb-coretext.cc @@ -591,7 +591,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (NULL, chars_len); CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref); - CFRelease (string_ref); CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), kCTFontAttributeName, font_data->ct_font); @@ -671,23 +670,33 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, if (buffer->in_error) FAIL ("Buffer resize failed"); hb_glyph_info_t *info = buffer->info + buffer->len; - buffer->len += range.length; - for (CFIndex j = 0; j < range.length; j++) + CGGlyph notdef = 0; + double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); + + for (CFIndex j = range.location; j < range.location + range.length; j++) { - CGGlyph notdef = 0; - double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); + UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); + if (hb_in_range (ch, 0xDC00, 0xDFFF) && range.location < j) + { + ch = CFStringGetCharacterAtIndex (string_ref, j - 1); + if (hb_in_range (ch, 0xD800, 0xDBFF)) + /* This is the second of a surrogate pair. Don't need .notdef + * for this one. */ + continue; + } info->codepoint = notdef; /* TODO We have to fixup clusters later. See vis_clusters in * hb-uniscribe.cc for example. */ - info->cluster = range.location + j; + info->cluster = j; info->mask = advance; info->var1.u32 = 0; info->var2.u32 = 0; info++; + buffer->len++; } continue; } @@ -796,6 +805,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } } + CFRelease (string_ref); CFRelease (line); return true; diff --git a/gfx/harfbuzz/src/hb-face-private.hh b/gfx/harfbuzz/src/hb-face-private.hh index b33be0e5fcee..6520d3dbdff2 100644 --- a/gfx/harfbuzz/src/hb-face-private.hh +++ b/gfx/harfbuzz/src/hb-face-private.hh @@ -31,7 +31,6 @@ #include "hb-private.hh" -#include "hb-font.h" #include "hb-object-private.hh" #include "hb-shaper-private.hh" #include "hb-shape-plan-private.hh" diff --git a/gfx/harfbuzz/src/hb-face.cc b/gfx/harfbuzz/src/hb-face.cc index ebe8ec5e5d5d..71cf49a5bc94 100644 --- a/gfx/harfbuzz/src/hb-face.cc +++ b/gfx/harfbuzz/src/hb-face.cc @@ -31,7 +31,6 @@ #include "hb-ot-layout-private.hh" #include "hb-font-private.hh" -#include "hb-blob.h" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" diff --git a/gfx/harfbuzz/src/hb-fallback-shape.cc b/gfx/harfbuzz/src/hb-fallback-shape.cc index b894a4a47d1b..ea54bb8e0f08 100644 --- a/gfx/harfbuzz/src/hb-fallback-shape.cc +++ b/gfx/harfbuzz/src/hb-fallback-shape.cc @@ -105,8 +105,9 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, * shaper which many people unfortunately still request. */ + bool has_space; hb_codepoint_t space; - font->get_glyph (' ', 0, &space); + has_space = font->get_glyph (' ', 0, &space); buffer->clear_positions (); @@ -114,7 +115,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, for (unsigned int i = 0; i < count; i++) { - if (buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) { + if (has_space && buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) { buffer->info[i].codepoint = space; buffer->pos[i].x_advance = 0; buffer->pos[i].y_advance = 0; diff --git a/gfx/harfbuzz/src/hb-font-private.hh b/gfx/harfbuzz/src/hb-font-private.hh index aa6c515bcb2f..33bbf7143a2f 100644 --- a/gfx/harfbuzz/src/hb-font-private.hh +++ b/gfx/harfbuzz/src/hb-font-private.hh @@ -31,7 +31,6 @@ #include "hb-private.hh" -#include "hb-font.h" #include "hb-object-private.hh" #include "hb-face-private.hh" #include "hb-shaper-private.hh" @@ -145,6 +144,12 @@ struct hb_font_t { /* Public getters */ + inline hb_bool_t has_glyph (hb_codepoint_t unicode) + { + hb_codepoint_t glyph; + return get_glyph (unicode, 0, &glyph); + } + inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph) { diff --git a/gfx/harfbuzz/src/hb-font.cc b/gfx/harfbuzz/src/hb-font.cc index 855864377e7f..fc4c8ebf077c 100644 --- a/gfx/harfbuzz/src/hb-font.cc +++ b/gfx/harfbuzz/src/hb-font.cc @@ -31,7 +31,6 @@ #include "hb-ot-layout-private.hh" #include "hb-font-private.hh" -#include "hb-blob.h" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc index 60d68d6b57a6..a309ca853bc0 100644 --- a/gfx/harfbuzz/src/hb-graphite2.cc +++ b/gfx/harfbuzz/src/hb-graphite2.cc @@ -34,8 +34,6 @@ #include -#include "hb-ot-tag.h" - HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face) HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font) @@ -109,7 +107,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face) hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t)); if (unlikely (!data)) - hb_blob_destroy (silf_blob); + return NULL; data->face = face; data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll); diff --git a/gfx/harfbuzz/src/hb-open-type-private.hh b/gfx/harfbuzz/src/hb-open-type-private.hh index ee3a21dc3b16..558103a8ecca 100644 --- a/gfx/harfbuzz/src/hb-open-type-private.hh +++ b/gfx/harfbuzz/src/hb-open-type-private.hh @@ -31,8 +31,6 @@ #include "hb-private.hh" -#include "hb-blob.h" - namespace OT { @@ -594,7 +592,7 @@ struct LONGDATETIME TRACE_SANITIZE (this); return TRACE_RETURN (likely (c->check_struct (this))); } - private: + protected: LONG major; ULONG minor; public: diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh index 5e4326ef0c57..7c0a4ea66673 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -109,11 +109,13 @@ struct ValueFormat : USHORT if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); if (format & xAdvance) { - if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); else values++; + if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values)); + values++; } /* y_advance values grow downward but font-space grows upward, hence negation */ if (format & yAdvance) { - if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values++)); else values++; + if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values)); + values++; } if (!has_device ()) return; @@ -125,17 +127,21 @@ struct ValueFormat : USHORT /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_x_delta (font); else values++; + if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); + values++; } if (format & yPlaDevice) { - if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (font); else values++; + if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); + values++; } if (format & xAdvDevice) { - if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++; + if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); + values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values++)).get_y_delta (font); else values++; + if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); + values++; } } @@ -240,12 +246,12 @@ struct AnchorFormat2 unsigned int x_ppem = font->x_ppem; unsigned int y_ppem = font->y_ppem; hb_position_t cx, cy; - hb_bool_t ret = false; + hb_bool_t ret; - if (x_ppem || y_ppem) - ret = font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); - *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate); - *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate); + ret = (x_ppem || y_ppem) && + font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); + *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); + *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) { diff --git a/gfx/harfbuzz/src/hb-ot-layout-private.hh b/gfx/harfbuzz/src/hb-ot-layout-private.hh index 139e33fe7a3e..0a0a54b25d06 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh @@ -31,8 +31,6 @@ #include "hb-private.hh" -#include "hb-ot-layout.h" - #include "hb-font-private.hh" #include "hb-buffer-private.hh" #include "hb-set-private.hh" diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h index dfc7f2446f7b..d90eff374d70 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.h +++ b/gfx/harfbuzz/src/hb-ot-layout.h @@ -193,11 +193,6 @@ hb_ot_layout_collect_lookups (hb_face_t *face, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */); -void -hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, - hb_tag_t table_tag, - hb_set_t *lookup_indexes /* OUT */); - void hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 4f6c86e8ee5f..ea6d85c1e6c1 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -199,7 +199,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_global_bool_feature (HB_TAG('c','a','l','t')); map->add_gsub_pause (NULL); - map->add_global_bool_feature (HB_TAG('c','s','w','h')); map->add_global_bool_feature (HB_TAG('m','s','e','t')); } @@ -366,7 +365,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = data_create_arabic, data_destroy_arabic, NULL, /* preprocess_text_arabic */ - NULL, /* normalization_preference */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, NULL, /* decompose */ NULL, /* compose */ setup_masks_arabic, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc index d6afa0e1c114..f7f097eedaa3 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc @@ -27,194 +27,18 @@ #include "hb-ot-shape-complex-private.hh" -/* TODO Add kana, and other small shapers here */ - - -/* The default shaper *only* adds additional per-script features.*/ - -static const hb_tag_t hangul_features[] = -{ - HB_TAG('l','j','m','o'), - HB_TAG('v','j','m','o'), - HB_TAG('t','j','m','o'), - HB_TAG_NONE -}; - -static const hb_tag_t tibetan_features[] = -{ - HB_TAG('a','b','v','s'), - HB_TAG('b','l','w','s'), - HB_TAG('a','b','v','m'), - HB_TAG('b','l','w','m'), - HB_TAG_NONE -}; - -static void -collect_features_default (hb_ot_shape_planner_t *plan) -{ - const hb_tag_t *script_features = NULL; - - switch ((hb_tag_t) plan->props.script) - { - /* Unicode-1.1 additions */ - case HB_SCRIPT_HANGUL: - script_features = hangul_features; - break; - - /* Unicode-2.0 additions */ - case HB_SCRIPT_TIBETAN: - script_features = tibetan_features; - break; - } - - for (; script_features && *script_features; script_features++) - plan->map.add_global_bool_feature (*script_features); -} - -static hb_ot_shape_normalization_mode_t -normalization_preference_default (const hb_segment_properties_t *props) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS; -} - -static bool -compose_default (const hb_ot_shape_normalize_context_t *c, - hb_codepoint_t a, - hb_codepoint_t b, - hb_codepoint_t *ab) -{ - /* Hebrew presentation-form shaping. - * https://bugzilla.mozilla.org/show_bug.cgi?id=728866 - * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA; - * Note that some letters do not have a dagesh presForm encoded. - */ - static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = { - 0xFB30, /* ALEF */ - 0xFB31, /* BET */ - 0xFB32, /* GIMEL */ - 0xFB33, /* DALET */ - 0xFB34, /* HE */ - 0xFB35, /* VAV */ - 0xFB36, /* ZAYIN */ - 0x0000, /* HET */ - 0xFB38, /* TET */ - 0xFB39, /* YOD */ - 0xFB3A, /* FINAL KAF */ - 0xFB3B, /* KAF */ - 0xFB3C, /* LAMED */ - 0x0000, /* FINAL MEM */ - 0xFB3E, /* MEM */ - 0x0000, /* FINAL NUN */ - 0xFB40, /* NUN */ - 0xFB41, /* SAMEKH */ - 0x0000, /* AYIN */ - 0xFB43, /* FINAL PE */ - 0xFB44, /* PE */ - 0x0000, /* FINAL TSADI */ - 0xFB46, /* TSADI */ - 0xFB47, /* QOF */ - 0xFB48, /* RESH */ - 0xFB49, /* SHIN */ - 0xFB4A /* TAV */ - }; - - bool found = c->unicode->compose (a, b, ab); - - if (!found && (b & ~0x7F) == 0x0580) { - /* Special-case Hebrew presentation forms that are excluded from - * standard normalization, but wanted for old fonts. */ - switch (b) { - case 0x05B4: /* HIRIQ */ - if (a == 0x05D9) { /* YOD */ - *ab = 0xFB1D; - found = true; - } - break; - case 0x05B7: /* patah */ - if (a == 0x05F2) { /* YIDDISH YOD YOD */ - *ab = 0xFB1F; - found = true; - } else if (a == 0x05D0) { /* ALEF */ - *ab = 0xFB2E; - found = true; - } - break; - case 0x05B8: /* QAMATS */ - if (a == 0x05D0) { /* ALEF */ - *ab = 0xFB2F; - found = true; - } - break; - case 0x05B9: /* HOLAM */ - if (a == 0x05D5) { /* VAV */ - *ab = 0xFB4B; - found = true; - } - break; - case 0x05BC: /* DAGESH */ - if (a >= 0x05D0 && a <= 0x05EA) { - *ab = sDageshForms[a - 0x05D0]; - found = (*ab != 0); - } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */ - *ab = 0xFB2C; - found = true; - } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */ - *ab = 0xFB2D; - found = true; - } - break; - case 0x05BF: /* RAFE */ - switch (a) { - case 0x05D1: /* BET */ - *ab = 0xFB4C; - found = true; - break; - case 0x05DB: /* KAF */ - *ab = 0xFB4D; - found = true; - break; - case 0x05E4: /* PE */ - *ab = 0xFB4E; - found = true; - break; - } - break; - case 0x05C1: /* SHIN DOT */ - if (a == 0x05E9) { /* SHIN */ - *ab = 0xFB2A; - found = true; - } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ - *ab = 0xFB2C; - found = true; - } - break; - case 0x05C2: /* SIN DOT */ - if (a == 0x05E9) { /* SHIN */ - *ab = 0xFB2B; - found = true; - } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ - *ab = 0xFB2D; - found = true; - } - break; - } - } - - return found; -} - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = { "default", - collect_features_default, + NULL, /* collect_features */ NULL, /* override_features */ NULL, /* data_create */ NULL, /* data_destroy */ NULL, /* preprocess_text */ - normalization_preference_default, + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, NULL, /* decompose */ - compose_default, + NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, true, /* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc new file mode 100644 index 000000000000..47aa44fedba1 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc @@ -0,0 +1,417 @@ +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-shape-complex-private.hh" + + +/* Hangul shaper */ + + +/* Same order as the feature array below */ +enum { + NONE, + + LJMO, + VJMO, + TJMO, + + FIRST_HANGUL_FEATURE = LJMO, + HANGUL_FEATURE_COUNT = TJMO + 1 +}; + +static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] = +{ + HB_TAG_NONE, + HB_TAG('l','j','m','o'), + HB_TAG('v','j','m','o'), + HB_TAG('t','j','m','o') +}; + +static void +collect_features_hangul (hb_ot_shape_planner_t *plan) +{ + hb_ot_map_builder_t *map = &plan->map; + + for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++) + map->add_feature (hangul_features[i], 1, F_NONE); +} + +struct hangul_shape_plan_t +{ + ASSERT_POD (); + + hb_mask_t mask_array[HANGUL_FEATURE_COUNT]; +}; + +static void * +data_create_hangul (const hb_ot_shape_plan_t *plan) +{ + hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t)); + if (unlikely (!hangul_plan)) + return NULL; + + for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++) + hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]); + + return hangul_plan; +} + +static void +data_destroy_hangul (void *data) +{ + free (data); +} + +/* Constants for algorithmic hangul syllable [de]composition. */ +#define LBase 0x1100 +#define VBase 0x1161 +#define TBase 0x11A7 +#define LCount 19 +#define VCount 21 +#define TCount 28 +#define SBase 0xAC00 +#define NCount (VCount * TCount) +#define SCount (LCount * NCount) + +#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1)) +#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1)) +#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1)) +#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1)) + +#define isL(u) (hb_in_ranges ((u), 0x1100, 0x115F, 0xA960, 0xA97C)) +#define isV(u) (hb_in_ranges ((u), 0x1160, 0x11A7, 0xD7B0, 0xD7C6)) +#define isT(u) (hb_in_ranges ((u), 0x11A8, 0x11FF, 0xD7CB, 0xD7FB)) + +#define isHangulTone(u) (hb_in_range ((u), 0x302e, 0x302f)) + +/* buffer var allocations */ +#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ + +static bool +is_zero_width_char (hb_font_t *font, + hb_codepoint_t unicode) +{ + hb_codepoint_t glyph; + return hb_font_get_glyph (font, unicode, 0, &glyph) && hb_font_get_glyph_h_advance (font, glyph) == 0; +} + +static void +preprocess_text_hangul (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + HB_BUFFER_ALLOCATE_VAR (buffer, hangul_shaping_feature); + + /* Hangul syllables come in two shapes: LV, and LVT. Of those: + * + * - LV can be precomposed, or decomposed. Lets call those + * and , + * - LVT can be fully precomposed, partically precomposed, or + * fully decomposed. Ie. , , or . + * + * The composition / decomposition is mechanical. However, not + * all sequences compose, and not all sequences + * compose. + * + * Here are the specifics: + * + * - : U+1100..115F, U+A960..A97F + * - : U+1160..11A7, U+D7B0..D7C7 + * - : U+11A8..11FF, U+D7CB..D7FB + * + * - Only the sequences for the 11xx ranges combine. + * - Only sequences for T in U+11A8..11C3 combine. + * + * Here is what we want to accomplish in this shaper: + * + * - If the whole syllable can be precomposed, do that, + * - Otherwise, fully decompose and apply ljmo/vjmo/tjmo features. + * - If a valid syllable is followed by a Hangul tone mark, reorder the tone + * mark to precede the whole syllable - unless it is a zero-width glyph, in + * which case we leave it untouched, assuming it's designed to overstrike. + * + * That is, of the different possible syllables: + * + * + * + * + * + * + * + * + * - needs no work. + * + * - and can stay the way they are if the font supports them, otherwise we + * should fully decompose them if font supports. + * + * - and we should compose if the whole thing can be composed. + * + * - we should compose if the whole thing can be composed, otherwise we should + * decompose. + */ + + buffer->clear_output (); + unsigned int start = 0, end = 0; /* Extent of most recently seen syllable; + * valid only if start < end + */ + unsigned int count = buffer->len; + + for (buffer->idx = 0; buffer->idx < count;) + { + hb_codepoint_t u = buffer->cur().codepoint; + + if (isHangulTone (u)) + { + /* + * We could cache the width of the tone marks and the existence of dotted-circle, + * but the use of the Hangul tone mark characters seems to be rare enough that + * I didn't bother for now. + */ + if (start < end && end == buffer->out_len) + { + /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ + buffer->next_glyph (); + if (!is_zero_width_char (font, u)) + { + hb_glyph_info_t *info = buffer->out_info; + hb_glyph_info_t tone = info[end]; + memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t)); + info[start] = tone; + } + /* Merge clusters across the (possibly reordered) syllable+tone. + * We want to merge even in the zero-width tone mark case here, + * so that clustering behavior isn't dependent on how the tone mark + * is handled by the font. + */ + buffer->merge_out_clusters (start, end + 1); + } + else + { + /* No valid syllable as base for tone mark; try to insert dotted circle. */ + if (font->has_glyph (0x25cc)) + { + hb_codepoint_t chars[2]; + if (!is_zero_width_char (font, u)) { + chars[0] = u; + chars[1] = 0x25cc; + } else { + chars[0] = 0x25cc; + chars[1] = u; + } + buffer->replace_glyphs (1, 2, chars); + } + else + { + /* No dotted circle available in the font; just leave tone mark untouched. */ + buffer->next_glyph (); + } + } + start = end = buffer->out_len; + continue; + } + + start = buffer->out_len; /* Remember current position as a potential syllable start; + * will only be used if we set end to a later position. + */ + + if (isL (u) && buffer->idx + 1 < count) + { + hb_codepoint_t l = u; + hb_codepoint_t v = buffer->cur(+1).codepoint; + if (isV (v)) + { + /* Have or . */ + hb_codepoint_t t = 0; + unsigned int tindex = 0; + if (buffer->idx + 2 < count) + { + t = buffer->cur(+2).codepoint; + if (isT (t)) + tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */ + else + t = 0; /* The next character was not a trailing jamo. */ + } + + /* We've got a syllable ; see if it can potentially be composed. */ + if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t))) + { + /* Try to compose; if this succeeds, end is set to start+1. */ + hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex; + if (font->has_glyph (s)) + { + buffer->replace_glyphs (t ? 3 : 2, 1, &s); + if (unlikely (buffer->in_error)) + return; + end = start + 1; + continue; + } + } + + /* We didn't compose, either because it's an Old Hangul syllable without a + * precomposed character in Unicode, or because the font didn't support the + * necessary precomposed glyph. + * Set jamo features on the individual glyphs, and advance past them. + */ + buffer->cur().hangul_shaping_feature() = LJMO; + buffer->next_glyph (); + buffer->cur().hangul_shaping_feature() = VJMO; + buffer->next_glyph (); + if (t) + { + buffer->cur().hangul_shaping_feature() = TJMO; + buffer->next_glyph (); + end = start + 3; + } + else + end = start + 2; + buffer->merge_out_clusters (start, end); + continue; + } + } + + else if (isCombinedS (u)) + { + /* Have , , or */ + hb_codepoint_t s = u; + bool has_glyph = font->has_glyph (s); + unsigned int lindex = (s - SBase) / NCount; + unsigned int nindex = (s - SBase) % NCount; + unsigned int vindex = nindex / TCount; + unsigned int tindex = nindex % TCount; + + if (!tindex && + buffer->idx + 1 < count && + isCombiningT (buffer->cur(+1).codepoint)) + { + /* , try to combine. */ + unsigned int new_tindex = buffer->cur(+1).codepoint - TBase; + hb_codepoint_t new_s = s + new_tindex; + if (font->has_glyph (new_s)) + { + buffer->replace_glyphs (2, 1, &new_s); + if (unlikely (buffer->in_error)) + return; + end = start + 1; + continue; + } + } + + /* Otherwise, decompose if font doesn't support or , + * or if having non-combining . Note that we already handled + * combining above. */ + if (!has_glyph || + (!tindex && + buffer->idx + 1 < count && + isT (buffer->cur(+1).codepoint))) + { + hb_codepoint_t decomposed[3] = {LBase + lindex, + VBase + vindex, + TBase + tindex}; + if (font->has_glyph (decomposed[0]) && + font->has_glyph (decomposed[1]) && + (!tindex || font->has_glyph (decomposed[2]))) + { + unsigned int s_len = tindex ? 3 : 2; + buffer->replace_glyphs (1, s_len, decomposed); + if (unlikely (buffer->in_error)) + return; + + /* We decomposed S: apply jamo features to the individual glyphs + * that are now in buffer->out_info. + */ + hb_glyph_info_t *info = buffer->out_info; + + /* If we decomposed an LV because of a non-combining T following, + * we want to include this T in the syllable. + */ + if (has_glyph && !tindex) + { + buffer->next_glyph (); + s_len++; + } + end = start + s_len; + + unsigned int i = start; + info[i++].hangul_shaping_feature() = LJMO; + info[i++].hangul_shaping_feature() = VJMO; + if (i < end) + info[i++].hangul_shaping_feature() = TJMO; + buffer->merge_out_clusters (start, end); + continue; + } + } + + if (has_glyph) + { + /* We didn't decompose the S, so just advance past it. */ + end = start + 1; + buffer->next_glyph (); + continue; + } + } + + /* Didn't find a recognizable syllable, so we leave end <= start; + * this will prevent tone-mark reordering happening. + */ + buffer->next_glyph (); + } + buffer->swap_buffers (); +} + +static void +setup_masks_hangul (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font HB_UNUSED) +{ + const hangul_shape_plan_t *hangul_plan = (const hangul_shape_plan_t *) plan->data; + + if (likely (hangul_plan)) + { + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++, info++) + info->mask |= hangul_plan->mask_array[info->hangul_shaping_feature()]; + } + + HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature); +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = +{ + "hangul", + collect_features_hangul, + NULL, /* override_features */ + data_create_hangul, /* data_create */ + data_destroy_hangul, /* data_destroy */ + preprocess_text_hangul, + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, + NULL, /* decompose */ + NULL, /* compose */ + setup_masks_hangul, /* setup_masks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, + false, /* fallback_position */ +}; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc new file mode 100644 index 000000000000..efef8c14adcc --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc @@ -0,0 +1,172 @@ +/* + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-shape-complex-private.hh" + + +static bool +compose_hebrew (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t a, + hb_codepoint_t b, + hb_codepoint_t *ab) +{ + /* Hebrew presentation-form shaping. + * https://bugzilla.mozilla.org/show_bug.cgi?id=728866 + * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA; + * Note that some letters do not have a dagesh presForm encoded. + */ + static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = { + 0xFB30, /* ALEF */ + 0xFB31, /* BET */ + 0xFB32, /* GIMEL */ + 0xFB33, /* DALET */ + 0xFB34, /* HE */ + 0xFB35, /* VAV */ + 0xFB36, /* ZAYIN */ + 0x0000, /* HET */ + 0xFB38, /* TET */ + 0xFB39, /* YOD */ + 0xFB3A, /* FINAL KAF */ + 0xFB3B, /* KAF */ + 0xFB3C, /* LAMED */ + 0x0000, /* FINAL MEM */ + 0xFB3E, /* MEM */ + 0x0000, /* FINAL NUN */ + 0xFB40, /* NUN */ + 0xFB41, /* SAMEKH */ + 0x0000, /* AYIN */ + 0xFB43, /* FINAL PE */ + 0xFB44, /* PE */ + 0x0000, /* FINAL TSADI */ + 0xFB46, /* TSADI */ + 0xFB47, /* QOF */ + 0xFB48, /* RESH */ + 0xFB49, /* SHIN */ + 0xFB4A /* TAV */ + }; + + bool found = c->unicode->compose (a, b, ab); + + if (!found) + { + /* Special-case Hebrew presentation forms that are excluded from + * standard normalization, but wanted for old fonts. */ + switch (b) { + case 0x05B4: /* HIRIQ */ + if (a == 0x05D9) { /* YOD */ + *ab = 0xFB1D; + found = true; + } + break; + case 0x05B7: /* patah */ + if (a == 0x05F2) { /* YIDDISH YOD YOD */ + *ab = 0xFB1F; + found = true; + } else if (a == 0x05D0) { /* ALEF */ + *ab = 0xFB2E; + found = true; + } + break; + case 0x05B8: /* QAMATS */ + if (a == 0x05D0) { /* ALEF */ + *ab = 0xFB2F; + found = true; + } + break; + case 0x05B9: /* HOLAM */ + if (a == 0x05D5) { /* VAV */ + *ab = 0xFB4B; + found = true; + } + break; + case 0x05BC: /* DAGESH */ + if (a >= 0x05D0 && a <= 0x05EA) { + *ab = sDageshForms[a - 0x05D0]; + found = (*ab != 0); + } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */ + *ab = 0xFB2C; + found = true; + } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */ + *ab = 0xFB2D; + found = true; + } + break; + case 0x05BF: /* RAFE */ + switch (a) { + case 0x05D1: /* BET */ + *ab = 0xFB4C; + found = true; + break; + case 0x05DB: /* KAF */ + *ab = 0xFB4D; + found = true; + break; + case 0x05E4: /* PE */ + *ab = 0xFB4E; + found = true; + break; + } + break; + case 0x05C1: /* SHIN DOT */ + if (a == 0x05E9) { /* SHIN */ + *ab = 0xFB2A; + found = true; + } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ + *ab = 0xFB2C; + found = true; + } + break; + case 0x05C2: /* SIN DOT */ + if (a == 0x05E9) { /* SHIN */ + *ab = 0xFB2B; + found = true; + } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ + *ab = 0xFB2D; + found = true; + } + break; + } + } + + return found; +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = +{ + "hebrew", + NULL, /* collect_features */ + NULL, /* override_features */ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + compose_hebrew, + NULL, /* setup_masks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, + true, /* fallback_position */ +}; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc index 9edefe305dc8..1e07d331778f 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc @@ -1690,12 +1690,6 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, } -static hb_ot_shape_normalization_mode_t -normalization_preference_indic (const hb_segment_properties_t *props HB_UNUSED) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; -} - static bool decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, @@ -1806,7 +1800,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = data_create_indic, data_destroy_indic, NULL, /* preprocess_text */ - normalization_preference_indic, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, compose_indic, setup_masks_indic, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc index 25ba7264caed..50209ffb0eee 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc @@ -541,13 +541,6 @@ final_reordering (const hb_ot_shape_plan_t *plan, } -static hb_ot_shape_normalization_mode_t -normalization_preference_myanmar (const hb_segment_properties_t *props HB_UNUSED) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; -} - - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = { "myanmar", @@ -556,7 +549,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = NULL, /* data_create */ NULL, /* data_destroy */ NULL, /* preprocess_text */ - normalization_preference_myanmar, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, NULL, /* decompose */ NULL, /* compose */ setup_masks_myanmar, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh index ac0072ba565c..104726e8af57 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh @@ -44,7 +44,9 @@ enum hb_ot_shape_zero_width_marks_type_t { // HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE + HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, + + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE }; @@ -52,10 +54,13 @@ enum hb_ot_shape_zero_width_marks_type_t { #define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \ HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \ HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \ + HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \ + HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \ HB_COMPLEX_SHAPER_IMPLEMENT (indic) \ HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \ HB_COMPLEX_SHAPER_IMPLEMENT (sea) \ HB_COMPLEX_SHAPER_IMPLEMENT (thai) \ + HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \ /* ^--- Add new shapers here */ @@ -105,12 +110,7 @@ struct hb_ot_complex_shaper_t hb_font_t *font); - /* normalization_preference() - * Called during shape(). - * May be NULL. - */ - hb_ot_shape_normalization_mode_t - (*normalization_preference) (const hb_segment_properties_t *props); + hb_ot_shape_normalization_mode_t normalization_preference; /* decompose() * Called during shape()'s normalization. @@ -189,19 +189,22 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_complex_shaper_thai; -#if 0 - /* Note: - * Currently we don't have a separate Hangul shaper. The default shaper handles - * Hangul by enabling jamo features. We may want to implement a separate shaper - * in the future. See this thread for details of what such a shaper would do: - * - * http://lists.freedesktop.org/archives/harfbuzz/2013-April/003070.html - */ /* Unicode-1.1 additions */ case HB_SCRIPT_HANGUL: return &_hb_ot_complex_shaper_hangul; -#endif + + + /* Unicode-2.0 additions */ + case HB_SCRIPT_TIBETAN: + + return &_hb_ot_complex_shaper_tibetan; + + + /* Unicode-1.1 additions */ + case HB_SCRIPT_HEBREW: + + return &_hb_ot_complex_shaper_hebrew; /* ^--- Add new shapers here */ @@ -241,9 +244,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_LAO: case HB_SCRIPT_THAI: - /* Unicode-2.0 additions */ - case HB_SCRIPT_TIBETAN: - /* Unicode-3.2 additions */ case HB_SCRIPT_TAGALOG: case HB_SCRIPT_TAGBANWA: diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc index da687ed6467c..6288a90c9a9b 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-sea.cc @@ -360,13 +360,6 @@ final_reordering (const hb_ot_shape_plan_t *plan, } -static hb_ot_shape_normalization_mode_t -normalization_preference_sea (const hb_segment_properties_t *props HB_UNUSED) -{ - return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; -} - - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea = { "sea", @@ -375,7 +368,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea = NULL, /* data_create */ NULL, /* data_destroy */ NULL, /* preprocess_text */ - normalization_preference_sea, + HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, NULL, /* decompose */ NULL, /* compose */ setup_masks_sea, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc index 45945339d6b7..8664eca45cd6 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc @@ -369,10 +369,10 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = NULL, /* data_create */ NULL, /* data_destroy */ preprocess_text_thai, - NULL, /* normalization_preference */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ - HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE, + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, false,/* fallback_position */ }; diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc new file mode 100644 index 000000000000..01465a426f8f --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc @@ -0,0 +1,61 @@ +/* + * Copyright © 2010,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-shape-complex-private.hh" + + +static const hb_tag_t tibetan_features[] = +{ + HB_TAG('a','b','v','s'), + HB_TAG('b','l','w','s'), + HB_TAG('a','b','v','m'), + HB_TAG('b','l','w','m'), + HB_TAG_NONE +}; + +static void +collect_features_tibetan (hb_ot_shape_planner_t *plan) +{ + for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++) + plan->map.add_global_bool_feature (*script_features); +} + + +const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan = +{ + "default", + collect_features_tibetan, + NULL, /* override_features */ + NULL, /* data_create */ + NULL, /* data_destroy */ + NULL, /* preprocess_text */ + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, + NULL, /* decompose */ + NULL, /* compose */ + NULL, /* setup_masks */ + HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, + true, /* fallback_position */ +}; diff --git a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc index 449b64e5ca79..5d526c3a8e80 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc @@ -430,14 +430,12 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? - HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n')); - if (!kern_mask) return; + if (!plan->has_kern) return; unsigned int count = buffer->len; OT::hb_apply_context_t c (1, font, buffer); - c.set_lookup_mask (kern_mask); + c.set_lookup_mask (plan->kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); hb_glyph_info_t *info = buffer->info; diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh b/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh index 085d48511d07..c744e26451d3 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-normalize-private.hh @@ -29,8 +29,6 @@ #include "hb-private.hh" -#include "hb-font.h" -#include "hb-buffer.h" /* buffer var allocations, used during the normalization process */ #define glyph_index() var1.u32 @@ -38,6 +36,7 @@ struct hb_ot_shape_plan_t; enum hb_ot_shape_normalization_mode_t { + HB_OT_SHAPE_NORMALIZATION_MODE_NONE, HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED, HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc index 6531e1b215ca..2a6a43900303 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc @@ -213,8 +213,9 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor } static inline void -handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end) +handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) { + /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ hb_buffer_t * const buffer = c->buffer; hb_font_t * const font = c->font; for (; buffer->idx < end - 1;) { @@ -250,27 +251,26 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns } static inline void -decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end) +decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) { hb_buffer_t * const buffer = c->buffer; - /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ for (unsigned int i = buffer->idx; i < end; i++) if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { - handle_variation_selector_cluster (c, end); + handle_variation_selector_cluster (c, end, short_circuit); return; } while (buffer->idx < end) - decompose_current_character (c, false); + decompose_current_character (c, short_circuit); } static inline void -decompose_cluster (const hb_ot_shape_normalize_context_t *c, bool short_circuit, unsigned int end) +decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit) { if (likely (c->buffer->idx + 1 == end)) - decompose_current_character (c, short_circuit); + decompose_current_character (c, might_short_circuit); else - decompose_multi_char_cluster (c, end); + decompose_multi_char_cluster (c, end, always_short_circuit); } @@ -289,9 +289,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, hb_font_t *font) { - hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference ? - plan->shaper->normalization_preference (&buffer->props) : - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT; + hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference; const hb_ot_shape_normalize_context_t c = { plan, buffer, @@ -301,8 +299,10 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, plan->shaper->compose ? plan->shaper->compose : compose_unicode }; - bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && - mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT; + bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE; + bool might_short_circuit = always_short_circuit || + (mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED && + mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT); unsigned int count; /* We do a fairly straightforward yet custom normalization process in three @@ -323,7 +323,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (buffer->cur().cluster != buffer->info[end].cluster) break; - decompose_cluster (&c, short_circuit, end); + decompose_cluster (&c, end, might_short_circuit, always_short_circuit); } buffer->swap_buffers (); @@ -355,7 +355,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, } - if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) + if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE || + mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED) return; /* Third round, recompose */ @@ -393,8 +394,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, return; buffer->merge_out_clusters (starter, buffer->out_len); buffer->out_len--; /* Remove the second composable. */ - buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */ - set_glyph (buffer->out_info[starter], font); + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode); continue; diff --git a/gfx/harfbuzz/src/hb-ot-shape-private.hh b/gfx/harfbuzz/src/hb-ot-shape-private.hh index cbfab5b40c91..df81fa25d97b 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-private.hh @@ -40,6 +40,10 @@ struct hb_ot_shape_plan_t const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_t map; const void *data; + hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask; + hb_mask_t kern_mask; + unsigned int has_frac : 1; + unsigned int has_kern : 1; inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const { @@ -77,6 +81,17 @@ struct hb_ot_shape_planner_t plan.props = props; plan.shaper = shaper; map.compile (plan.map); + + plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); + plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); + plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); + plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); + + plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ? + HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n')); + + plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); + plan.has_kern = !!plan.kern_mask; } private: diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc index 63c36f936fbf..3080a1d03dbf 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.cc +++ b/gfx/harfbuzz/src/hb-ot-shape.cc @@ -88,6 +88,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, break; } + map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE); + map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE); + map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE); + if (planner->shaper->collect_features) planner->shaper->collect_features (planner); @@ -234,8 +238,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) return; - hb_codepoint_t dottedcircle_glyph; - if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph)) + if (!font->has_glyph (0x25CC)) return; hb_glyph_info_t dottedcircle; @@ -292,7 +295,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c) hb_buffer_t *buffer = c->buffer; hb_unicode_funcs_t *unicode = buffer->unicode; - hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); + hb_mask_t rtlm_mask = c->plan->rtlm_mask; unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; @@ -306,13 +309,58 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c) } static inline void -hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) +hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) +{ + if (!c->plan->has_frac) + return; + + hb_buffer_t *buffer = c->buffer; + + /* TODO look in pre/post context text also. */ + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) + { + if (info[i].codepoint == 0x2044) /* FRACTION SLASH */ + { + unsigned int start = i, end = i + 1; + while (start && + _hb_glyph_info_get_general_category (&info[start - 1]) == + HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) + start--; + while (end < count && + _hb_glyph_info_get_general_category (&info[end]) == + HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) + end++; + + for (unsigned int j = start; j < i; j++) + info[j].mask |= c->plan->numr_mask | c->plan->frac_mask; + info[i].mask |= c->plan->frac_mask; + for (unsigned int j = i + 1; j < end; j++) + info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask; + + i = end - 1; + } + } +} + +static inline void +hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c) { hb_ot_map_t *map = &c->plan->map; hb_buffer_t *buffer = c->buffer; hb_mask_t global_mask = map->get_global_mask (); buffer->reset_masks (global_mask); +} + +static inline void +hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) +{ + hb_ot_map_t *map = &c->plan->map; + hb_buffer_t *buffer = c->buffer; + + hb_ot_shape_setup_masks_fraction (c); if (c->plan->shaper->setup_masks) c->plan->shaper->setup_masks (c->plan, buffer, c->font); @@ -358,6 +406,8 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) if (c->plan->shaper->preprocess_text) c->plan->shaper->preprocess_text (c->plan, buffer, c->font); + hb_ot_shape_initialize_masks (c); + hb_ot_mirror_chars (c); HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); diff --git a/gfx/harfbuzz/src/hb-ot-shape.h b/gfx/harfbuzz/src/hb-ot-shape.h new file mode 100644 index 000000000000..afe6fe9618c1 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-shape.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2013 Red Hat, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_SHAPE_H +#define HB_OT_SHAPE_H +#define HB_OT_SHAPE_H_IN + +#include "hb.h" + +#include "hb-ot-layout.h" +#include "hb-ot-tag.h" + +HB_BEGIN_DECLS + +/* TODO port to shape-plan / set. */ +void +hb_ot_shape_glyphs_closure (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + hb_set_t *glyphs); + +void +hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, + hb_tag_t table_tag, + hb_set_t *lookup_indexes /* OUT */); + +HB_END_DECLS + +#undef HB_OT_SHAPE_H_IN +#endif /* HB_OT_SHAPE_H */ diff --git a/gfx/harfbuzz/src/hb-ot-tag.cc b/gfx/harfbuzz/src/hb-ot-tag.cc index d9bc2f6b0aaa..5594ef5074a0 100644 --- a/gfx/harfbuzz/src/hb-ot-tag.cc +++ b/gfx/harfbuzz/src/hb-ot-tag.cc @@ -27,7 +27,6 @@ */ #include "hb-private.hh" -#include "hb-ot.h" #include diff --git a/gfx/harfbuzz/src/hb-ot.h b/gfx/harfbuzz/src/hb-ot.h index 80739063991c..e9a280b7ddae 100644 --- a/gfx/harfbuzz/src/hb-ot.h +++ b/gfx/harfbuzz/src/hb-ot.h @@ -32,17 +32,10 @@ #include "hb-ot-layout.h" #include "hb-ot-tag.h" +#include "hb-ot-shape.h" HB_BEGIN_DECLS -/* TODO remove */ -void -hb_ot_shape_glyphs_closure (hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features, - hb_set_t *glyphs); - HB_END_DECLS #undef HB_OT_H_IN diff --git a/gfx/harfbuzz/src/hb-private.hh b/gfx/harfbuzz/src/hb-private.hh index 4b72260ed5cb..680b21e2cc6c 100644 --- a/gfx/harfbuzz/src/hb-private.hh +++ b/gfx/harfbuzz/src/hb-private.hh @@ -807,6 +807,12 @@ hb_in_range (T u, T lo, T hi) return lo <= u && u <= hi; } +template static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); +} + template static inline bool hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) { diff --git a/gfx/harfbuzz/src/hb-set-private.hh b/gfx/harfbuzz/src/hb-set-private.hh index ca2a07b7619e..705f554ce698 100644 --- a/gfx/harfbuzz/src/hb-set-private.hh +++ b/gfx/harfbuzz/src/hb-set-private.hh @@ -28,7 +28,6 @@ #define HB_SET_PRIVATE_HH #include "hb-private.hh" -#include "hb-set.h" #include "hb-object-private.hh" diff --git a/gfx/harfbuzz/src/hb-shape-plan-private.hh b/gfx/harfbuzz/src/hb-shape-plan-private.hh index e12b05f97b52..607da5e7791d 100644 --- a/gfx/harfbuzz/src/hb-shape-plan-private.hh +++ b/gfx/harfbuzz/src/hb-shape-plan-private.hh @@ -28,7 +28,6 @@ #define HB_SHAPE_PLAN_PRIVATE_HH #include "hb-private.hh" -#include "hb-shape-plan.h" #include "hb-object-private.hh" #include "hb-shaper-private.hh" diff --git a/gfx/harfbuzz/src/hb-shaper-list.hh b/gfx/harfbuzz/src/hb-shaper-list.hh index b9c029e58f1f..da6d8e0be984 100644 --- a/gfx/harfbuzz/src/hb-shaper-list.hh +++ b/gfx/harfbuzz/src/hb-shaper-list.hh @@ -52,4 +52,6 @@ HB_SHAPER_IMPLEMENT (uniscribe) HB_SHAPER_IMPLEMENT (coretext) #endif +#ifdef HAVE_FALLBACK HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ +#endif diff --git a/gfx/harfbuzz/src/hb-tt-font.cc b/gfx/harfbuzz/src/hb-tt-font.cc index c503a404380a..2233a4f1d513 100644 --- a/gfx/harfbuzz/src/hb-tt-font.cc +++ b/gfx/harfbuzz/src/hb-tt-font.cc @@ -31,8 +31,6 @@ #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" -#include "hb-blob.h" - #include diff --git a/gfx/harfbuzz/src/hb-unicode-private.hh b/gfx/harfbuzz/src/hb-unicode-private.hh index dd4d00138e1b..ba193e8fa5bb 100644 --- a/gfx/harfbuzz/src/hb-unicode-private.hh +++ b/gfx/harfbuzz/src/hb-unicode-private.hh @@ -32,8 +32,6 @@ #define HB_UNICODE_PRIVATE_HH #include "hb-private.hh" - -#include "hb-unicode.h" #include "hb-object-private.hh" @@ -108,7 +106,11 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE modified_combining_class (hb_codepoint_t unicode) { /* XXX This hack belongs to the Myanmar shaper. */ - if (unicode == 0x1037) unicode = 0x103A; + if (unlikely (unicode == 0x1037)) unicode = 0x103A; + + /* XXX This hack belongs to the SEA shaper (for Tai Tham): + * Reorder SAKOT to ensure it comes after any tone marks. */ + if (unlikely (unicode == 0x1A60)) return 254; return _hb_modified_combining_class[combining_class (unicode)]; } @@ -132,10 +134,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * 6.3 is also added manually. The new Unicode 6.3 bidi formatting * characters are encoded in a block that was Default_Ignorable already. * - * Note: While U+115F and U+1160 are Default_Ignorable, we do NOT want to - * hide them, as the way Uniscribe has implemented them is with regular - * spacing glyphs, and that's the way fonts are made to work. As such, - * we make exceptions for those two. + * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable, + * we do NOT want to hide them, as the way Uniscribe has implemented them + * is with regular spacing glyphs, and that's the way fonts are made to work. + * As such, we make exceptions for those four. * * Gathered from: * http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on @@ -157,10 +159,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * 200B..200F ;RIGHT-TO-LEFT MARK * 202A..202E ;RIGHT-TO-LEFT OVERRIDE * 2060..206F ;NOMINAL DIGIT SHAPES - * 3164 ;HANGUL FILLER + * #3164 ;HANGUL FILLER * FE00..FE0F ;VARIATION SELECTOR-16 * FEFF ;ZERO WIDTH NO-BREAK SPACE - * FFA0 ;HALFWIDTH HANGUL FILLER + * #FFA0 ;HALFWIDTH HANGUL FILLER * FFF0..FFF8 ; * 1D173..1D17A ;MUSICAL SYMBOL END PHRASE * E0000..E0FFF ; @@ -182,9 +184,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE case 0x20: return hb_in_ranges (ch, 0x200B, 0x200F, 0x202A, 0x202E, 0x2060, 0x206F); - case 0x31: return unlikely (ch == 0x3164); case 0xFE: return hb_in_range (ch, 0xFE00, 0xFE0F) || ch == 0xFEFF; - case 0xFF: return hb_in_range (ch, 0xFFF0, 0xFFF8) || ch == 0xFFA0; + case 0xFF: return hb_in_range (ch, 0xFFF0, 0xFFF8); default: return false; } } diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc index fcb1aa65d4a5..6571448872ae 100644 --- a/gfx/harfbuzz/src/hb-uniscribe.cc +++ b/gfx/harfbuzz/src/hb-uniscribe.cc @@ -709,7 +709,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < range_records.len; i++) { range_record_t *range = &range_records[i]; - range->props.potfRecords = feature_records.array + reinterpret_cast (range->props.potfRecords); + range->props.potfRecords = feature_records.array + reinterpret_cast (range->props.potfRecords); } } else @@ -776,13 +776,14 @@ retry: } } - /* All the following types are sized in multiples of sizeof(int). */ - unsigned int glyphs_size = scratch_size / ((sizeof (WORD) + - sizeof (SCRIPT_GLYPHPROP) + - sizeof (int) + - sizeof (GOFFSET) + - sizeof (uint32_t)) - / sizeof (int)); + /* The -2 in the following is to compensate for possible + * alignment needed after the WORD array. sizeof(WORD) == 2. */ + unsigned int glyphs_size = (scratch_size * sizeof (int) - 2) + / (sizeof (WORD) + + sizeof (SCRIPT_GLYPHPROP) + + sizeof (int) + + sizeof (GOFFSET) + + sizeof (uint32_t)); ALLOCATE_ARRAY (WORD, glyphs, glyphs_size); ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size); diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h index 5f83b13671c5..790e0ecbaee1 100644 --- a/gfx/harfbuzz/src/hb-version.h +++ b/gfx/harfbuzz/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 0 #define HB_VERSION_MINOR 9 -#define HB_VERSION_MICRO 24 +#define HB_VERSION_MICRO 25 -#define HB_VERSION_STRING "0.9.24" +#define HB_VERSION_STRING "0.9.25" #define HB_VERSION_CHECK(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) >= \ diff --git a/gfx/harfbuzz/src/moz.build b/gfx/harfbuzz/src/moz.build index 632545ce1c62..4b8c3b535685 100644 --- a/gfx/harfbuzz/src/moz.build +++ b/gfx/harfbuzz/src/moz.build @@ -12,6 +12,7 @@ EXPORTS.harfbuzz += [ 'hb-face.h', 'hb-font.h', 'hb-ot-layout.h', + 'hb-ot-shape.h', 'hb-ot-tag.h', 'hb-ot.h', 'hb-set.h', @@ -25,6 +26,7 @@ EXPORTS.harfbuzz += [ SOURCES += [ 'hb-blob.cc', # error: use of undeclared identifier 'snprintf' (FreeBSD) 'hb-common.cc', # error: use of undeclared identifier 'strdup' + 'hb-ot-shape-complex-hangul.cc', # error: redefinition of enumerator 'NONE' 'hb-ot-shape-complex-indic.cc', # error: redefinition of enumerator 'INIT' 'hb-ot-shape-complex-sea.cc', # error: redefinition of 'basic_features' 'hb-ot-shape.cc', # error: functions that differ only in their return type cannot be overloaded @@ -40,9 +42,11 @@ UNIFIED_SOURCES += [ 'hb-ot-map.cc', 'hb-ot-shape-complex-arabic.cc', 'hb-ot-shape-complex-default.cc', + 'hb-ot-shape-complex-hebrew.cc', 'hb-ot-shape-complex-indic-table.cc', 'hb-ot-shape-complex-myanmar.cc', 'hb-ot-shape-complex-thai.cc', + 'hb-ot-shape-complex-tibetan.cc', 'hb-ot-shape-fallback.cc', 'hb-ot-shape-normalize.cc', 'hb-ot-tag.cc', From 135b65feab51f44fa5dcfd19fbe093eb1818c403 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 30 Jan 2014 09:48:37 +0000 Subject: [PATCH 27/88] bug 964313 - use harfbuzz for all text shaping (now including Hangul) on Windows. r=jdaggett --- modules/libpref/src/init/all.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 3893584eb823..32256cdbeb34 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -365,17 +365,9 @@ pref("gfx.font_rendering.graphite.enabled", true); // (see http://mxr.mozilla.org/mozilla-central/ident?i=ShapingType) // Scripts not listed are grouped in the default category. // Set the pref to 255 to have all text shaped via the harfbuzz backend. -#ifdef XP_WIN -// Use harfbuzz for everything except Hangul (0x08). Harfbuzz doesn't yet -// have a Hangul shaper, which means that the marks U+302E/302F would not -// reorder properly in Malgun Gothic or similar fonts. -pref("gfx.font_rendering.harfbuzz.scripts", 247); -#else -// Use harfbuzz for all scripts (except when using AAT fonts on OS X). -// AFAICT, Core Text doesn't support full OpenType Hangul shaping anyway, -// so there's no benefit to excluding it here. +// Default setting: +// We use harfbuzz for all scripts (except when using AAT fonts on OS X). pref("gfx.font_rendering.harfbuzz.scripts", 255); -#endif #ifdef XP_WIN pref("gfx.font_rendering.directwrite.enabled", false); From b6b3cfcc16794047e841921181b699e731a1fcac Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 30 Jan 2014 11:07:57 +0100 Subject: [PATCH 28/88] Bug 965243 - Remove dead constructor of ScopeIter r=jorendorff --HG-- extra : amend_source : e11741d6b1e4baeaa08df1e041df303055d68634 --- js/src/vm/ScopeObject.cpp | 38 -------------------------------------- js/src/vm/ScopeObject.h | 4 ---- 2 files changed, 42 deletions(-) diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 59ba37444c5b..0c1e1da7209a 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -899,44 +899,6 @@ ScopeIter::ScopeIter(const ScopeIterVal &val, JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_INIT; } -ScopeIter::ScopeIter(AbstractFramePtr frame, jsbytecode *pc, ScopeObject &scope, JSContext *cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) - : cx(cx), - frame_(frame), - cur_(cx, &scope), - block_(cx) -{ - /* - * Find the appropriate static block for this iterator, given 'scope'. We - * know that 'scope' is a (non-optimized) scope on fp's scope chain. We do - * not, however, know whether fp->maybeScopeChain() encloses 'scope'. E.g.: - * - * let (x = 1) { - * g = function() { eval('debugger') }; - * let (y = 1) g(); - * } - * - * g will have x's block in its enclosing scope but not y's. However, at the - * debugger statement, both the x's and y's blocks will be on the block - * chain. Fortunately, we can compare scope object stack depths to determine - * the block (if any) that encloses 'scope'. - */ - if (cur_->is()) { - block_ = frame.script()->getBlockScope(pc); - while (block_) { - if (block_->stackDepth() <= cur_->as().stackDepth()) - break; - block_ = block_->enclosingBlock(); - } - JS_ASSERT_IF(cur_->is(), - cur_->as().staticBlock() == *block_); - } else { - block_ = nullptr; - } - settle(); - MOZ_GUARD_OBJECT_NOTIFIER_INIT; -} - ScopeObject & ScopeIter::scope() const { diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index bdb5110dc084..6f4834b9407a 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -575,10 +575,6 @@ class ScopeIter ScopeIter(JSObject &enclosingScope, JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM); - /* Like ScopeIter(StackFrame *) except start at 'scope'. */ - ScopeIter(AbstractFramePtr frame, jsbytecode *pc, ScopeObject &scope, JSContext *cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM); - ScopeIter(const ScopeIterVal &hashVal, JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM); From 02870ebbdd857aa5b70825b475bc1da60a03bfed Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Thu, 30 Jan 2014 20:00:01 +0900 Subject: [PATCH 29/88] Bug 964964 - Remove window.pkcs11. r=bz --- dom/base/nsGlobalWindow.cpp | 7 ------- dom/base/nsGlobalWindow.h | 4 ---- dom/bindings/Bindings.conf | 1 - dom/interfaces/base/domstubs.idl | 1 - dom/interfaces/base/moz.build | 1 - dom/interfaces/base/nsIDOMPkcs11.idl | 16 ---------------- dom/interfaces/base/nsIDOMWindow.idl | 3 +-- dom/webidl/Window.webidl | 3 --- 8 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 dom/interfaces/base/nsIDOMPkcs11.idl diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8050d9659ba5..3a20cab61d10 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4168,13 +4168,6 @@ nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto) return rv.ErrorCode(); } -NS_IMETHODIMP -nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11) -{ - *aPkcs11 = nullptr; - return NS_OK; -} - nsIControllers* nsGlobalWindow::GetControllers(ErrorResult& aError) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 24057e7ae1ee..a12d5bbabbe1 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -909,10 +909,6 @@ public: int64_t GetMozAnimationStartTime(mozilla::ErrorResult& aError); void SizeToContent(mozilla::ErrorResult& aError); nsIDOMCrypto* GetCrypto(mozilla::ErrorResult& aError); - nsIDOMPkcs11* GetPkcs11() - { - return nullptr; - } nsIControllers* GetControllers(mozilla::ErrorResult& aError); float GetMozInnerScreenX(mozilla::ErrorResult& aError); float GetMozInnerScreenY(mozilla::ErrorResult& aError); diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index ae4a061748bd..d3b52e084ef1 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1935,7 +1935,6 @@ addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True) addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True) addExternalIface('OutputStream', nativeType='nsIOutputStream', notflattened=True) -addExternalIface('Pkcs11') addExternalIface('Principal', nativeType='nsIPrincipal', headerFile='nsIPrincipal.h', notflattened=True) addExternalIface('StackFrame', nativeType='nsIStackFrame', diff --git a/dom/interfaces/base/domstubs.idl b/dom/interfaces/base/domstubs.idl index 14d8d8134ed1..4a6c4702be0e 100644 --- a/dom/interfaces/base/domstubs.idl +++ b/dom/interfaces/base/domstubs.idl @@ -77,7 +77,6 @@ interface nsIDOMRange; // Crypto interface nsIDOMCrypto; -interface nsIDOMPkcs11; // Used font face (for inspector) interface nsIDOMFontFace; diff --git a/dom/interfaces/base/moz.build b/dom/interfaces/base/moz.build index fd7f03af5619..bcc90e7e0532 100644 --- a/dom/interfaces/base/moz.build +++ b/dom/interfaces/base/moz.build @@ -23,7 +23,6 @@ XPIDL_SOURCES += [ 'nsIDOMLocation.idl', 'nsIDOMModalContentWindow.idl', 'nsIDOMNavigator.idl', - 'nsIDOMPkcs11.idl', 'nsIDOMScreen.idl', 'nsIDOMWindow.idl', 'nsIDOMWindowCollection.idl', diff --git a/dom/interfaces/base/nsIDOMPkcs11.idl b/dom/interfaces/base/nsIDOMPkcs11.idl deleted file mode 100644 index 9811cbc17943..000000000000 --- a/dom/interfaces/base/nsIDOMPkcs11.idl +++ /dev/null @@ -1,16 +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 "domstubs.idl" - -[scriptable, uuid(9fd42950-25e7-11d4-8a7d-006008c844c3)] -interface nsIDOMPkcs11 : nsISupports -{ - long deletemodule(in DOMString moduleName); - long addmodule(in DOMString moduleName, - in DOMString libraryFullPath, - in long cryptoMechanismFlags, - in long cipherFlags); -}; diff --git a/dom/interfaces/base/nsIDOMWindow.idl b/dom/interfaces/base/nsIDOMWindow.idl index e64ad3598026..78c056bcb286 100644 --- a/dom/interfaces/base/nsIDOMWindow.idl +++ b/dom/interfaces/base/nsIDOMWindow.idl @@ -24,7 +24,7 @@ interface nsIVariant; * @see */ -[scriptable, uuid(f2d1d383-f7b5-46f8-aadf-b69a0ebfb16f)] +[scriptable, uuid(97b6784b-ab12-4f79-8422-d7868a4cc7dc)] interface nsIDOMWindow : nsISupports { // the current browsing context @@ -374,7 +374,6 @@ interface nsIDOMWindow : nsISupports readonly attribute boolean closed; readonly attribute nsIDOMCrypto crypto; - readonly attribute nsIDOMPkcs11 pkcs11; // Note: this is [ChromeOnly] scriptable via WebIDL. [noscript] readonly attribute nsIControllers controllers; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index b783e5a7c70c..1b8409897f7f 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -18,7 +18,6 @@ interface ApplicationCache; interface MozFrameRequestCallback; interface nsIDOMCrypto; -interface Pkcs11; typedef any Transferable; // http://www.whatwg.org/specs/web-apps/current-work/ @@ -257,8 +256,6 @@ partial interface Window { */ [Throws] void sizeToContent(); - readonly attribute Pkcs11? pkcs11; - // XXX Shouldn't this be in nsIDOMChromeWindow? [ChromeOnly, Replaceable, Throws] readonly attribute MozControllers controllers; From df4bd6bd7683c65859c4d40d1b5cd9cc5d18aac9 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 30 Jan 2014 12:12:02 +0000 Subject: [PATCH 30/88] Bug 964726 - (Windows/OS2 only) Don't handle CTRL+F4 as a combobox command, so that it works as Close Tab as intended. r=bz --- layout/forms/nsListControlFrame.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 89a3028831fe..93ac78e15bfe 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -2203,7 +2203,9 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent) #if defined(XP_WIN) || defined(XP_OS2) case NS_VK_F4: - DropDownToggleKey(aKeyEvent); + if (!isControlOrMeta) { + DropDownToggleKey(aKeyEvent); + } return NS_OK; #endif From 0e6b7fff02b5a1a9d794fa36ad58e80db534ded6 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 30 Jan 2014 12:12:02 +0000 Subject: [PATCH 31/88] Bug 959311 - Splitting nsComboboxControlFrame makes no sense so it should always report COMPLETE reflow status. Also, make them page-break-inside:avoid by default. r=bz --- layout/forms/crashtests/959311.html | 17 +++++++++++++++++ layout/forms/crashtests/crashtests.list | 1 + layout/forms/nsComboboxControlFrame.cpp | 6 ++++++ .../combobox-page-break-inside-ref.html | 17 +++++++++++++++++ .../pagination/combobox-page-break-inside.html | 17 +++++++++++++++++ layout/reftests/pagination/reftest.list | 1 + layout/style/forms.css | 1 + 7 files changed, 60 insertions(+) create mode 100644 layout/forms/crashtests/959311.html create mode 100644 layout/reftests/pagination/combobox-page-break-inside-ref.html create mode 100644 layout/reftests/pagination/combobox-page-break-inside.html diff --git a/layout/forms/crashtests/959311.html b/layout/forms/crashtests/959311.html new file mode 100644 index 000000000000..c646b84f7a89 --- /dev/null +++ b/layout/forms/crashtests/959311.html @@ -0,0 +1,17 @@ + + + + + + + +
+ + + diff --git a/layout/forms/crashtests/crashtests.list b/layout/forms/crashtests/crashtests.list index 548b99247973..5c850462628e 100644 --- a/layout/forms/crashtests/crashtests.list +++ b/layout/forms/crashtests/crashtests.list @@ -54,4 +54,5 @@ load 682684.xhtml load 865602.html load 944198.html load 949891.xhtml +load 959311.html load 960277-2.html diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 0b4714ed6023..9682ef23a963 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -866,6 +866,12 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, buttonRect.width = buttonWidth; mButtonFrame->SetRect(buttonRect); + if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) && + !NS_FRAME_IS_FULLY_COMPLETE(aStatus)) { + // This frame didn't fit inside a fragmentation container. Splitting + // a nsComboboxControlFrame makes no sense, so we override the status here. + aStatus = NS_FRAME_COMPLETE; + } return rv; } diff --git a/layout/reftests/pagination/combobox-page-break-inside-ref.html b/layout/reftests/pagination/combobox-page-break-inside-ref.html new file mode 100644 index 000000000000..c8a7733cd19a --- /dev/null +++ b/layout/reftests/pagination/combobox-page-break-inside-ref.html @@ -0,0 +1,17 @@ + + + + + + + +
+ + + diff --git a/layout/reftests/pagination/combobox-page-break-inside.html b/layout/reftests/pagination/combobox-page-break-inside.html new file mode 100644 index 000000000000..f573a1c9f6ff --- /dev/null +++ b/layout/reftests/pagination/combobox-page-break-inside.html @@ -0,0 +1,17 @@ + + + + + + + +
+ + + diff --git a/layout/reftests/pagination/reftest.list b/layout/reftests/pagination/reftest.list index 86a14254cd8b..2d94e7d66fd6 100644 --- a/layout/reftests/pagination/reftest.list +++ b/layout/reftests/pagination/reftest.list @@ -60,3 +60,4 @@ skip-if(B2G) == table-caption-splitaftercaption-7.html table-caption-splitafterc # == table-caption-splitaftercaption-10.html blank.html # bug 672654 # == table-caption-splitaftercaption-11.html blank.html # bug 672654 == column-balancing-break-inside-avoid-2.html column-balancing-break-inside-avoid-2-ref.html +== combobox-page-break-inside.html combobox-page-break-inside-ref.html diff --git a/layout/style/forms.css b/layout/style/forms.css index 66dd66cb3261..4bb0fa5c3d15 100644 --- a/layout/style/forms.css +++ b/layout/style/forms.css @@ -206,6 +206,7 @@ select { text-shadow: none; /* No text-decoration reaching inside, by default */ display: inline-block; + page-break-inside: avoid; } /* Need the "select[size][multiple]" selector to override the settings on From cf6bacb02cb87a161dc8dbb0cb0899fce3cfbabc Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Thu, 30 Jan 2014 14:39:25 +0200 Subject: [PATCH 32/88] Bug 959061 - Have only one "Chinese, Simplified" item in the Character Encoding menu. r=Unfocused. --- browser/base/content/browser.js | 15 +++++++++++++-- .../components/viewsource/content/viewSource.js | 13 ++++++++++++- .../en-US/chrome/global/charsetMenu.properties | 9 +++++++++ toolkit/modules/CharsetMenu.jsm | 9 ++++++++- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 8f1a3477a49a..fd8758cb8983 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -5221,12 +5221,23 @@ function UpdateCurrentCharset(target) { pref_item.setAttribute('checked', 'false'); } - var menuitem = charsetMenuGetElement(target, "charset." + wnd.document.characterSet); + var menuitem = charsetMenuGetElement(target, "charset." + FoldCharset(wnd.document.characterSet)); if (menuitem) { menuitem.setAttribute('checked', 'true'); } } +function FoldCharset(charset) { + // For substantially similar encodings, treat two encodings as the same + // for the purpose of the check mark. + if (charset == "ISO-8859-8-I") { + return "windows-1255"; + } else if (charset == "gb18030") { + return "gbk"; + } + return charset; +} + function UpdateCharsetDetector(target) { var prefvalue; @@ -5249,7 +5260,7 @@ function UpdateMenus(event) { } function charsetLoadListener() { - var charset = window.content.document.characterSet; + var charset = FoldCharset(window.content.document.characterSet); if (charset.length > 0 && (charset != gLastBrowserCharset)) { gPrevCharset = gLastBrowserCharset; diff --git a/toolkit/components/viewsource/content/viewSource.js b/toolkit/components/viewsource/content/viewSource.js index 3067c746bf84..715cbfabc1d2 100644 --- a/toolkit/components/viewsource/content/viewSource.js +++ b/toolkit/components/viewsource/content/viewSource.js @@ -697,8 +697,19 @@ function SelectDetector(event) } } +function FoldCharset(charset) { + // For substantially similar encodings, treat two encodings as the same + // for the purpose of the check mark. + if (charset == "ISO-8859-8-I") { + return "windows-1255"; + } else if (charset == "gb18030") { + return "gbk"; + } + return charset; +} + function UpdateCurrentCharset() { - var menuitem = document.getElementById("charset." + content.document.characterSet); + var menuitem = document.getElementById("charset." + FoldCharset(content.document.characterSet)); if (menuitem) menuitem.setAttribute("checked", "true"); } diff --git a/toolkit/locales/en-US/chrome/global/charsetMenu.properties b/toolkit/locales/en-US/chrome/global/charsetMenu.properties index e37260d1cdc6..5ed954f760d3 100644 --- a/toolkit/locales/en-US/chrome/global/charsetMenu.properties +++ b/toolkit/locales/en-US/chrome/global/charsetMenu.properties @@ -6,6 +6,9 @@ # Localizations may add or delete properties where the property key ends with # ".key" as appropriate for the localization. The code that uses this data can # deal with the absence of an access key for an item. +# +# For gbk, gbk.bis and gbk.bis.key are used to trigger string changes in +# localizations. # # Make sure the keys defined here don't collide with # charsetMenuAutodet.accesskey in charsetMenu.dtd. @@ -61,6 +64,12 @@ ISO-8859-2.key = l ISO-8859-2 = Central European (ISO) # Chinese, Simplified +# LOCALIZATION NOTE (gbk.bis.key): +# gbk.bis.key never appears together with gbk.key and, hence, can be the same. +gbk.bis.key = S +gbk.bis = Chinese, Simplified +# The strings gbk.key, gbk and gb18030 are no longer used but are retained +# in order to enable backout after string freeze, just in case. gbk.key = S gbk = Chinese, Simplified (GBK) gb18030 = Chinese, Simplified (GB18030) diff --git a/toolkit/modules/CharsetMenu.jsm b/toolkit/modules/CharsetMenu.jsm index 5dbaf01e8f77..058715f1efbb 100644 --- a/toolkit/modules/CharsetMenu.jsm +++ b/toolkit/modules/CharsetMenu.jsm @@ -44,7 +44,6 @@ const kEncodings = new Set([ "ISO-8859-2", // Chinese, Simplified "gbk", - "gb18030", // Chinese, Traditional "Big5", // Cyrillic @@ -217,12 +216,20 @@ let CharsetMenu = { }, _getCharsetLabel: function(charset) { + if (charset == "gbk") { + // Localization key has been revised + charset = "gbk.bis"; + } try { return gBundle.GetStringFromName(charset); } catch (ex) {} return charset; }, _getCharsetAccessKey: function(charset) { + if (charset == "gbk") { + // Localization key has been revised + charset = "gbk.bis"; + } try { accesskey = gBundle.GetStringFromName(charset + ".key"); } catch (ex) {} From 7c745b83df0621a973435c5c95a5af0bdd63b135 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Thu, 30 Jan 2014 04:45:48 -0800 Subject: [PATCH 33/88] Bug 964293 - Implement Cu.cloneInto() method, r=bholley --- dom/base/StructuredCloneTags.h | 2 + dom/datastore/DataStore.jsm | 3 +- dom/datastore/DataStoreCursor.jsm | 25 ++- js/src/jsfriendapi.cpp | 1 + js/xpconnect/idl/xpccomponents.idl | 12 +- js/xpconnect/src/Sandbox.cpp | 11 ++ js/xpconnect/src/XPCComponents.cpp | 159 +++++++++++++++++++ js/xpconnect/src/xpcprivate.h | 4 + js/xpconnect/tests/chrome/chrome.ini | 1 + js/xpconnect/tests/chrome/test_cloneInto.xul | 140 ++++++++++++++++ 10 files changed, 342 insertions(+), 16 deletions(-) create mode 100644 js/xpconnect/tests/chrome/test_cloneInto.xul diff --git a/dom/base/StructuredCloneTags.h b/dom/base/StructuredCloneTags.h index 533d39f1b5e1..8c9523c052ac 100644 --- a/dom/base/StructuredCloneTags.h +++ b/dom/base/StructuredCloneTags.h @@ -30,6 +30,8 @@ enum StructuredCloneTags { SCTAG_DOM_IMAGEDATA, SCTAG_DOM_MESSAGEPORT, + SCTAG_DOM_FUNCTION, + SCTAG_DOM_MAX }; diff --git a/dom/datastore/DataStore.jsm b/dom/datastore/DataStore.jsm index a4418d3f8570..0166d6a3869e 100644 --- a/dom/datastore/DataStore.jsm +++ b/dom/datastore/DataStore.jsm @@ -25,7 +25,6 @@ const MAX_REQUESTS = 25; Cu.import("resource://gre/modules/DataStoreCursor.jsm"); Cu.import("resource://gre/modules/DataStoreDB.jsm"); -Cu.import("resource://gre/modules/ObjectWrapper.jsm"); Cu.import('resource://gre/modules/Services.jsm'); Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.importGlobalProperties(["indexedDB"]); @@ -142,7 +141,7 @@ this.DataStore.prototype = { function getInternalSuccess(aEvent, aPos) { debug("GetInternal success. Record: " + aEvent.target.result); - results[aPos] = ObjectWrapper.wrap(aEvent.target.result, self._window); + results[aPos] = Cu.cloneInto(aEvent.target.result, self._window); if (!--pendingIds) { aCallback(results); return; diff --git a/dom/datastore/DataStoreCursor.jsm b/dom/datastore/DataStoreCursor.jsm index c40421159150..06e7d81f6061 100644 --- a/dom/datastore/DataStoreCursor.jsm +++ b/dom/datastore/DataStoreCursor.jsm @@ -27,7 +27,6 @@ const REVISION_REMOVED = 'removed'; const REVISION_VOID = 'void'; const REVISION_SKIP = 'skip' -Cu.import('resource://gre/modules/ObjectWrapper.jsm'); Cu.import('resource://gre/modules/XPCOMUtils.jsm'); /** @@ -151,7 +150,7 @@ this.DataStoreCursor.prototype = { self._revision = aEvent.target.result.value; self._objectId = 0; self._state = STATE_SEND_ALL; - aResolve(ObjectWrapper.wrap({ operation: 'clear' }, self._window)); + aResolve(Cu.cloneInto({ operation: 'clear' }, self._window)); } }, @@ -291,7 +290,7 @@ this.DataStoreCursor.prototype = { if (self._revision.revisionId != aEvent.target.result.value.revisionId) { self._revision = aEvent.target.result.value; self._objectId = 0; - aResolve(ObjectWrapper.wrap({ operation: 'clear' }, self._window)); + aResolve(Cu.cloneInto({ operation: 'clear' }, self._window)); return; } @@ -305,8 +304,8 @@ this.DataStoreCursor.prototype = { } self._objectId = cursor.key; - aResolve(ObjectWrapper.wrap({ operation: 'add', id: self._objectId, - data: cursor.value }, self._window)); + aResolve(Cu.cloneInto({ operation: 'add', id: self._objectId, + data: cursor.value }, self._window)); }; }; }, @@ -324,8 +323,8 @@ this.DataStoreCursor.prototype = { switch (this._revision.operation) { case REVISION_REMOVED: - aResolve(ObjectWrapper.wrap({ operation: 'remove', id: this._revision.objectId }, - this._window)); + aResolve(Cu.cloneInto({ operation: 'remove', id: this._revision.objectId }, + this._window)); break; case REVISION_ADDED: { @@ -337,8 +336,8 @@ this.DataStoreCursor.prototype = { return; } - aResolve(ObjectWrapper.wrap({ operation: 'add', id: self._revision.objectId, - data: aEvent.target.result }, self._window)); + aResolve(Cu.cloneInto({ operation: 'add', id: self._revision.objectId, + data: aEvent.target.result }, self._window)); } break; } @@ -357,8 +356,8 @@ this.DataStoreCursor.prototype = { return; } - aResolve(ObjectWrapper.wrap({ operation: 'update', id: self._revision.objectId, - data: aEvent.target.result }, self._window)); + aResolve(Cu.cloneInto({ operation: 'update', id: self._revision.objectId, + data: aEvent.target.result }, self._window)); } break; } @@ -377,8 +376,8 @@ this.DataStoreCursor.prototype = { stateMachineDone: function(aStore, aRevisionStore, aResolve, aReject) { this.close(); - aResolve(ObjectWrapper.wrap({ revisionId: this._revision.revisionId, - operation: 'done' }, this._window)); + aResolve(Cu.cloneInto({ revisionId: this._revision.revisionId, + operation: 'done' }, this._window)); }, // public interface diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 600ed0955f00..8b481dc6b778 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -541,6 +541,7 @@ JS_FRIEND_API(void) js::SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val) { JS_ASSERT(fun->as().isNative()); + MOZ_ASSERT_IF(val.isObject(), val.toObject().compartment() == fun->compartment()); fun->as().setExtendedSlot(which, val); } diff --git a/js/xpconnect/idl/xpccomponents.idl b/js/xpconnect/idl/xpccomponents.idl index 3138e604b994..a3e3937aeb5a 100644 --- a/js/xpconnect/idl/xpccomponents.idl +++ b/js/xpconnect/idl/xpccomponents.idl @@ -120,7 +120,7 @@ interface ScheduledGCCallback : nsISupports /** * interface of Components.utils */ -[scriptable, uuid(c9ab0d20-8499-11e3-baa7-0800200c9a66)] +[scriptable, uuid(cd4bccf4-3433-492e-8dfd-dfdb3fe9efa1)] interface nsIXPCComponents_Utils : nsISupports { @@ -551,6 +551,16 @@ interface nsIXPCComponents_Utils : nsISupports [implicit_jscontext] jsval getJSEngineTelemetryValue(); + + /* + * Clone an object into a scope. + * The 3rd argument is an optional options object: + * - cloneFunction: boolean. If true, any function in the value is are + * wrapped in a function forwarder that appears to be a native function in + * the content scope. + */ + [implicit_jscontext] + jsval cloneInto(in jsval value, in jsval scope, [optional] in jsval options); }; /** diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index 7a686e64b22f..7ae4da47fa01 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -1804,6 +1804,17 @@ xpc::NewFunctionForwarder(JSContext *cx, HandleId id, HandleObject callable, boo return true; } +bool +xpc::NewFunctionForwarder(JSContext *cx, HandleObject callable, bool doclone, + MutableHandleValue vp) +{ + RootedId emptyId(cx); + if (!JS_ValueToId(cx, JS_GetEmptyStringValue(cx), &emptyId)) + return false; + + return NewFunctionForwarder(cx, emptyId, callable, doclone, vp); +} + nsresult xpc::GetSandboxMetadata(JSContext *cx, HandleObject sandbox, MutableHandleValue rval) diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index ccea79d8f300..4140e9bbe1a7 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -15,13 +15,17 @@ #include "mozJSComponentLoader.h" #include "nsContentUtils.h" #include "jsfriendapi.h" +#include "js/StructuredClone.h" #include "mozilla/Attributes.h" #include "nsJSEnvironment.h" #include "mozilla/XPTInterfaceInfoManager.h" #include "mozilla/dom/DOMException.h" #include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/StructuredCloneTags.h" #include "nsZipArchive.h" +#include "nsIDOMFile.h" +#include "nsIDOMFileList.h" using namespace mozilla; using namespace JS; @@ -3465,6 +3469,161 @@ nsXPCComponents_Utils::GetJSEngineTelemetryValue(JSContext *cx, MutableHandleVal return NS_OK; } +class MOZ_STACK_CLASS CloneIntoOptions : public OptionsBase +{ +public: + CloneIntoOptions(JSContext *cx = xpc_GetSafeJSContext(), + JSObject *options = nullptr) + : OptionsBase(cx, options) + , cloneFunctions(false) + {} + + virtual bool Parse() + { + return ParseBoolean("cloneFunctions", &cloneFunctions); + } + + bool cloneFunctions; +}; + +class MOZ_STACK_CLASS CloneIntoCallbacksData +{ +public: + CloneIntoCallbacksData(JSContext *aCx, CloneIntoOptions *aOptions) + : mOptions(aOptions) + , mFunctions(aCx) + {} + + CloneIntoOptions *mOptions; + AutoObjectVector mFunctions; +}; + +static JSObject* +CloneIntoReadStructuredClone(JSContext *cx, + JSStructuredCloneReader *reader, + uint32_t tag, + uint32_t value, + void* closure) +{ + CloneIntoCallbacksData* data = static_cast(closure); + MOZ_ASSERT(data); + + if (tag == mozilla::dom::SCTAG_DOM_BLOB || tag == mozilla::dom::SCTAG_DOM_FILELIST) { + MOZ_ASSERT(!value, "Data should be empty"); + + nsISupports *supports; + if (JS_ReadBytes(reader, &supports, sizeof(supports))) { + RootedObject global(cx, CurrentGlobalOrNull(cx)); + if (global) { + RootedValue val(cx); + if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports, &val))) + return val.toObjectOrNull(); + } + } + } + + if (tag == mozilla::dom::SCTAG_DOM_FUNCTION) { + MOZ_ASSERT(value < data->mFunctions.length()); + + RootedValue functionValue(cx); + RootedObject obj(cx, data->mFunctions[value]); + + if (!JS_WrapObject(cx, &obj)) + return nullptr; + + if (!xpc::NewFunctionForwarder(cx, obj, false, &functionValue)) + return nullptr; + + return &functionValue.toObject(); + } + + return nullptr; +} + +static bool +CloneIntoWriteStructuredClone(JSContext *cx, + JSStructuredCloneWriter *writer, + HandleObject obj, + void *closure) +{ + CloneIntoCallbacksData* data = static_cast(closure); + MOZ_ASSERT(data); + + nsCOMPtr wrappedNative; + nsContentUtils::XPConnect()->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative)); + if (wrappedNative) { + uint32_t scTag = 0; + nsISupports *supports = wrappedNative->Native(); + + nsCOMPtr blob = do_QueryInterface(supports); + if (blob) + scTag = mozilla::dom::SCTAG_DOM_BLOB; + else { + nsCOMPtr list = do_QueryInterface(supports); + if (list) + scTag = mozilla::dom::SCTAG_DOM_FILELIST; + } + + if (scTag) { + return JS_WriteUint32Pair(writer, scTag, 0) && + JS_WriteBytes(writer, &supports, sizeof(supports)); + } + } + + if (data->mOptions->cloneFunctions && JS_ObjectIsCallable(cx, obj)) { + data->mFunctions.append(obj); + return JS_WriteUint32Pair(writer, mozilla::dom::SCTAG_DOM_FUNCTION, + data->mFunctions.length() - 1); + } + + return false; +} + +// These functions serialize raw XPCOM pointers in the data stream, and thus +// should only be used when the read and write are done together +// synchronously. +static JSStructuredCloneCallbacks CloneIntoCallbacks = { + CloneIntoReadStructuredClone, + CloneIntoWriteStructuredClone, + nullptr +}; + +NS_IMETHODIMP +nsXPCComponents_Utils::CloneInto(HandleValue aValue, HandleValue aScope, + HandleValue aOptions, JSContext *aCx, + MutableHandleValue aCloned) +{ + if (!aScope.isObject()) + return NS_ERROR_INVALID_ARG; + + RootedObject scope(aCx, &aScope.toObject()); + scope = js::CheckedUnwrap(scope); + NS_ENSURE_TRUE(scope, NS_ERROR_FAILURE); + + if (!aOptions.isUndefined() && !aOptions.isObject()) { + JS_ReportError(aCx, "Invalid argument"); + return NS_ERROR_FAILURE; + } + + RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject() + : nullptr); + CloneIntoOptions options(aCx, optionsObject); + if (aOptions.isObject() && !options.Parse()) + return NS_ERROR_FAILURE; + + { + CloneIntoCallbacksData data(aCx, &options); + JSAutoCompartment ac(aCx, scope); + if (!JS_StructuredClone(aCx, aValue, aCloned, &CloneIntoCallbacks, &data)) + return NS_ERROR_FAILURE; + } + + if (!JS_WrapValue(aCx, aCloned)) + return NS_ERROR_FAILURE; + + return NS_OK; +} + /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 944d92601448..67844cf57c32 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -3333,6 +3333,10 @@ bool NewFunctionForwarder(JSContext *cx, JS::HandleId id, JS::HandleObject callable, bool doclone, JS::MutableHandleValue vp); +bool +NewFunctionForwarder(JSContext *cx, JS::HandleObject callable, + bool doclone, JS::MutableHandleValue vp); + // Old fashioned xpc error reporter. Try to use JS_ReportError instead. nsresult ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval); diff --git a/js/xpconnect/tests/chrome/chrome.ini b/js/xpconnect/tests/chrome/chrome.ini index c8a587797eda..b406d53b5630 100644 --- a/js/xpconnect/tests/chrome/chrome.ini +++ b/js/xpconnect/tests/chrome/chrome.ini @@ -53,6 +53,7 @@ support-files = [test_bug932906.xul] [test_xrayToJS.xul] [test_chrometoSource.xul] +[test_cloneInto.xul] [test_cows.xul] [test_documentdomain.xul] [test_doublewrappedcompartments.xul] diff --git a/js/xpconnect/tests/chrome/test_cloneInto.xul b/js/xpconnect/tests/chrome/test_cloneInto.xul new file mode 100644 index 000000000000..bd4c285decaf --- /dev/null +++ b/js/xpconnect/tests/chrome/test_cloneInto.xul @@ -0,0 +1,140 @@ + + + + + + + + + Cu.cloneInto() + + + + + From 2d244ee3f6d8c0b8c90784164b9696a524c6fc1d Mon Sep 17 00:00:00 2001 From: Andrew Halberstadt Date: Thu, 30 Jan 2014 08:42:18 -0500 Subject: [PATCH 34/88] Bug 948070 - Create a mach target for b2g desktop reftests, r=jgriffin, DONTBUILD, a=NPOTB --- layout/tools/reftest/mach_commands.py | 121 +++++++++++++++++++++----- 1 file changed, 98 insertions(+), 23 deletions(-) diff --git a/layout/tools/reftest/mach_commands.py b/layout/tools/reftest/mach_commands.py index 157d41ef637f..e471db78bb31 100644 --- a/layout/tools/reftest/mach_commands.py +++ b/layout/tools/reftest/mach_commands.py @@ -8,6 +8,7 @@ import mozpack.path import os import re import sys +import warnings import which from mozbuild.base import ( @@ -25,8 +26,43 @@ from mach.decorators import ( DEBUGGER_HELP = 'Debugger binary to run test in. Program name or path.' -ADB_NOT_FOUND = """The %s command requires the adb binary to be on your path. -This can be found in '%s/out/host//bin'.""" +ADB_NOT_FOUND = ''' +The %s command requires the adb binary to be on your path. + +If you have a B2G build, this can be found in +'%s/out/host//bin'. +'''.lstrip() + +GAIA_PROFILE_NOT_FOUND = ''' +The %s command requires a non-debug gaia profile. Either pass in --profile, +or set the GAIA_PROFILE environment variable. + +If you do not have a non-debug gaia profile, you can build one: + $ git clone https://github.com/mozilla-b2g/gaia + $ cd gaia + $ make + +The profile should be generated in a directory called 'profile'. +'''.lstrip() + +GAIA_PROFILE_IS_DEBUG = ''' +The %s command requires a non-debug gaia profile. The specified profile, +%s, is a debug profile. + +If you do not have a non-debug gaia profile, you can build one: + $ git clone https://github.com/mozilla-b2g/gaia + $ cd gaia + $ make + +The profile should be generated in a directory called 'profile'. +'''.lstrip() + +MARIONETTE_DISABLED = ''' +The %s command requires a marionette enabled build. + +Add 'ENABLE_MARIONETTE=1' to your mozconfig file and re-build the application. +Your currently active mozconfig is %s. +'''.lstrip() class ReftestRunner(MozbuildObject): """Easily run reftests. @@ -72,7 +108,8 @@ class ReftestRunner(MozbuildObject): def _make_shell_string(self, s): return "'%s'" % re.sub("'", r"'\''", s) - def run_b2g_test(self, b2g_home, xre_path, test_file=None, suite=None, **kwargs): + def run_b2g_test(self, b2g_home=None, xre_path=None, test_file=None, + suite=None, **kwargs): """Runs a b2g reftest. test_file is a path to a test file. It can be a relative path from the @@ -85,12 +122,6 @@ class ReftestRunner(MozbuildObject): if suite not in ('reftest', 'crashtest'): raise Exception('None or unrecognized reftest suite type.') - try: - which.which('adb') - except which.WhichError: - # TODO Find adb automatically if it isn't on the path - raise Exception(ADB_NOT_FOUND % ('%s-remote' % suite, b2g_home)) - # Find the manifest file if not test_file: if suite == 'reftest': @@ -109,25 +140,21 @@ class ReftestRunner(MozbuildObject): # Need to chdir to reftest_dir otherwise imports fail below. os.chdir(self.reftest_dir) - import imp - path = os.path.join(self.reftest_dir, 'runreftestb2g.py') - with open(path, 'r') as fh: - imp.load_module('reftest', fh, path, ('.py', 'r', imp.PY_SOURCE)) - import reftest + # The imp module can spew warnings if the modules below have + # already been imported, ignore them. + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + + import imp + path = os.path.join(self.reftest_dir, 'runreftestb2g.py') + with open(path, 'r') as fh: + imp.load_module('reftest', fh, path, ('.py', 'r', imp.PY_SOURCE)) + import reftest # Set up the reftest options. parser = reftest.B2GOptions() options, args = parser.parse_args([]) - options.b2gPath = b2g_home - options.logcat_dir = self.reftest_dir - options.httpdPath = os.path.join(self.topsrcdir, 'netwerk', 'test', 'httpserver') - options.ignoreWindowSize = True - options.xrePath = xre_path - - for k, v in kwargs.iteritems(): - setattr(options, k, v) - # Tests need to be served from a subdirectory of the server. Symlink # topsrcdir here to get around this. tests = os.path.join(self.reftest_dir, 'tests') @@ -135,6 +162,47 @@ class ReftestRunner(MozbuildObject): os.symlink(self.topsrcdir, tests) args.insert(0, os.path.join('tests', manifest)) + for k, v in kwargs.iteritems(): + setattr(options, k, v) + + if conditions.is_b2g_desktop(self): + if self.substs.get('ENABLE_MARIONETTE') != '1': + print(MARIONETTE_DISABLED % ('mochitest-b2g-desktop', + self.mozconfig['path'])) + return 1 + + options.profile = options.profile or os.environ.get('GAIA_PROFILE') + if not options.profile: + print(GAIA_PROFILE_NOT_FOUND % 'reftest-b2g-desktop') + return 1 + + if os.path.isfile(os.path.join(options.profile, 'extensions', \ + 'httpd@gaiamobile.org')): + print(GAIA_PROFILE_IS_DEBUG % ('mochitest-b2g-desktop', + options.profile)) + return 1 + + options.desktop = True + options.app = self.get_binary_path() + if not options.app.endswith('-bin'): + options.app = '%s-bin' % options.app + if not os.path.isfile(options.app): + options.app = options.app[:-len('-bin')] + + return reftest.run_desktop_reftests(parser, options, args) + + + try: + which.which('adb') + except which.WhichError: + # TODO Find adb automatically if it isn't on the path + raise Exception(ADB_NOT_FOUND % ('%s-remote' % suite, b2g_home)) + + options.b2gPath = b2g_home + options.logcat_dir = self.reftest_dir + options.httpdPath = os.path.join(self.topsrcdir, 'netwerk', 'test', 'httpserver') + options.xrePath = xre_path + options.ignoreWindowSize = True return reftest.run_remote_reftests(parser, options, args) def run_desktop_test(self, test_file=None, filter=None, suite=None, @@ -307,6 +375,13 @@ class B2GCommands(MachCommandBase): def run_reftest_remote(self, test_file, **kwargs): return self._run_reftest(test_file, suite='reftest', **kwargs) + @Command('reftest-b2g-desktop', category='testing', + description='Run a b2g desktop reftest.', + conditions=[conditions.is_b2g_desktop]) + @B2GCommand + def run_reftest_b2g_desktop(self, test_file, **kwargs): + return self._run_reftest(test_file, suite='reftest', **kwargs) + @Command('crashtest-remote', category='testing', description='Run a remote crashtest.', conditions=[conditions.is_b2g, is_emulator]) From 12f8e2be0bdf374efae13f3a1fc6e86569c65104 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Thu, 30 Jan 2014 14:59:24 +0100 Subject: [PATCH 35/88] Bug 958158 - IonMonkey: Optimize do {} while(false), r=djvj --- js/src/jit/IonBuilder.cpp | 12 ++++++++++++ js/src/jit/IonBuilder.h | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 2c8344f98548..ddf1f9ec9717 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -2178,6 +2178,18 @@ IonBuilder::processDoWhileCondEnd(CFGState &state) if (!successor) return ControlStatus_Error; + // Test for do {} while(false) and don't create a loop in that case. + if (vins->isConstant()) { + MConstant *cte = vins->toConstant(); + if (cte->value().isBoolean() && !cte->value().toBoolean()) { + current->end(MGoto::New(alloc(), successor)); + current = nullptr; + + state.loop.successor = successor; + return processBrokenLoop(state); + } + } + // Create the test instruction and end the current block. MTest *test = MTest::New(alloc(), vins, state.loop.entry, successor); current->end(test); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index ca5e78f0433c..bce41c5df58a 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -291,8 +291,8 @@ class IonBuilder : public MIRGenerator // linking each break to the new block. MBasicBlock *createBreakCatchBlock(DeferredEdge *edge, jsbytecode *pc); - // Finishes loops that do not actually loop, containing only breaks or - // returns. + // Finishes loops that do not actually loop, containing only breaks and + // returns or a do while loop with a condition that is constant false. ControlStatus processBrokenLoop(CFGState &state); // Computes loop phis, places them in all successors of a loop, then From ce4e1fcf64ddf09ab7c73dbc0716b518fa06a495 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Thu, 30 Jan 2014 16:05:47 +0100 Subject: [PATCH 36/88] Bug 946200 - Use the new texture client/host and async-video if OMTC is activated on Linux. r=nrc --- modules/libpref/src/init/all.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 32256cdbeb34..2969dff10104 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -4099,6 +4099,12 @@ pref("layers.use-deprecated-textures", true); pref("layers.async-video.enabled",false); #endif +#ifdef MOZ_X11 +// OMTC off by default on Linux, but if activated, use new textures and async-video. +pref("layers.use-deprecated-textures", false); +pref("layers.async-video.enabled", true); +#endif + #ifdef XP_MACOSX pref("layers.offmainthreadcomposition.enabled", true); pref("layers.use-deprecated-textures", false); From bf55a487103a94f63c9643e1b7c6c5abc755ee2c Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 30 Jan 2014 07:45:15 -0800 Subject: [PATCH 37/88] Bug 959012 - When resolving iterator classes, use JSProto_Iterator instead of JSProto_GeneratorFunction. r=luke The former triggers all of the appropriate initialization, whereas the latter is 'imaginary' in jsprototypes.h, which means that the is no initialization function associated with it. --- js/src/jsworkers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/jsworkers.cpp b/js/src/jsworkers.cpp index ebfca2062eff..436a68dbc33a 100644 --- a/js/src/jsworkers.cpp +++ b/js/src/jsworkers.cpp @@ -284,7 +284,7 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio if (!js_GetClassObject(cx, cx->global(), JSProto_Function, &obj) || !js_GetClassObject(cx, cx->global(), JSProto_Array, &obj) || !js_GetClassObject(cx, cx->global(), JSProto_RegExp, &obj) || - !js_GetClassObject(cx, cx->global(), JSProto_GeneratorFunction, &obj)) + !js_GetClassObject(cx, cx->global(), JSProto_Iterator, &obj)) { return false; } @@ -293,7 +293,7 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio if (!js_GetClassObject(cx, global, JSProto_Function, &obj) || !js_GetClassObject(cx, global, JSProto_Array, &obj) || !js_GetClassObject(cx, global, JSProto_RegExp, &obj) || - !js_GetClassObject(cx, global, JSProto_GeneratorFunction, &obj)) + !js_GetClassObject(cx, global, JSProto_Iterator, &obj)) { return false; } From 8b2a3c8d5b7d9779ffe269f32398c3390dce444f Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 30 Jan 2014 07:45:16 -0800 Subject: [PATCH 38/88] Bug 959012 - Remove unused cx parameter from JS_IdentifyClassPrototype. r=jorendorff --- js/src/jsapi.cpp | 5 +---- js/src/jsapi.h | 2 +- js/xpconnect/wrappers/ChromeObjectWrapper.cpp | 2 +- js/xpconnect/wrappers/WrapperFactory.cpp | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 2fbf2c6a2f0c..b6a9fd7929ff 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1374,11 +1374,8 @@ JS_GetClassPrototype(JSContext *cx, JSProtoKey key, MutableHandleObject objp) } JS_PUBLIC_API(JSProtoKey) -JS_IdentifyClassPrototype(JSContext *cx, JSObject *obj) +JS_IdentifyClassPrototype(JSObject *obj) { - AssertHeapIsIdle(cx); - CHECK_REQUEST(cx); - assertSameCompartment(cx, obj); JS_ASSERT(!obj->is()); return js_IdentifyClassPrototype(obj); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 0463b64bb07e..aec1f19bc92e 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1796,7 +1796,7 @@ extern JS_PUBLIC_API(bool) JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JS::MutableHandle objp); extern JS_PUBLIC_API(JSProtoKey) -JS_IdentifyClassPrototype(JSContext *cx, JSObject *obj); +JS_IdentifyClassPrototype(JSObject *obj); extern JS_PUBLIC_API(JSProtoKey) JS_IdToProtoKey(JSContext *cx, JS::HandleId id); diff --git a/js/xpconnect/wrappers/ChromeObjectWrapper.cpp b/js/xpconnect/wrappers/ChromeObjectWrapper.cpp index e4b52e152fa2..99110413e44e 100644 --- a/js/xpconnect/wrappers/ChromeObjectWrapper.cpp +++ b/js/xpconnect/wrappers/ChromeObjectWrapper.cpp @@ -36,7 +36,7 @@ PropIsFromStandardPrototype(JSContext *cx, JS::MutableHandle Date: Thu, 30 Jan 2014 07:45:16 -0800 Subject: [PATCH 39/88] Bug 959012 - Move js_GetClassObject creation logic into GlobalObject. r=jorendorff --- js/src/jsobj.cpp | 56 ++++++++------------------------------ js/src/vm/GlobalObject.cpp | 25 +++++++++++++++++ js/src/vm/GlobalObject.h | 10 +++++-- 3 files changed, 43 insertions(+), 48 deletions(-) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 6cd472d69c74..7084897d2a90 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3158,24 +3158,6 @@ JSObject::shrinkElements(ThreadSafeContext *cx, uint32_t newcap) elements = newheader->elements(); } -static JSObject * -js_InitNullClass(JSContext *cx, HandleObject obj) -{ - JS_ASSERT(0); - return nullptr; -} - -#define DECLARE_PROTOTYPE_CLASS_INIT(name,code,init,clasp) \ - extern JSObject *init(JSContext *cx, Handle obj); -JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT) -#undef DECLARE_PROTOTYPE_CLASS_INIT - -static const ClassInitializerOp lazy_prototype_init[JSProto_LIMIT] = { -#define LAZY_PROTOTYPE_INIT(name,code,init,clasp) init, - JS_FOR_EACH_PROTOTYPE(LAZY_PROTOTYPE_INIT) -#undef LAZY_PROTOTYPE_INIT -}; - bool js::SetClassAndProto(JSContext *cx, HandleObject obj, const Class *clasp, Handle proto, @@ -3260,36 +3242,20 @@ js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, Mutabl { Rooted global(cxArg, &obj->global()); - Value v = global->getConstructor(key); - if (v.isObject()) { - objp.set(&v.toObject()); - return true; - } - - // Classes can only be initialized on the main thread. - if (!cxArg->shouldBeJSContext()) - return false; - - JSContext *cx = cxArg->asJSContext(); - - RootedId name(cx, NameToId(ClassName(key, cx))); - AutoResolving resolving(cx, global, name); - if (resolving.alreadyStarted()) { - /* Already caching id in global -- suppress recursion. */ - objp.set(nullptr); - return true; - } - - RootedObject cobj(cx, nullptr); - if (ClassInitializerOp init = lazy_prototype_init[key]) { - if (!init(cx, global)) + // We can only resolve constructors with a real JSContext. + if (!global->isStandardClassResolved(key)) { + if (!cxArg->shouldBeJSContext()) + return false; + JSContext *cx = cxArg->asJSContext(); + RootedId name(cx, NameToId(ClassName(key, cx))); + AutoResolving resolving(cx, global, name); + if (!resolving.alreadyStarted() && !global->ensureConstructor(cx, key)) return false; - v = global->getConstructor(key); - if (v.isObject()) - cobj = &v.toObject(); } - objp.set(cobj); + Value v = global->getConstructor(key); + if (v.isObject()) + objp.set(&v.toObject()); return true; } diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 8ddd297425d1..defca523f7a4 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -12,6 +12,7 @@ #include "jsfriendapi.h" #include "jsmath.h" #include "json.h" +#include "jsprototypes.h" #include "jsweakmap.h" #include "builtin/Eval.h" @@ -32,6 +33,19 @@ using namespace js; +#define DECLARE_PROTOTYPE_CLASS_INIT(name,code,init,clasp) \ + extern JSObject *init(JSContext *cx, Handle obj); +JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT) +#undef DECLARE_PROTOTYPE_CLASS_INIT + +static const ClassInitializerOp class_init_functions[JSProto_LIMIT] = { +#define INIT_FUNC(name,code,init,clasp) init, +#define INIT_FUNC_DUMMY(name,code,init,clasp) nullptr, + JS_FOR_PROTOTYPES(INIT_FUNC, INIT_FUNC_DUMMY) +#undef INIT_FUNC_DUMMY +#undef INIT_FUNC +}; + // This method is not in the header file to avoid having to include // TypedObject.h from GlobalObject.h. It is not generally perf // sensitive. @@ -407,6 +421,17 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx) return functionProto; } +bool +GlobalObject::ensureConstructor(JSContext *cx, JSProtoKey key) +{ + if (getConstructor(key).isObject()) + return true; + MOZ_ASSERT(getConstructor(key).isUndefined()); + RootedObject self(cx, this); + ClassInitializerOp init = class_init_functions[key]; + return !init || init(cx, self); +} + GlobalObject * GlobalObject::create(JSContext *cx, const Class *clasp) { diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 4864e7f11a6d..851919cc3029 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -164,6 +164,7 @@ class GlobalObject : public JSObject JS_ASSERT(key <= JSProto_LIMIT); return getSlotForCompilation(APPLICATION_SLOTS + key); } + bool ensureConstructor(JSContext *cx, JSProtoKey key); void setConstructor(JSProtoKey key, const Value &v) { JS_ASSERT(key <= JSProto_LIMIT); @@ -215,15 +216,18 @@ class GlobalObject : public JSObject * Note: A few builtin objects, like JSON and Math, are not constructors, * so getConstructor is a bit of a misnomer. */ - bool isStandardClassResolved(const js::Class *clasp) const { - JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp); - + bool isStandardClassResolved(JSProtoKey key) const { // If the constructor is undefined, then it hasn't been initialized. MOZ_ASSERT(getConstructor(key).isUndefined() || getConstructor(key).isObject()); return !getConstructor(key).isUndefined(); } + bool isStandardClassResolved(const js::Class *clasp) const { + JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp); + return isStandardClassResolved(key); + } + private: void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) { JS_ASSERT(getConstructor(key).isUndefined()); From fd6a49474ce659d482f39566aefbae775a744431 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 30 Jan 2014 07:45:16 -0800 Subject: [PATCH 40/88] Bug 959012 - Create separate js_GetClassPrototype and js_FindClassPrototype to mimic js_{Get,Find}ClassObject. r=jorendorff The current behavior is crazy, and most definitely not Xray-safe. --- js/src/jsinfer.cpp | 2 +- js/src/jsobj.cpp | 58 +++++++++++++++++++++++++++++-------------- js/src/jsobj.h | 27 ++++++++++++-------- js/src/jsobjinlines.h | 2 +- 4 files changed, 58 insertions(+), 31 deletions(-) diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 4a2d8e229563..50c6dcc69444 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1984,7 +1984,7 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke if (!res) { RootedObject proto(cx); - if (!js_GetClassPrototype(cx, key.kind, &proto, nullptr)) + if (!js_GetClassPrototype(cx, key.kind, &proto)) return nullptr; Rooted tagged(cx, TaggedProto(proto)); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 7084897d2a90..bea9d93ae407 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3237,21 +3237,28 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj, return true; } -bool -js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, MutableHandleObject objp) +static bool +MaybeResolveConstructor(ExclusiveContext *cxArg, Handle global, JSProtoKey key) { - Rooted global(cxArg, &obj->global()); + if (global->isStandardClassResolved(key)) + return true; + if (!cxArg->shouldBeJSContext()) + return false; - // We can only resolve constructors with a real JSContext. - if (!global->isStandardClassResolved(key)) { - if (!cxArg->shouldBeJSContext()) - return false; - JSContext *cx = cxArg->asJSContext(); - RootedId name(cx, NameToId(ClassName(key, cx))); - AutoResolving resolving(cx, global, name); - if (!resolving.alreadyStarted() && !global->ensureConstructor(cx, key)) - return false; - } + JSContext *cx = cxArg->asJSContext(); + RootedId name(cx, NameToId(ClassName(key, cx))); + AutoResolving resolving(cx, global, name); + if (resolving.alreadyStarted()) + return true; + return global->ensureConstructor(cx, key); +} + +bool +js_GetClassObject(ExclusiveContext *cx, JSObject *obj, JSProtoKey key, MutableHandleObject objp) +{ + Rooted global(cx, &obj->global()); + if (!MaybeResolveConstructor(cx, global, key)) + return false; Value v = global->getConstructor(key); if (v.isObject()) @@ -3259,6 +3266,19 @@ js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, Mutabl return true; } +bool +js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject protop) +{ + Rooted global(cx, cx->global()); + if (!MaybeResolveConstructor(cx, global, key)) + return false; + + Value v = global->getPrototype(key); + if (v.isObject()) + protop.set(&v.toObject()); + return true; +} + JSProtoKey js_IdentifyClassPrototype(JSObject *obj) { @@ -5428,12 +5448,14 @@ js::GetClassPrototypePure(GlobalObject *global, JSProtoKey protoKey) * NewBuiltinClassInstance in jsobjinlines.h. */ bool -js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey, - MutableHandleObject protop, const Class *clasp) +js_FindClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey, + MutableHandleObject protop, const Class *clasp) { - if (JSObject *proto = GetClassPrototypePure(cx->global(), protoKey)) { - protop.set(proto); - return true; + if (protoKey != JSProto_Null) { + if (!js_GetClassPrototype(cx, protoKey, protop)) + return false; + if (protop) + return true; } RootedValue v(cx); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index edd1a3b37f99..746c254d83db 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1324,6 +1324,10 @@ extern bool js_GetClassObject(js::ExclusiveContext *cx, JSObject *obj, JSProtoKey key, js::MutableHandleObject objp); +extern bool +js_GetClassPrototype(js::ExclusiveContext *cx, JSProtoKey key, + js::MutableHandleObject objp); + /* * Determine if the given object is a prototype for a standard class. If so, * return the associated JSProtoKey. If not, return JSProto_Null. @@ -1339,6 +1343,18 @@ bool js_FindClassObject(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp, const js::Class *clasp = nullptr); +/* + * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is + * JSProto_Null, clasp must non-null. + * + * If protoKey is constant and scope is non-null, use GlobalObject's prototype + * methods instead. + */ +extern bool +js_FindClassPrototype(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop, + const js::Class *clasp = nullptr); + + namespace js { extern bool @@ -1597,17 +1613,6 @@ extern unsigned js_InferFlags(JSContext *cx, unsigned defaultFlags); -/* - * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is - * JSProto_Null, clasp must non-null. - * - * If protoKey is constant and scope is non-null, use GlobalObject's prototype - * methods instead. - */ -extern bool -js_GetClassPrototype(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop, - const js::Class *clasp = nullptr); - namespace js { JSObject * diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 80ac25f76d93..c8ea9f318376 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -877,7 +877,7 @@ inline bool FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto) { JSProtoKey protoKey = GetClassProtoKey(clasp); - if (!js_GetClassPrototype(cx, protoKey, proto, clasp)) + if (!js_FindClassPrototype(cx, protoKey, proto, clasp)) return false; if (!proto && !js_GetClassPrototype(cx, JSProto_Object, proto)) return false; From 331a1f6c7b4bb9750b8218e8e5ffe7bcfb91b11b Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 30 Jan 2014 07:45:16 -0800 Subject: [PATCH 41/88] Bug 959012 - Clean up and separate the semantics of js_{Get,Find}Class{Prototype,Object}. r=jorendorff --- js/src/jsapi.cpp | 5 ++-- js/src/jsapi.h | 3 +- js/src/jscompartment.cpp | 6 ++-- js/src/jsiter.cpp | 6 ++-- js/src/jsobj.cpp | 42 +++++++++++++-------------- js/src/jsobj.h | 25 +++++++--------- js/src/jsobjinlines.h | 3 +- js/src/jsworkers.cpp | 16 +++++----- js/src/vm/TypedArrayObject.cpp | 3 +- js/xpconnect/wrappers/XrayWrapper.cpp | 2 +- 10 files changed, 52 insertions(+), 59 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index b6a9fd7929ff..90d9f09b42d9 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1357,12 +1357,11 @@ JS_EnumerateStandardClasses(JSContext *cx, HandleObject obj) } JS_PUBLIC_API(bool) -JS_GetClassObject(JSContext *cx, HandleObject obj, JSProtoKey key, MutableHandleObject objp) +JS_GetClassObject(JSContext *cx, JSProtoKey key, MutableHandleObject objp) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); - assertSameCompartment(cx, obj); - return js_GetClassObject(cx, obj, key, objp); + return js_GetClassObject(cx, key, objp); } JS_PUBLIC_API(bool) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index aec1f19bc92e..103ea768b966 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1789,8 +1789,7 @@ extern JS_PUBLIC_API(bool) JS_EnumerateStandardClasses(JSContext *cx, JS::HandleObject obj); extern JS_PUBLIC_API(bool) -JS_GetClassObject(JSContext *cx, JS::Handle obj, JSProtoKey key, - JS::MutableHandle objp); +JS_GetClassObject(JSContext *cx, JSProtoKey key, JS::MutableHandle objp); extern JS_PUBLIC_API(bool) JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JS::MutableHandle objp); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 561ae4d4e05b..19d3bd036ff5 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -386,10 +386,10 @@ JSCompartment::wrap(JSContext *cx, MutableHandleObject obj, HandleObject existin /* Translate StopIteration singleton. */ if (obj->is()) { - RootedValue v(cx); - if (!js_FindClassObject(cx, JSProto_StopIteration, &v)) + RootedObject stopIteration(cx); + if (!js_GetClassObject(cx, JSProto_StopIteration, &stopIteration)) return false; - obj.set(&v.toObject()); + obj.set(stopIteration); return true; } diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 801695ccdd9c..b65bd94cace8 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -730,9 +730,9 @@ bool js_ThrowStopIteration(JSContext *cx) { JS_ASSERT(!JS_IsExceptionPending(cx)); - RootedValue v(cx); - if (js_FindClassObject(cx, JSProto_StopIteration, &v)) - cx->setPendingException(v); + RootedObject ctor(cx); + if (js_GetClassObject(cx, JSProto_StopIteration, &ctor) && ctor) + cx->setPendingException(ObjectValue(*ctor)); return false; } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index bea9d93ae407..bbed8abe67bf 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3254,9 +3254,10 @@ MaybeResolveConstructor(ExclusiveContext *cxArg, Handle global, J } bool -js_GetClassObject(ExclusiveContext *cx, JSObject *obj, JSProtoKey key, MutableHandleObject objp) +js_GetClassObject(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp) { - Rooted global(cx, &obj->global()); + MOZ_ASSERT(key != JSProto_Null); + Rooted global(cx, cx->global()); if (!MaybeResolveConstructor(cx, global, key)) return false; @@ -3269,6 +3270,7 @@ js_GetClassObject(ExclusiveContext *cx, JSObject *obj, JSProtoKey key, MutableHa bool js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject protop) { + MOZ_ASSERT(key != JSProto_Null); Rooted global(cx, cx->global()); if (!MaybeResolveConstructor(cx, global, key)) return false; @@ -3303,20 +3305,19 @@ js_IdentifyClassPrototype(JSObject *obj) } bool -js_FindClassObject(ExclusiveContext *cx, JSProtoKey protoKey, MutableHandleValue vp, const Class *clasp) +js_FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp) { + MOZ_ASSERT(clasp); + JSProtoKey protoKey = GetClassProtoKey(clasp); RootedId id(cx); - if (protoKey != JSProto_Null) { JS_ASSERT(JSProto_Null < protoKey); JS_ASSERT(protoKey < JSProto_LIMIT); RootedObject cobj(cx); - if (!js_GetClassObject(cx, cx->global(), protoKey, &cobj)) + if (!js_GetClassObject(cx, protoKey, protop)) return false; - if (cobj) { - vp.set(ObjectValue(*cobj)); + if (cobj) return true; - } id = NameToId(ClassName(protoKey, cx)); } else { JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name)); @@ -3331,13 +3332,11 @@ js_FindClassObject(ExclusiveContext *cx, JSProtoKey protoKey, MutableHandleValue return false; RootedValue v(cx, UndefinedValue()); if (shape && pobj->isNative()) { - if (shape->hasSlot()) { + if (shape->hasSlot()) v = pobj->nativeGetSlot(shape->slot()); - if (v.get().isPrimitive()) - v.get().setUndefined(); - } } - vp.set(v); + if (v.isObject()) + protop.set(&v.toObject()); return true; } @@ -5448,9 +5447,10 @@ js::GetClassPrototypePure(GlobalObject *global, JSProtoKey protoKey) * NewBuiltinClassInstance in jsobjinlines.h. */ bool -js_FindClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey, - MutableHandleObject protop, const Class *clasp) +js_FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp) { + protop.set(nullptr); + JSProtoKey protoKey = GetClassProtoKey(clasp); if (protoKey != JSProto_Null) { if (!js_GetClassPrototype(cx, protoKey, protop)) return false; @@ -5458,12 +5458,12 @@ js_FindClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey, return true; } - RootedValue v(cx); - if (!js_FindClassObject(cx, protoKey, &v, clasp)) + RootedObject ctor(cx); + if (!js_FindClassObject(cx, &ctor, clasp)) return false; - if (IsFunctionObject(v)) { - RootedObject ctor(cx, &v.get().toObject()); + if (ctor && ctor->is()) { + RootedValue v(cx); if (cx->isJSContext()) { if (!JSObject::getProperty(cx->asJSContext(), ctor, ctor, cx->names().prototype, &v)) @@ -5475,9 +5475,9 @@ js_FindClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey, if (!shape || !NativeGetPureInline(ctor, shape, v.address())) return false; } + if (v.isObject()) + protop.set(&v.toObject()); } - - protop.set(v.get().isObject() ? &v.get().toObject() : nullptr); return true; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 746c254d83db..809e6ec7c10e 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1321,7 +1321,7 @@ js_PopulateObject(JSContext *cx, js::HandleObject newborn, js::HandleObject prop * Fast access to immutable standard objects (constructors and prototypes). */ extern bool -js_GetClassObject(js::ExclusiveContext *cx, JSObject *obj, JSProtoKey key, +js_GetClassObject(js::ExclusiveContext *cx, JSProtoKey key, js::MutableHandleObject objp); extern bool @@ -1336,23 +1336,18 @@ extern JSProtoKey js_IdentifyClassPrototype(JSObject *obj); /* - * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is - * JSProto_Null, clasp must non-null. + * Property-lookup-based access to interface and prototype objects for classes. + * If the class is built-in (and has a non-null JSProtoKey), these forward to + * js_GetClass{Object,Prototype}. */ -bool -js_FindClassObject(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp, - const js::Class *clasp = nullptr); -/* - * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is - * JSProto_Null, clasp must non-null. - * - * If protoKey is constant and scope is non-null, use GlobalObject's prototype - * methods instead. - */ +bool +js_FindClassObject(js::ExclusiveContext *cx, js::MutableHandleObject protop, + const js::Class *clasp); + extern bool -js_FindClassPrototype(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop, - const js::Class *clasp = nullptr); +js_FindClassPrototype(js::ExclusiveContext *cx, js::MutableHandleObject protop, + const js::Class *clasp); namespace js { diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index c8ea9f318376..b765e6795377 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -876,8 +876,7 @@ GetClassProtoKey(const js::Class *clasp) inline bool FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto) { - JSProtoKey protoKey = GetClassProtoKey(clasp); - if (!js_FindClassPrototype(cx, protoKey, proto, clasp)) + if (!js_FindClassPrototype(cx, proto, clasp)) return false; if (!proto && !js_GetClassPrototype(cx, JSProto_Object, proto)) return false; diff --git a/js/src/jsworkers.cpp b/js/src/jsworkers.cpp index 436a68dbc33a..88699f89bb95 100644 --- a/js/src/jsworkers.cpp +++ b/js/src/jsworkers.cpp @@ -281,19 +281,19 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio // Initialize all classes needed for parsing while we are still on the main // thread. Do this for both the target and the new global so that prototype // pointers can be changed infallibly after parsing finishes. - if (!js_GetClassObject(cx, cx->global(), JSProto_Function, &obj) || - !js_GetClassObject(cx, cx->global(), JSProto_Array, &obj) || - !js_GetClassObject(cx, cx->global(), JSProto_RegExp, &obj) || - !js_GetClassObject(cx, cx->global(), JSProto_Iterator, &obj)) + if (!js_GetClassObject(cx, JSProto_Function, &obj) || + !js_GetClassObject(cx, JSProto_Array, &obj) || + !js_GetClassObject(cx, JSProto_RegExp, &obj) || + !js_GetClassObject(cx, JSProto_Iterator, &obj)) { return false; } { AutoCompartment ac(cx, global); - if (!js_GetClassObject(cx, global, JSProto_Function, &obj) || - !js_GetClassObject(cx, global, JSProto_Array, &obj) || - !js_GetClassObject(cx, global, JSProto_RegExp, &obj) || - !js_GetClassObject(cx, global, JSProto_Iterator, &obj)) + if (!js_GetClassObject(cx, JSProto_Function, &obj) || + !js_GetClassObject(cx, JSProto_Array, &obj) || + !js_GetClassObject(cx, JSProto_RegExp, &obj) || + !js_GetClassObject(cx, JSProto_Iterator, &obj)) { return false; } diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 0c42755cef00..a0eabfb0546e 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -3955,11 +3955,12 @@ JSObject * js_InitTypedArrayClasses(JSContext *cx, HandleObject obj) { JS_ASSERT(obj->isNative()); + assertSameCompartment(cx, obj); Rooted global(cx, &obj->as()); /* Idempotency required: we initialize several things, possibly lazily. */ RootedObject stop(cx); - if (!js_GetClassObject(cx, global, JSProto_ArrayBuffer, &stop)) + if (!js_GetClassObject(cx, JSProto_ArrayBuffer, &stop)) return nullptr; if (stop) return stop; diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 7b7d15650302..0c9994e994d2 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -858,7 +858,7 @@ XrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, if (key != JSProto_Null) { MOZ_ASSERT(key < JSProto_LIMIT); RootedObject constructor(cx); - if (!JS_GetClassObject(cx, target, key, &constructor)) + if (!JS_GetClassObject(cx, key, &constructor)) return false; MOZ_ASSERT(constructor); desc.value().set(ObjectValue(*constructor)); From d8c8c1540ff255992b6c6f1332f313afd998bb49 Mon Sep 17 00:00:00 2001 From: Joel Maher Date: Thu, 30 Jan 2014 10:47:28 -0500 Subject: [PATCH 42/88] Bug 965731 - upload a new talos.zip to pick up all the fixes. r=armenzg --- testing/talos/talos.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 1f8857402b8e..6efa49eb5db3 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -1,11 +1,11 @@ { "talos.zip": { - "url": "http://talos-bundles.pvt.build.mozilla.org/zips/talos.8c5f2725fbdd.zip", + "url": "http://talos-bundles.pvt.build.mozilla.org/zips/talos.e78104c1f552.zip", "path": "" }, "global": { "talos_repo": "http://hg.mozilla.org/build/talos", - "talos_revision": "82b7680f9eaf" + "talos_revision": "e78104c1f552" }, "suites": { "chromez": { From 267e4c10f0469c5fb15dc205fc2f1cc0544eb0d5 Mon Sep 17 00:00:00 2001 From: Shih-Chiang Chien Date: Thu, 30 Jan 2014 10:59:15 -0500 Subject: [PATCH 43/88] Bug 948725 - Invoke |QuitPumpingEvent| after response packet is received. r=jduell --- netwerk/test/TestUDPSocket.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netwerk/test/TestUDPSocket.cpp b/netwerk/test/TestUDPSocket.cpp index 62b676c38773..c504301ba2cf 100644 --- a/netwerk/test/TestUDPSocket.cpp +++ b/netwerk/test/TestUDPSocket.cpp @@ -114,6 +114,7 @@ UDPClientListener::OnPacketReceived(nsIUDPSocket* socket, nsIUDPMessage* message } else { fail("Response written"); } + return NS_OK; } else if (TEST_OUTPUT_STREAM != phase || !CheckMessageContent(message, RESPONSE)) { mResult = NS_ERROR_FAILURE; } @@ -178,10 +179,13 @@ UDPServerListener::OnPacketReceived(nsIUDPSocket* socket, nsIUDPMessage* message } else { fail("Response written"); } + return NS_OK; } else if (TEST_SEND_API != phase || !CheckMessageContent(message, RESPONSE)) { mResult = NS_ERROR_FAILURE; } + // Notify thread + QuitPumpingEvents(); return NS_OK; } From c1082ab70e81a3c77ff7d75a04e8b258d47c0991 Mon Sep 17 00:00:00 2001 From: Ethan Tseng Date: Thu, 30 Jan 2014 10:00:53 +0800 Subject: [PATCH 44/88] Bug 951188 - [RTSP][V1.3] No error notification when the RTSP link fails to load. r=sworkman --- content/media/RtspMediaResource.cpp | 5 ++- .../protocol/rtsp/rtsp/ARTSPConnection.cpp | 33 +++++++++++++++---- netwerk/protocol/rtsp/rtsp/ARTSPConnection.h | 2 ++ .../rtsp/rtsp/RTSPConnectionHandler.h | 18 ++++++++-- netwerk/protocol/rtsp/rtsp/RTSPSource.cpp | 17 +++++----- 5 files changed, 55 insertions(+), 20 deletions(-) diff --git a/content/media/RtspMediaResource.cpp b/content/media/RtspMediaResource.cpp index 4f5400f2eff3..6a61f2f373e3 100644 --- a/content/media/RtspMediaResource.cpp +++ b/content/media/RtspMediaResource.cpp @@ -540,10 +540,9 @@ RtspMediaResource::OnDisconnected(uint8_t aTrackIdx, nsresult aReason) if (aReason == NS_ERROR_NOT_INITIALIZED || aReason == NS_ERROR_CONNECTION_REFUSED || - aReason == NS_ERROR_NOT_CONNECTED) { - + aReason == NS_ERROR_NOT_CONNECTED || + aReason == NS_ERROR_NET_TIMEOUT) { RTSPMLOG("Error in OnDisconnected 0x%x", aReason); - mDecoder->NetworkError(); return NS_OK; } diff --git a/netwerk/protocol/rtsp/rtsp/ARTSPConnection.cpp b/netwerk/protocol/rtsp/rtsp/ARTSPConnection.cpp index 2fb8146e89cb..ca83726cd52b 100644 --- a/netwerk/protocol/rtsp/rtsp/ARTSPConnection.cpp +++ b/netwerk/protocol/rtsp/rtsp/ARTSPConnection.cpp @@ -44,6 +44,7 @@ namespace android { // static const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll; +const int64_t ARTSPConnection::kSelectTimeoutRetries = 10000ll; ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid) : mUIDValid(uidValid), @@ -53,7 +54,8 @@ ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid) mSocket(-1), mConnectionID(0), mNextCSeq(0), - mReceiveResponseEventPending(false) { + mReceiveResponseEventPending(false), + mNumSelectTimeoutRetries(0) { MakeUserAgent(&mUserAgent); } @@ -76,8 +78,14 @@ void ARTSPConnection::connect(const char *url, const sp &reply) { } void ARTSPConnection::disconnect(const sp &reply) { + int32_t result; sp msg = new AMessage(kWhatDisconnect, id()); msg->setMessage("reply", reply); + if (reply->findInt32("result", &result)) { + msg->setInt32("result", result); + } else { + msg->setInt32("result", OK); + } msg->post(); } @@ -285,6 +293,7 @@ void ARTSPConnection::onConnect(const sp &msg) { if (err < 0) { if (errno == EINPROGRESS) { + mNumSelectTimeoutRetries = 0; sp msg = new AMessage(kWhatCompleteConnection, id()); msg->setMessage("reply", reply); msg->setInt32("connection-id", mConnectionID); @@ -324,20 +333,22 @@ void ARTSPConnection::performDisconnect() { mPass.clear(); mAuthType = NONE; mNonce.clear(); + mNumSelectTimeoutRetries = 0; mState = DISCONNECTED; } void ARTSPConnection::onDisconnect(const sp &msg) { + int32_t result; if (mState == CONNECTED || mState == CONNECTING) { performDisconnect(); } sp reply; CHECK(msg->findMessage("reply", &reply)); + CHECK(msg->findInt32("result", &result)); - reply->setInt32("result", OK); - + reply->setInt32("result", result); reply->post(); } @@ -368,9 +379,19 @@ void ARTSPConnection::onCompleteConnection(const sp &msg) { CHECK_GE(res, 0); if (res == 0) { - // Timed out. Not yet connected. - - msg->post(); + // select() timed out. Not yet connected. + if (mNumSelectTimeoutRetries < kSelectTimeoutRetries) { + mNumSelectTimeoutRetries++; + msg->post(); + } else { + // Connection timeout here. + // We cannot establish TCP connection, abort the connect + // and reply an error to RTSPConnectionHandler. + LOGE("Connection timeout. Failed to connect to the server."); + mNumSelectTimeoutRetries = 0; + reply->setInt32("result", -ETIMEDOUT); + reply->post(); + } return; } diff --git a/netwerk/protocol/rtsp/rtsp/ARTSPConnection.h b/netwerk/protocol/rtsp/rtsp/ARTSPConnection.h index 68f2d59ea80e..50f366c978f9 100644 --- a/netwerk/protocol/rtsp/rtsp/ARTSPConnection.h +++ b/netwerk/protocol/rtsp/rtsp/ARTSPConnection.h @@ -73,6 +73,7 @@ private: }; static const int64_t kSelectTimeoutUs; + static const int64_t kSelectTimeoutRetries; bool mUIDValid; uid_t mUID; @@ -84,6 +85,7 @@ private: int32_t mConnectionID; int32_t mNextCSeq; bool mReceiveResponseEventPending; + int64_t mNumSelectTimeoutRetries; KeyedVector > mPendingRequests; diff --git a/netwerk/protocol/rtsp/rtsp/RTSPConnectionHandler.h b/netwerk/protocol/rtsp/rtsp/RTSPConnectionHandler.h index aeb3b0c0351c..af2b02589796 100644 --- a/netwerk/protocol/rtsp/rtsp/RTSPConnectionHandler.h +++ b/netwerk/protocol/rtsp/rtsp/RTSPConnectionHandler.h @@ -427,7 +427,9 @@ struct RtspConnectionHandler : public AHandler { sp reply = new AMessage('desc', id()); mConn->sendRequest(request.c_str(), reply); } else { - (new AMessage('disc', id()))->post(); + sp reply = new AMessage('disc', id()); + reply->setInt32("result", result); + mConn->disconnect(reply); } break; } @@ -441,7 +443,11 @@ struct RtspConnectionHandler : public AHandler { sp reply = new AMessage('conn', id()); mConn->connect(mOriginalSessionURL.c_str(), reply); } else { - (new AMessage('quit', id()))->post(); + int32_t result; + CHECK(msg->findInt32("result", &result)); + sp reply = new AMessage('quit', id()); + reply->setInt32("result", result); + reply->post(); } break; } @@ -550,6 +556,7 @@ struct RtspConnectionHandler : public AHandler { if (result != OK) { sp reply = new AMessage('disc', id()); + reply->setInt32("result", result); mConn->disconnect(reply); } break; @@ -681,6 +688,7 @@ struct RtspConnectionHandler : public AHandler { msg->post(); } else { sp reply = new AMessage('disc', id()); + reply->setInt32("result", result); mConn->disconnect(reply); } break; @@ -723,6 +731,7 @@ struct RtspConnectionHandler : public AHandler { if (result != OK) { sp reply = new AMessage('disc', id()); + reply->setInt32("result", result); mConn->disconnect(reply); } @@ -841,6 +850,7 @@ struct RtspConnectionHandler : public AHandler { result, strerror(-result)); sp reply = new AMessage('disc', id()); + reply->setInt32("result", result); int32_t reconnect; if (msg->findInt32("reconnect", &reconnect) && reconnect) { @@ -853,9 +863,11 @@ struct RtspConnectionHandler : public AHandler { case 'quit': { + int32_t result; + CHECK(msg->findInt32("result", &result)); sp msg = mNotify->dup(); msg->setInt32("what", kWhatDisconnected); - msg->setInt32("result", UNKNOWN_ERROR); + msg->setInt32("result", result); msg->post(); break; } diff --git a/netwerk/protocol/rtsp/rtsp/RTSPSource.cpp b/netwerk/protocol/rtsp/rtsp/RTSPSource.cpp index 42751d09cfec..e25fd6b3232b 100644 --- a/netwerk/protocol/rtsp/rtsp/RTSPSource.cpp +++ b/netwerk/protocol/rtsp/rtsp/RTSPSource.cpp @@ -576,12 +576,11 @@ void RTSPSource::onDisconnected(const sp &msg) { status_t err; CHECK(msg != NULL); CHECK(msg->findInt32("result", &err)); - CHECK_NE(err, (status_t)OK); - CHECK(mLooper != NULL); - CHECK(mHandler != NULL); - mLooper->unregisterHandler(mHandler->id()); - mHandler.clear(); + if ((mLooper != NULL) && (mHandler != NULL)) { + mLooper->unregisterHandler(mHandler->id()); + mHandler.clear(); + } mState = DISCONNECTED; mFinalResult = err; @@ -590,9 +589,11 @@ void RTSPSource::onDisconnected(const sp &msg) { finishDisconnectIfPossible(); } if (mListener) { - // err is always set to UNKNOWN_ERROR from - // Android right now, rename err to NS_ERROR_NET_TIMEOUT. - mListener->OnDisconnected(0, NS_ERROR_NET_TIMEOUT); + if (err == OK) { + mListener->OnDisconnected(0, NS_OK); + } else { + mListener->OnDisconnected(0, NS_ERROR_NET_TIMEOUT); + } } mAudioTrack = NULL; mVideoTrack = NULL; From 719046a9e6828368e408313dcceecc7c283ff484 Mon Sep 17 00:00:00 2001 From: James Kitchener Date: Thu, 30 Jan 2014 10:59:16 -0500 Subject: [PATCH 45/88] Bug 953385 - Set math script where applicable in /gfx. r=jfkthame --- gfx/thebes/gfxFont.cpp | 3 ++- gfx/thebes/gfxFont.h | 5 ++++- gfx/thebes/gfxHarfBuzzShaper.cpp | 19 +++++++++++++------ layout/media/symbols.def.in | 1 + 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index f50ace76190c..c1f0523cc53e 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -3545,7 +3545,8 @@ gfxFont::SplitAndInitTextRun(gfxContext *aContext, // the only flags we care about for ShapedWord construction/caching uint32_t flags = aTextRun->GetFlags(); flags &= (gfxTextRunFactory::TEXT_IS_RTL | - gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES); + gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES | + gfxTextRunFactory::TEXT_USE_MATH_SCRIPT); if (sizeof(T) == sizeof(uint8_t)) { flags |= gfxTextRunFactory::TEXT_IS_8BIT; } diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 2b688ab14d84..0686609697aa 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -1151,7 +1151,10 @@ public: */ TEXT_INCOMING_ARABICCHAR = 0x40000000, - TEXT_UNUSED_FLAGS = 0x90000000 + // Set if the textrun should use the OpenType 'math' script. + TEXT_USE_MATH_SCRIPT = 0x80000000, + + TEXT_UNUSED_FLAGS = 0x10000000 }; /** diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index c8cbb2070cad..f97a18033f2a 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -796,6 +796,8 @@ AddOpenTypeFeature(const uint32_t& aTag, uint32_t& aValue, void *aUserArg) static hb_font_funcs_t * sHBFontFuncs = nullptr; static hb_unicode_funcs_t * sHBUnicodeFuncs = nullptr; +static const hb_script_t sMathScript = + hb_ot_tag_to_script(HB_TAG('m','a','t','h')); bool gfxHarfBuzzShaper::ShapeText(gfxContext *aContext, @@ -940,12 +942,17 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext, hb_buffer_set_unicode_funcs(buffer, sHBUnicodeFuncs); hb_buffer_set_direction(buffer, isRightToLeft ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); - // For unresolved "common" or "inherited" runs, default to Latin for now. - // (Should we somehow use the language or locale to try and infer - // a better default?) - hb_script_t scriptTag = (aScript <= MOZ_SCRIPT_INHERITED) ? - HB_SCRIPT_LATIN : - hb_script_t(GetScriptTagForCode(aScript)); + hb_script_t scriptTag; + if (aShapedText->Flags() & gfxTextRunFactory::TEXT_USE_MATH_SCRIPT) { + scriptTag = sMathScript; + } else if (aScript <= MOZ_SCRIPT_INHERITED) { + // For unresolved "common" or "inherited" runs, default to Latin for + // now. (Should we somehow use the language or locale to try and infer + // a better default?) + scriptTag = HB_SCRIPT_LATIN; + } else { + scriptTag = hb_script_t(GetScriptTagForCode(aScript)); + } hb_buffer_set_script(buffer, scriptTag); hb_language_t language; diff --git a/layout/media/symbols.def.in b/layout/media/symbols.def.in index 1d308a318d1a..84fc943f30d0 100644 --- a/layout/media/symbols.def.in +++ b/layout/media/symbols.def.in @@ -595,6 +595,7 @@ hb_ot_layout_script_get_language_tags hb_ot_layout_table_choose_script hb_ot_layout_table_get_script_tags hb_ot_tag_to_language +hb_ot_tag_to_script hb_ot_tags_from_script hb_set_add hb_set_clear From 106ab919b68e762db7d3cb76fae88b33072c0e44 Mon Sep 17 00:00:00 2001 From: James Kitchener Date: Thu, 30 Jan 2014 10:59:16 -0500 Subject: [PATCH 46/88] Bug 953385 - Set math script flag on textruns belonging to MathML tokens. r=roc --- layout/generic/nsTextFrame.cpp | 22 +++++++++++++++++----- layout/generic/nsTextFrameUtils.h | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index fabeaabda81b..f8ded067ccf0 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1324,11 +1324,16 @@ BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame, "Wrong line container hint"); } - if (aForFrame && aForFrame->HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI)) { - aLineContainer->AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI); - } - if (aForFrame && aForFrame->HasAnyStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT)) { - aLineContainer->AddStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT); + if (aForFrame) { + if (aForFrame->HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML)) { + aLineContainer->AddStateBits(TEXT_IS_IN_TOKEN_MATHML); + if (aForFrame->HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI)) { + aLineContainer->AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI); + } + } + if (aForFrame->HasAnyStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT)) { + aLineContainer->AddStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT); + } } nsPresContext* presContext = aLineContainer->PresContext(); @@ -1980,6 +1985,13 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) anyMathMLStyling = true; } nsIFrame* parent = mLineContainer->GetParent(); + if (mLineContainer->HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML)) { + // All MathML tokens except use 'math' script. + if (!(parent && parent->GetContent() && + parent->GetContent()->Tag() == nsGkAtoms::mtext_)) { + textFlags |= gfxTextRunFactory::TEXT_USE_MATH_SCRIPT; + } + } nsIFrame* child = mLineContainer; uint8_t oldScriptLevel = 0; while (parent && diff --git a/layout/generic/nsTextFrameUtils.h b/layout/generic/nsTextFrameUtils.h index 769e038b0eb5..17b692b75a26 100644 --- a/layout/generic/nsTextFrameUtils.h +++ b/layout/generic/nsTextFrameUtils.h @@ -54,6 +54,9 @@ public: // so that it also has access to the _INCOMING flag // TEXT_TRAILING_ARABICCHAR // TEXT_INCOMING_ARABICCHAR + + // This is defined in gfxTextRunFactory to allow access in gfxFont. + // TEXT_USE_MATH_SCRIPT }; // These constants are used in TransformText to represent context information From d36cb8630c9753597bb05287bc92140acb116e7c Mon Sep 17 00:00:00 2001 From: James Kitchener Date: Thu, 30 Jan 2014 10:59:16 -0500 Subject: [PATCH 47/88] Bug 953385 - Tests for OpenType 'math' script in MathML. r=fredw --- layout/reftests/mathml/mathscript-1-ref.html | 45 +++++++++++++++++++ layout/reftests/mathml/mathscript-1.html | 37 +++++++++++++++ layout/reftests/mathml/mathscript-2-ref.html | 25 +++++++++++ layout/reftests/mathml/mathscript-2.html | 39 ++++++++++++++++ layout/reftests/mathml/mathssty.woff | Bin 0 -> 1384 bytes layout/reftests/mathml/reftest.list | 2 + 6 files changed, 148 insertions(+) create mode 100644 layout/reftests/mathml/mathscript-1-ref.html create mode 100644 layout/reftests/mathml/mathscript-1.html create mode 100644 layout/reftests/mathml/mathscript-2-ref.html create mode 100644 layout/reftests/mathml/mathscript-2.html create mode 100644 layout/reftests/mathml/mathssty.woff diff --git a/layout/reftests/mathml/mathscript-1-ref.html b/layout/reftests/mathml/mathscript-1-ref.html new file mode 100644 index 000000000000..1d3bf301f860 --- /dev/null +++ b/layout/reftests/mathml/mathscript-1-ref.html @@ -0,0 +1,45 @@ + + + + + + + + + +
D
+
D
+ + + + + + D + B + C + + + +

+ + + + C + C + D + + + diff --git a/layout/reftests/mathml/mathscript-1.html b/layout/reftests/mathml/mathscript-1.html new file mode 100644 index 000000000000..7a6e2ae0a19c --- /dev/null +++ b/layout/reftests/mathml/mathscript-1.html @@ -0,0 +1,37 @@ + + + + + + + +

A
+
A
+ + + + + + A + A + A + + + +

+ + + + A + A + A + + + diff --git a/layout/reftests/mathml/mathscript-2-ref.html b/layout/reftests/mathml/mathscript-2-ref.html new file mode 100644 index 000000000000..05f623fe7e6a --- /dev/null +++ b/layout/reftests/mathml/mathscript-2-ref.html @@ -0,0 +1,25 @@ + + + + Dynamic OpenType 'math' script tests + + + + + + +

DD
+ + + + + CC + + + + diff --git a/layout/reftests/mathml/mathscript-2.html b/layout/reftests/mathml/mathscript-2.html new file mode 100644 index 000000000000..ed6ea014f13c --- /dev/null +++ b/layout/reftests/mathml/mathscript-2.html @@ -0,0 +1,39 @@ + + + + Dynamic OpenType 'math' script tests + + + + + + +
A
+ + + + + A + + + + + + + diff --git a/layout/reftests/mathml/mathssty.woff b/layout/reftests/mathml/mathssty.woff new file mode 100644 index 0000000000000000000000000000000000000000..eb6a6677532c6cb7de292b05f076eb6c4cd56f8b GIT binary patch literal 1384 zcmZWpYfw{17~KmYBoHXoR`3O(Qj8EFB!EyNiADnjB$)w5q=nu~9upry1UkkF0?I?N z*q{y~Qo#o*K51!DY9$E?DiB1(M{EOxpz%>gMSNgUZue^KpYF{0zBy-hzui6i&2A70 zg`%V+5daPf-~!-q+yf9I|9=RCLOK8l3nCU`6_Y#Xxlow2900pKIC~C(RUO9`MK4_@ zgjzM^-Vh8B0(_#yqC}|u4mq8GvNCsjbYk)nsF@*;f`}hxJYS1Y9&$> z!%(U8u2YYHC$sa*<-t-^nt@8Qa9!_HLCshht^cEyHZLo45%+sPu5nV8a`(JPcz65r z3m1lIo-gwUG}8)fOV zbOF4xh5!v?QL-+km%n)4;Uh=1vET4q7&YW+H~ka(yW;}-iX)wdzo3gV#BwnvmZ36f z61&2vd@%TG9_lsHmd_K7N(Se@jC*pqrQo}@lT#r(rYI8|ts)RPBT!pXxs(npq#V zw~l?Nil6pGe&o$@d58SQ*#(~s9J)7N&}EeF9?3Xx^zXW|=KW=BylzK%9>_OOs#N#R zo2JGo2oObWnFSq%W)s2ao-HBr)w87s-sPz?k+X<JN`6_;doYjLE^3WP8WnU4KP6Ck}GVDNNJ$&jn?bL}dIOE(K&XHKq{9dYY;y-X7cKxiwyOJ7DdKURNtw#*)Mye_N$bW&o`&n7jTrRKQk@y|NTIh! zTU^N#PUemVbx82sxtsUlMxu2VGHS5J@(qnws9{^I5z!iQVKVuEd5`n8*DlTF#jj;B6a zp*__Sw~o`gp-nx0;`#WA^p*P<0nsI|_UCf1Hrgsqw6yx2zJGf1R?GHZGVN!@Hf-3e zAMvOi+RP>m4zSWo)3~8zy2hj5Bn@zs8Vb#}0S6oZ- Date: Thu, 30 Jan 2014 10:59:16 -0500 Subject: [PATCH 48/88] Bug 960319 - Don't use GLTextures for non-ANGLE D3D WebGL layers. r=vlad --- gfx/layers/d3d10/CanvasLayerD3D10.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.cpp b/gfx/layers/d3d10/CanvasLayerD3D10.cpp index b27d03b3e77f..72625be50f40 100644 --- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp +++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp @@ -63,10 +63,6 @@ CanvasLayerD3D10::Initialize(const Data& aData) factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, device(), screen->Caps()); - } else { - factory = new SurfaceFactory_GLTexture(mGLContext, - nullptr, - screen->Caps()); } } From 8e0d266e53f9cbd050ca703ab9244b0f1d5de8fc Mon Sep 17 00:00:00 2001 From: Michael Shal Date: Thu, 30 Jan 2014 11:14:35 -0500 Subject: [PATCH 49/88] Bug 963123 - NNS Windows build fix to prevent lower case working directories to make the build fail. r=glandium --- security/build/Makefile.in | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/security/build/Makefile.in b/security/build/Makefile.in index 572366548fa5..a666ceb03f19 100644 --- a/security/build/Makefile.in +++ b/security/build/Makefile.in @@ -139,16 +139,11 @@ endif ifdef NSS_DISABLE_DBM DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1 endif -ifeq ($(HOST_OS_ARCH),WINNT) -ABS_topsrcdir := $(shell cd $(topsrcdir); pwd -W) -else -ABS_topsrcdir := $(shell cd $(topsrcdir); pwd) -endif # Hack to force NSS build system to use "normal" object directories -DEFAULT_GMAKE_FLAGS += ABS_topsrcdir='$(ABS_topsrcdir)' -# ABS_topsrcdir can't be expanded here because msys path mangling likes to break +DEFAULT_GMAKE_FLAGS += topsrcdir='$(topsrcdir)' +# topsrcdir can't be expanded here because msys path mangling likes to break # paths in that case. -DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $$(ABS_topsrcdir)/security/,,$$(CURDIR))' +DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $$(topsrcdir)/security/,,$$(CURDIR))' DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)' DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST) ifndef MOZ_DEBUG @@ -226,7 +221,7 @@ DEFAULT_GMAKE_FLAGS += \ STANDARDS_CFLAGS='-std=gnu89' \ $(NULL) -DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -include $(ABS_topsrcdir)/security/manager/android_stub.h' +DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -include $(topsrcdir)/security/manager/android_stub.h' endif endif From aea08d0bde00ec76f8b657ab0aabd9288e67e298 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Thu, 30 Jan 2014 11:17:10 -0500 Subject: [PATCH 50/88] Bug 964976 - Prevent crash of unsupported pixel format gralloc allocation. r=nical --- gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp index 884d780bb148..73bbf11c52c5 100644 --- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp +++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp @@ -172,6 +172,9 @@ PixelFormatForImageFormat(gfxImageFormat aFormat) return android::PIXEL_FORMAT_RGBX_8888; case gfxImageFormat::RGB16_565: return android::PIXEL_FORMAT_RGB_565; + case gfxImageFormat::A8: + NS_WARNING("gralloc does not support gfxImageFormat::A8"); + return android::PIXEL_FORMAT_UNKNOWN; default: MOZ_CRASH("Unknown gralloc pixel format"); } @@ -430,6 +433,10 @@ ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfx::IntSize& aSize, PGrallocBufferChild* gc; bool defaultRBSwap; + if (PixelFormatForContentType(aContent) == android::PIXEL_FORMAT_UNKNOWN) { + return false; + } + if (aCaps & USING_GL_RENDERING_ONLY) { gc = AllocGrallocBuffer(aSize, PixelFormatForContentType(aContent), From f5ee3a4fbe813d65a3094078bcdf0b21175a4c88 Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Wed, 29 Jan 2014 09:28:06 -0500 Subject: [PATCH 51/88] Bug 965246 - Integrate bulk updates from vtt.js. r=rillian Relevant changes for bugs 881976 and 964625. --- content/media/webvtt/vtt.jsm | 37 +++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/content/media/webvtt/vtt.jsm b/content/media/webvtt/vtt.jsm index 4b90bce6ac9c..37c621482d27 100644 --- a/content/media/webvtt/vtt.jsm +++ b/content/media/webvtt/vtt.jsm @@ -8,8 +8,25 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; * Code below is vtt.js the JS WebVTTParser. * Current source code can be found at http://github.com/andreasgal/vtt.js * - * Code taken from commit 33a837b1ceef138a61a3b2f6fac90d5c70bd90d9 + * Code taken from commit d819872e198d051dfcebcfb7ecf260462c9a9c6f */ +/** + * Copyright 2013 vtt.js Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + (function(global) { function ParsingError(message) { @@ -130,7 +147,7 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; throw new ParsingError("Malformed time stamp."); } // Remove time stamp from input. - input = input.replace(/^[^\s-]+/, ""); + input = input.replace(/^[^\sa-zA-Z-]+/, ""); return ts; } @@ -632,13 +649,19 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) { return cue.line; } - if (!cue.track) { + if (!cue.track || !cue.track.textTrackList || + !cue.track.textTrackList.mediaElement) { return -1; } - // TODO: Have to figure out a way to determine what the position of the - // Track is in the Media element's list of TextTracks and return that + 1, - // negated. - return 100; + var track = cue.track, + trackList = track.textTrackList, + count = 0; + for (var i = 0; i < trackList.length && trackList[i] !== track; i++) { + if (trackList[i].mode === "showing") { + count++; + } + } + return ++count * -1; } function BoundingBox() { From f5388f98e71d54cd2954ea9b55eb382de4999c31 Mon Sep 17 00:00:00 2001 From: Douglas Crosher Date: Thu, 30 Jan 2014 01:30:56 +1100 Subject: [PATCH 52/88] Bug 965247 - ARM simulator: Support an environment variable and shell argument to enabling icache checks. r=jandem --- js/src/jit/arm/Simulator-arm.cpp | 8 ++++++-- js/src/shell/js.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/js/src/jit/arm/Simulator-arm.cpp b/js/src/jit/arm/Simulator-arm.cpp index 94fed83ee8d2..14dfb2b0372f 100644 --- a/js/src/jit/arm/Simulator-arm.cpp +++ b/js/src/jit/arm/Simulator-arm.cpp @@ -402,6 +402,8 @@ class AutoLockSimulatorRuntime } }; +bool Simulator::ICacheCheckingEnabled = false; + SimulatorRuntime * CreateSimulatorRuntime() { @@ -413,6 +415,10 @@ CreateSimulatorRuntime() js_delete(srt); return nullptr; } + + if (getenv("ARM_SIM_ICACHE_CHECKS")) + Simulator::ICacheCheckingEnabled = true; + return srt; } @@ -3790,8 +3796,6 @@ Simulator::decodeSpecialCondition(SimInstruction *instr) } } -bool Simulator::ICacheCheckingEnabled = false; - // Executes the current instruction. void Simulator::instructionDecode(SimInstruction *instr) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 3b9b6a214441..9eb3431a6fb8 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -60,6 +60,7 @@ #include "builtin/TestingFunctions.h" #include "frontend/Parser.h" +#include "jit/arm/Simulator-arm.h" #include "jit/Ion.h" #include "js/OldDebugAPI.h" #include "js/StructuredClone.h" @@ -5844,6 +5845,10 @@ main(int argc, char **argv, char **envp) #endif || !op.addIntOption('\0', "available-memory", "SIZE", "Select GC settings based on available memory (MB)", 0) +#ifdef JS_ARM_SIMULATOR + || !op.addBoolOption('\0', "arm-sim-icache-checks", "Enable icache flush checks in the ARM " + "simulator.") +#endif ) { return EXIT_FAILURE; @@ -5892,6 +5897,11 @@ main(int argc, char **argv, char **envp) #endif #endif +#ifdef JS_ARM_SIMULATOR + if (op.getBoolOption("arm-sim-icache-checks")) + jit::Simulator::ICacheCheckingEnabled = true; +#endif + // Start the engine. if (!JS_Init()) return 1; From 4799fe01c342bde38f4603198c7574bee1fbc8a0 Mon Sep 17 00:00:00 2001 From: Simone Carletti Date: Thu, 30 Jan 2014 11:17:11 -0500 Subject: [PATCH 53/88] Bug 965740 - Add Microsoft azure to PSL. r=gerv --- netwerk/dns/effective_tld_names.dat | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat index d36d55be3b78..a847361f5d3b 100644 --- a/netwerk/dns/effective_tld_names.dat +++ b/netwerk/dns/effective_tld_names.dat @@ -7789,6 +7789,12 @@ info.at // Michau Enterprises Limited : http://www.co.pl/ co.pl +// Microsoft : http://microsoft.com +// Submitted by Barry Dorrans 2014-01-24 +azurewebsites.net +azure-mobile.net +cloudapp.net + // NYC.mn : http://www.information.nyc.mn // Submitted by Matthew Brown 2013-03-11 nyc.mn From 4bab919aa07652098b267b54059bbb3773971fa2 Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Wed, 29 Jan 2014 12:57:43 -0500 Subject: [PATCH 54/88] Bug 965336 - Setting TextTrackCue's Start or End times should set its state to dirty. r=rillian --- content/media/TextTrackCue.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/media/TextTrackCue.h b/content/media/TextTrackCue.h index ab46596d0467..a45d18093752 100644 --- a/content/media/TextTrackCue.h +++ b/content/media/TextTrackCue.h @@ -89,6 +89,7 @@ public: } mStartTime = aStartTime; + mReset = true; CueChanged(); } @@ -104,6 +105,7 @@ public: } mEndTime = aEndTime; + mReset = true; CueChanged(); } From 2e107e320451501b1c353fde0bc91bf0c65aea3d Mon Sep 17 00:00:00 2001 From: Simone Carletti Date: Thu, 30 Jan 2014 11:32:08 -0500 Subject: [PATCH 55/88] Bug 965744 - PSL changes for Google private domains. r=gerv --- netwerk/dns/effective_tld_names.dat | 1 + 1 file changed, 1 insertion(+) diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat index a847361f5d3b..220472822e6e 100644 --- a/netwerk/dns/effective_tld_names.dat +++ b/netwerk/dns/effective_tld_names.dat @@ -7772,6 +7772,7 @@ blogspot.tw codespot.com googleapis.com googlecode.com +withgoogle.com // Heroku : https://www.heroku.com/ // Submitted by Tom Maher 2013-05-02 From 6aff20394a0518848572af1085cfeb7eb2284f7b Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Wed, 29 Jan 2014 15:28:57 -0800 Subject: [PATCH 56/88] Bug 965587 - Add lock to Firefox Health Report uploading; r=rnewman Previously, it was technically possible for the FHR client to have multiple simultaneous uploads. While this should never occur in well-behaving systems, server logs have indicated that this behavior might be occurring. This patch adds a lock around uploading to ensure only 1 upload operation may be active at a given time. To measure the impact of this change in the wild, we added a counter that increments whenever a held lock is encountered. --HG-- extra : rebase_source : f0bb5065a3618cd335b6b6f31e4e68850f31f151 --- services/datareporting/policy.jsm | 11 +++ services/healthreport/docs/dataformat.rst | 10 +++ services/healthreport/healthreporter.jsm | 86 ++++++++++++------- services/healthreport/providers.jsm | 28 +++++- .../tests/xpcshell/test_healthreporter.js | 55 ++++++++++-- 5 files changed, 151 insertions(+), 39 deletions(-) diff --git a/services/datareporting/policy.jsm b/services/datareporting/policy.jsm index 20f76265619e..3faedf74d50d 100644 --- a/services/datareporting/policy.jsm +++ b/services/datareporting/policy.jsm @@ -148,6 +148,7 @@ this.DataSubmissionRequest.prototype = Object.freeze({ SUBMISSION_SUCCESS: "success", SUBMISSION_FAILURE_SOFT: "failure-soft", SUBMISSION_FAILURE_HARD: "failure-hard", + UPLOAD_IN_PROGRESS: "upload-in-progress", /** * No submission was attempted because no data was available. @@ -210,6 +211,16 @@ this.DataSubmissionRequest.prototype = Object.freeze({ this.promise.resolve(this); return this.promise.promise; }, + + /** + * The request was aborted because an upload was already in progress. + */ + onUploadInProgress: function (reason=null) { + this.state = this.UPLOAD_IN_PROGRESS; + this.reason = reason; + this.promise.resolve(this); + return this.promise.promise; + }, }); /** diff --git a/services/healthreport/docs/dataformat.rst b/services/healthreport/docs/dataformat.rst index 9e46544cdd73..b6a4bc5958ad 100644 --- a/services/healthreport/docs/dataformat.rst +++ b/services/healthreport/docs/dataformat.rst @@ -996,6 +996,16 @@ org.mozilla.healthreport.submissions This measurement contains a history of FHR's own data submission activity. It was added in Firefox 23 in early May 2013. +Version 2 +^^^^^^^^^ + +This is the same as version 1 except an additional field has been added. + +uploadAlreadyInProgress + A request for upload was initiated while another upload was in progress. + This should not occur in well-behaving clients. It (along with a lock + preventing simultaneous upload) was added to ensure this never occurs. + Version 1 ^^^^^^^^^ diff --git a/services/healthreport/healthreporter.jsm b/services/healthreport/healthreporter.jsm index e844eabf44f8..4065c3d34df7 100644 --- a/services/healthreport/healthreporter.jsm +++ b/services/healthreport/healthreporter.jsm @@ -1144,6 +1144,7 @@ AbstractHealthReporter.prototype = Object.freeze({ */ this.HealthReporter = function (branch, policy, sessionRecorder, stateLeaf=null) { this._stateLeaf = stateLeaf; + this._uploadInProgress = false; AbstractHealthReporter.call(this, branch, policy, sessionRecorder); @@ -1311,6 +1312,7 @@ this.HealthReporter.prototype = Object.freeze({ onSubmissionSuccess: function () {}, onSubmissionFailureSoft: function () {}, onSubmissionFailureHard: function () {}, + onUploadInProgress: function () {}, }; this._uploadData(request); @@ -1374,6 +1376,18 @@ this.HealthReporter.prototype = Object.freeze({ }, _uploadData: function (request) { + // Under ideal circumstances, clients should never race to this + // function. However, server logs have observed behavior where + // racing to this function could be a cause. So, this lock was + // instituted. + if (this._uploadInProgress) { + this._log.warn("Upload requested but upload already in progress."); + let provider = this.getProvider("org.mozilla.healthreport"); + let promise = provider.recordEvent("uploadAlreadyInProgress"); + request.onUploadInProgress("Upload already in progress."); + return promise; + } + let id = CommonUtils.generateUUID(); this._log.info("Uploading data to server: " + this.serverURI + " " + @@ -1382,40 +1396,48 @@ this.HealthReporter.prototype = Object.freeze({ let now = this._now(); return Task.spawn(function doUpload() { - let payload = yield this.getJSONPayload(); - - let histogram = Services.telemetry.getHistogramById(TELEMETRY_PAYLOAD_SIZE_UNCOMPRESSED); - histogram.add(payload.length); - - let lastID = this.lastSubmitID; - yield this._state.addRemoteID(id); - - let hrProvider = this.getProvider("org.mozilla.healthreport"); - if (hrProvider) { - let event = lastID ? "continuationUploadAttempt" - : "firstDocumentUploadAttempt"; - hrProvider.recordEvent(event, now); - } - - TelemetryStopwatch.start(TELEMETRY_UPLOAD, this); - let result; try { - let options = { - deleteIDs: this._state.remoteIDs.filter((x) => { return x != id; }), - telemetryCompressed: TELEMETRY_PAYLOAD_SIZE_COMPRESSED, - }; - result = yield client.uploadJSON(this.serverNamespace, id, payload, - options); - TelemetryStopwatch.finish(TELEMETRY_UPLOAD, this); - } catch (ex) { - TelemetryStopwatch.cancel(TELEMETRY_UPLOAD, this); - if (hrProvider) { - hrProvider.recordEvent("uploadClientFailure", now); - } - throw ex; - } + // The test for upload locking monkeypatches getJSONPayload. + // If the next two lines change, be sure to verify the test is + // accurate! + this._uploadInProgress = true; + let payload = yield this.getJSONPayload(); - yield this._onBagheeraResult(request, false, now, result); + let histogram = Services.telemetry.getHistogramById(TELEMETRY_PAYLOAD_SIZE_UNCOMPRESSED); + histogram.add(payload.length); + + let lastID = this.lastSubmitID; + yield this._state.addRemoteID(id); + + let hrProvider = this.getProvider("org.mozilla.healthreport"); + if (hrProvider) { + let event = lastID ? "continuationUploadAttempt" + : "firstDocumentUploadAttempt"; + hrProvider.recordEvent(event, now); + } + + TelemetryStopwatch.start(TELEMETRY_UPLOAD, this); + let result; + try { + let options = { + deleteIDs: this._state.remoteIDs.filter((x) => { return x != id; }), + telemetryCompressed: TELEMETRY_PAYLOAD_SIZE_COMPRESSED, + }; + result = yield client.uploadJSON(this.serverNamespace, id, payload, + options); + TelemetryStopwatch.finish(TELEMETRY_UPLOAD, this); + } catch (ex) { + TelemetryStopwatch.cancel(TELEMETRY_UPLOAD, this); + if (hrProvider) { + hrProvider.recordEvent("uploadClientFailure", now); + } + throw ex; + } + + yield this._onBagheeraResult(request, false, now, result); + } finally { + this._uploadInProgress = false; + } }.bind(this)); }, diff --git a/services/healthreport/providers.jsm b/services/healthreport/providers.jsm index d082ca4fa1c6..b1e728a41297 100644 --- a/services/healthreport/providers.jsm +++ b/services/healthreport/providers.jsm @@ -1367,6 +1367,27 @@ HealthReportSubmissionMeasurement1.prototype = Object.freeze({ }, }); +function HealthReportSubmissionMeasurement2() { + Metrics.Measurement.call(this); +} + +HealthReportSubmissionMeasurement2.prototype = Object.freeze({ + __proto__: Metrics.Measurement.prototype, + + name: "submissions", + version: 2, + + fields: { + firstDocumentUploadAttempt: DAILY_COUNTER_FIELD, + continuationUploadAttempt: DAILY_COUNTER_FIELD, + uploadSuccess: DAILY_COUNTER_FIELD, + uploadTransportFailure: DAILY_COUNTER_FIELD, + uploadServerFailure: DAILY_COUNTER_FIELD, + uploadClientFailure: DAILY_COUNTER_FIELD, + uploadAlreadyInProgress: DAILY_COUNTER_FIELD, + }, +}); + this.HealthReportProvider = function () { Metrics.Provider.call(this); } @@ -1376,10 +1397,13 @@ HealthReportProvider.prototype = Object.freeze({ name: "org.mozilla.healthreport", - measurementTypes: [HealthReportSubmissionMeasurement1], + measurementTypes: [ + HealthReportSubmissionMeasurement1, + HealthReportSubmissionMeasurement2, + ], recordEvent: function (event, date=new Date()) { - let m = this.getMeasurement("submissions", 1); + let m = this.getMeasurement("submissions", 2); return this.enqueueStorageOperation(function recordCounter() { return m.incrementDailyCounter(event, date); }); diff --git a/services/healthreport/tests/xpcshell/test_healthreporter.js b/services/healthreport/tests/xpcshell/test_healthreporter.js index 6bd48b0ed14d..5a4d2f78d0d1 100644 --- a/services/healthreport/tests/xpcshell/test_healthreporter.js +++ b/services/healthreport/tests/xpcshell/test_healthreporter.js @@ -75,7 +75,7 @@ function getHealthReportProviderValues(reporter, day=null) { return Task.spawn(function getValues() { let p = reporter.getProvider("org.mozilla.healthreport"); do_check_neq(p, null); - let m = p.getMeasurement("submissions", 1); + let m = p.getMeasurement("submissions", 2); do_check_neq(m, null); let data = yield reporter._storage.getMeasurementValues(m.id); @@ -86,6 +86,7 @@ function getHealthReportProviderValues(reporter, day=null) { do_check_true(data.days.hasDay(day)); let serializer = m.serializer(m.SERIALIZE_JSON) let json = serializer.daily(data.days.getDay(day)); + do_check_eq(json._v, 2); throw new Task.Result(json); }); @@ -565,7 +566,6 @@ add_task(function test_data_submission_transport_failure() { do_check_eq(request.state, request.SUBMISSION_FAILURE_SOFT); let data = yield getHealthReportProviderValues(reporter, new Date()); - do_check_eq(data._v, 1); do_check_eq(data.firstDocumentUploadAttempt, 1); do_check_eq(data.uploadTransportFailure, 1); do_check_eq(Object.keys(data).length, 3); @@ -592,7 +592,6 @@ add_task(function test_data_submission_server_failure() { do_check_eq(request.state, request.SUBMISSION_FAILURE_HARD); let data = yield getHealthReportProviderValues(reporter, now); - do_check_eq(data._v, 1); do_check_eq(data.firstDocumentUploadAttempt, 1); do_check_eq(data.uploadServerFailure, 1); do_check_eq(Object.keys(data).length, 3); @@ -631,7 +630,6 @@ add_task(function test_data_submission_success() { do_check_true("DummyConstantProvider.DummyMeasurement" in o.data.last); let data = yield getHealthReportProviderValues(reporter, now); - do_check_eq(data._v, 1); do_check_eq(data.continuationUploadAttempt, 1); do_check_eq(data.uploadSuccess, 1); do_check_eq(Object.keys(data).length, 3); @@ -682,7 +680,6 @@ add_task(function test_recurring_daily_pings() { // now() on the health reporter instance wasn't munged. So, we should see // both requests attributed to the same day. let data = yield getHealthReportProviderValues(reporter, new Date()); - do_check_eq(data._v, 1); do_check_eq(data.firstDocumentUploadAttempt, 1); do_check_eq(data.continuationUploadAttempt, 1); do_check_eq(data.uploadSuccess, 2); @@ -720,6 +717,54 @@ add_task(function test_request_remote_data_deletion() { } }); +add_task(function test_multiple_simultaneous_uploads() { + let [reporter, server] = yield getReporterAndServer("multiple_simultaneous_uploads"); + + try { + let d1 = Promise.defer(); + let d2 = Promise.defer(); + let t1 = new Date(Date.now() - 1000); + let t2 = new Date(t1.getTime() + 500); + let r1 = new DataSubmissionRequest(d1, t1); + let r2 = new DataSubmissionRequest(d2, t2); + + let getPayloadDeferred = Promise.defer(); + + Object.defineProperty(reporter, "getJSONPayload", { + configurable: true, + value: () => { + getPayloadDeferred.resolve(); + delete reporter["getJSONPayload"]; + return reporter.getJSONPayload(); + }, + }); + + let p1 = reporter.requestDataUpload(r1); + yield getPayloadDeferred.promise; + do_check_true(reporter._uploadInProgress); + let p2 = reporter.requestDataUpload(r2); + + yield p1; + yield p2; + + do_check_eq(r1.state, r1.SUBMISSION_SUCCESS); + do_check_eq(r2.state, r2.UPLOAD_IN_PROGRESS); + + // They should both be resolved already. + yield d1; + yield d2; + + let data = yield getHealthReportProviderValues(reporter, t1); + do_check_eq(data.firstDocumentUploadAttempt, 1); + do_check_false("continuationUploadAttempt" in data); + do_check_eq(data.uploadSuccess, 1); + do_check_eq(data.uploadAlreadyInProgress, 1); + } finally { + reporter._shutdown(); + yield shutdownServer(server); + } +}); + add_task(function test_policy_accept_reject() { let [reporter, server] = yield getReporterAndServer("policy_accept_reject"); From fba7012b6a103ccbbb5adef10086cf7f4c5dc456 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 28 Jan 2014 04:33:00 +0100 Subject: [PATCH 57/88] Bug 961821: jit-support for writes into TypedObject arrays. As part of above, alpha-renamed IonBuilder::setElemTryTyped to IonBuilder::setElemTryTypedArray to keep clear the current distinction between TypedObject and TypedArray. Drive-by fix: Reference to Bug 894105 in comment had off-by-one typo. Bug 961821: jit-support for writes into TypedObject arrays (r=nmatsakis). As part of above, alpha-renamed IonBuilder::setElemTryTyped to IonBuilder::setElemTryTypedArray to keep clear the current distinction between TypedObject and TypedArray. Drive-by fix: Reference to Bug 894105 in comment had off-by-one typo. --- js/src/jit/IonBuilder.cpp | 91 +++++++++++++++++++++++++++++++++++++-- js/src/jit/IonBuilder.h | 11 ++++- 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index ddf1f9ec9717..adb7b81c620e 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -6635,7 +6635,7 @@ IonBuilder::getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition * switch (elemTypeReprs.kind()) { case TypeRepresentation::X4: - // FIXME (bug 894104): load into a MIRType_float32x4 etc + // FIXME (bug 894105): load into a MIRType_float32x4 etc return true; case TypeRepresentation::Struct: @@ -7350,10 +7350,13 @@ IonBuilder::jsop_setelem() MDefinition *index = current->pop(); MDefinition *object = current->pop(); + if (!setElemTryTypedObject(&emitted, object, index, value) || emitted) + return emitted; + if (!setElemTryTypedStatic(&emitted, object, index, value) || emitted) return emitted; - if (!setElemTryTyped(&emitted, object, index, value) || emitted) + if (!setElemTryTypedArray(&emitted, object, index, value) || emitted) return emitted; if (!setElemTryDense(&emitted, object, index, value) || emitted) @@ -7376,6 +7379,86 @@ IonBuilder::jsop_setelem() return resumeAfter(ins); } +bool +IonBuilder::setElemTryTypedObject(bool *emitted, MDefinition *obj, + MDefinition *index, MDefinition *value) +{ + JS_ASSERT(*emitted == false); + + TypeRepresentationSet objTypeReprs; + if (!lookupTypeRepresentationSet(obj, &objTypeReprs)) + return false; + + if (!objTypeReprs.allOfArrayKind()) + return true; + + TypeRepresentationSet elemTypeReprs; + if (!objTypeReprs.arrayElementType(*this, &elemTypeReprs)) + return false; + if (elemTypeReprs.empty()) + return true; + + JS_ASSERT(TypeRepresentation::isSized(elemTypeReprs.kind())); + + size_t elemSize; + if (!elemTypeReprs.allHaveSameSize(&elemSize)) + return true; + + switch (elemTypeReprs.kind()) { + case TypeRepresentation::X4: + // FIXME (bug 894105): store a MIRType_float32x4 etc + return true; + + case TypeRepresentation::Reference: + case TypeRepresentation::Struct: + case TypeRepresentation::SizedArray: + case TypeRepresentation::UnsizedArray: + // For now, only optimize storing scalars. + return true; + + case TypeRepresentation::Scalar: + return setElemTryScalarPropOfTypedObject(emitted, + obj, + index, + objTypeReprs, + value, + elemTypeReprs, + elemSize); + } + + MOZ_ASSUME_UNREACHABLE("Bad kind"); +} + +bool +IonBuilder::setElemTryScalarPropOfTypedObject(bool *emitted, + MDefinition *obj, + MDefinition *index, + TypeRepresentationSet objTypeReprs, + MDefinition *value, + TypeRepresentationSet elemTypeReprs, + size_t elemSize) +{ + // Must always be storing the same scalar type + if (!elemTypeReprs.singleton()) + return true; + + ScalarTypeRepresentation *elemTypeRepr = + elemTypeReprs.getTypeRepresentation()->asScalar(); + + MDefinition *indexAsByteOffset; + if (!checkTypedObjectIndexInBounds(elemSize, obj, index, &indexAsByteOffset, objTypeReprs)) + return false; + + // Store the element + if (!storeScalarTypedObjectValue(obj, indexAsByteOffset, elemTypeRepr, value)) + return false; + + current->push(value); + + *emitted = true; + return true; +} + bool IonBuilder::setElemTryTypedStatic(bool *emitted, MDefinition *object, MDefinition *index, MDefinition *value) @@ -7428,8 +7511,8 @@ IonBuilder::setElemTryTypedStatic(bool *emitted, MDefinition *object, } bool -IonBuilder::setElemTryTyped(bool *emitted, MDefinition *object, - MDefinition *index, MDefinition *value) +IonBuilder::setElemTryTypedArray(bool *emitted, MDefinition *object, + MDefinition *index, MDefinition *value) { JS_ASSERT(*emitted == false); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index bce41c5df58a..5bb36ca99d54 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -464,8 +464,10 @@ class IonBuilder : public MIRGenerator TypeRepresentationSet objTypeReprs); // jsop_setelem() helpers. - bool setElemTryTyped(bool *emitted, MDefinition *object, + bool setElemTryTypedArray(bool *emitted, MDefinition *object, MDefinition *index, MDefinition *value); + bool setElemTryTypedObject(bool *emitted, MDefinition *obj, + MDefinition *index, MDefinition *value); bool setElemTryTypedStatic(bool *emitted, MDefinition *object, MDefinition *index, MDefinition *value); bool setElemTryDense(bool *emitted, MDefinition *object, @@ -474,6 +476,13 @@ class IonBuilder : public MIRGenerator MDefinition *index, MDefinition *value); bool setElemTryCache(bool *emitted, MDefinition *object, MDefinition *index, MDefinition *value); + bool setElemTryScalarPropOfTypedObject(bool *emitted, + MDefinition *obj, + MDefinition *index, + TypeRepresentationSet objTypeReprs, + MDefinition *value, + TypeRepresentationSet elemTypeReprs, + size_t elemSize); // jsop_getelem() helpers. bool getElemTryDense(bool *emitted, MDefinition *obj, MDefinition *index); From c200f20793b62cd3593f46b45b4f3788741aa5bf Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 30 Jan 2014 17:47:14 +0100 Subject: [PATCH 58/88] Bug 961821: tests for jit-support for writes into TypedObject arrays (r=pnkfelix). These iteration counts were selected to be close to the minimum number necessary to expose bugs while working on this patch (see comments in Bug 961821 for more details here). Note that they are all 500 iterations (not 5000); please be wary of reducing the iteration count further without first ensuring that the jit has time to compile this code. --- .../jit-write-u16-into-mdim-array.js | 43 +++++++++++++++++++ .../jit-write-u16-into-u16-array-in-struct.js | 34 +++++++++++++++ .../jit-write-u16-into-u16-array.js | 25 +++++++++++ .../jit-write-u32-into-mdim-array.js | 43 +++++++++++++++++++ .../jit-write-u32-into-u32-array-in-struct.js | 34 +++++++++++++++ .../jit-write-u32-into-u32-array.js | 25 +++++++++++ 6 files changed, 204 insertions(+) create mode 100644 js/src/jit-test/tests/TypedObject/jit-write-u16-into-mdim-array.js create mode 100644 js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array-in-struct.js create mode 100644 js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array.js create mode 100644 js/src/jit-test/tests/TypedObject/jit-write-u32-into-mdim-array.js create mode 100644 js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array-in-struct.js create mode 100644 js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array.js diff --git a/js/src/jit-test/tests/TypedObject/jit-write-u16-into-mdim-array.js b/js/src/jit-test/tests/TypedObject/jit-write-u16-into-mdim-array.js new file mode 100644 index 000000000000..3d826d6607e7 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/jit-write-u16-into-mdim-array.js @@ -0,0 +1,43 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +setJitCompilerOption("ion.usecount.trigger", 30); + +var PointType = TypedObject.uint16.array(3); +var VecPointType = PointType.array(3); + +function foo() { + for (var i = 0; i < 5000; i += 10) { + var vec = new VecPointType(); + + var i0 = i % 3; + var i1 = (i+1) % 3; + var i2 = (i+2) % 3; + + vec[i0][i0] = i; + vec[i0][i1] = i+1; + vec[i0][i2] = i+2; + + vec[i1][i0] = i+3; + vec[i1][i1] = i+4; + vec[i1][i2] = i+5; + + vec[i2][i0] = i+6; + vec[i2][i1] = i+7; + vec[i2][i2] = i+8; + + var sum = vec[i0][i0] + vec[i0][i1] + vec[i0][i2]; + assertEq(sum, 3*i + 3); + sum = vec[i1][i0] + vec[i1][i1] + vec[i1][i2]; + assertEq(sum, 3*i + 12); + sum = vec[i2][i0] + vec[i2][i1] + vec[i2][i2]; + assertEq(sum, 3*i + 21); + } +} + +foo(); diff --git a/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array-in-struct.js b/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array-in-struct.js new file mode 100644 index 000000000000..eb27392f80e9 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array-in-struct.js @@ -0,0 +1,34 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +setJitCompilerOption("ion.usecount.trigger", 30); + +var Vec3u16Type = TypedObject.uint16.array(3); +var PairVec3u16Type = new TypedObject.StructType({fst: Vec3u16Type, + snd: Vec3u16Type}); + +function foo_u16() { + for (var i = 0; i < 5000; i += 10) { + var p = new PairVec3u16Type(); + + p.fst[(i) % 3] = i; + p.fst[(i+1) % 3] = i+1; + p.fst[(i+2) % 3] = i+2; + + p.snd[(i) % 3] = i+3; + p.snd[(i+1) % 3] = i+4; + p.snd[(i+2) % 3] = i+5; + + var sum = p.fst[0] + p.fst[1] + p.fst[2]; + assertEq(sum, 3*i + 3); + sum = p.snd[0] + p.snd[1] + p.snd[2]; + assertEq(sum, 3*i + 12); + } +} + +foo_u16(); diff --git a/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array.js b/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array.js new file mode 100644 index 000000000000..bbd80ddbe7ef --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/jit-write-u16-into-u16-array.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +setJitCompilerOption("ion.usecount.trigger", 30); + +var Vec3u16Type = TypedObject.uint16.array(3); + +function foo_u16() { + for (var i = 0; i < 5000; i += 10) { + var vec = new Vec3u16Type(); + // making index non-trivially dependent on |i| to foil compiler optimization + vec[(i) % 3] = i; + vec[(i + 1) % 3] = i+1; + vec[(i + 2) % 3] = i+2; + var sum = vec[0] + vec[1] + vec[2]; + assertEq(sum, 3*i + 3); + } +} + +foo_u16(); diff --git a/js/src/jit-test/tests/TypedObject/jit-write-u32-into-mdim-array.js b/js/src/jit-test/tests/TypedObject/jit-write-u32-into-mdim-array.js new file mode 100644 index 000000000000..0c069b7ac8b1 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/jit-write-u32-into-mdim-array.js @@ -0,0 +1,43 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +setJitCompilerOption("ion.usecount.trigger", 30); + +var PointType = TypedObject.uint32.array(3); +var VecPointType = PointType.array(3); + +function foo() { + for (var i = 0; i < 5000; i += 10) { + var vec = new VecPointType(); + + var i0 = i % 3; + var i1 = (i+1) % 3; + var i2 = (i+2) % 3; + + vec[i0][i0] = i; + vec[i0][i1] = i+1; + vec[i0][i2] = i+2; + + vec[i1][i0] = i+3; + vec[i1][i1] = i+4; + vec[i1][i2] = i+5; + + vec[i2][i0] = i+6; + vec[i2][i1] = i+7; + vec[i2][i2] = i+8; + + var sum = vec[i0][i0] + vec[i0][i1] + vec[i0][i2]; + assertEq(sum, 3*i + 3); + sum = vec[i1][i0] + vec[i1][i1] + vec[i1][i2]; + assertEq(sum, 3*i + 12); + sum = vec[i2][i0] + vec[i2][i1] + vec[i2][i2]; + assertEq(sum, 3*i + 21); + } +} + +foo(); diff --git a/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array-in-struct.js b/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array-in-struct.js new file mode 100644 index 000000000000..a4fe72a1af73 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array-in-struct.js @@ -0,0 +1,34 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +setJitCompilerOption("ion.usecount.trigger", 30); + +var Vec3u32Type = TypedObject.uint32.array(3); +var PairVec3u32Type = new TypedObject.StructType({fst: Vec3u32Type, + snd: Vec3u32Type}); + +function foo_u32() { + for (var i = 0; i < 5000; i += 10) { + var p = new PairVec3u32Type(); + + p.fst[(i) % 3] = i; + p.fst[(i+1) % 3] = i+1; + p.fst[(i+2) % 3] = i+2; + + p.snd[(i) % 3] = i+3; + p.snd[(i+1) % 3] = i+4; + p.snd[(i+2) % 3] = i+5; + + var sum = p.fst[0] + p.fst[1] + p.fst[2]; + assertEq(sum, 3*i + 3); + sum = p.snd[0] + p.snd[1] + p.snd[2]; + assertEq(sum, 3*i + 12); + } +} + +foo_u32(); diff --git a/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array.js b/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array.js new file mode 100644 index 000000000000..d75aacaba9b6 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/jit-write-u32-into-u32-array.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +setJitCompilerOption("ion.usecount.trigger", 30); + +var Vec3u32Type = TypedObject.uint32.array(3); + +function foo_u32() { + for (var i = 0; i < 5000; i += 10) { + var vec = new Vec3u32Type(); + // making index non-trivially dependent on |i| to foil compiler optimization + vec[(i) % 3] = i; + vec[(i + 1) % 3] = i+1; + vec[(i + 2) % 3] = i+2; + var sum = vec[0] + vec[1] + vec[2]; + assertEq(sum, 3*i + 3); + } +} + +foo_u32(); From 117e9d0005581c5a61f2d90a271d9160bf87aa5e Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 28 Jan 2014 06:47:38 -0700 Subject: [PATCH 59/88] Bug 936226 - Mark canvas-drawImage-scale-2a.html as passing on Android x86; r=dminor --- layout/reftests/svg/as-image/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/svg/as-image/reftest.list b/layout/reftests/svg/as-image/reftest.list index 39e4addcc8f7..83f95d660148 100644 --- a/layout/reftests/svg/as-image/reftest.list +++ b/layout/reftests/svg/as-image/reftest.list @@ -42,7 +42,7 @@ skip-if(B2G) == canvas-drawImage-scale-1b.html lime100x100-ref.html skip-if(B2G) == canvas-drawImage-scale-1c.html lime100x100-ref.html # Fuzzyness and fails for scaling should be fixed by bug 941467 -fuzzy(1,2) fails-if(Android&&AndroidVersion!=15) == canvas-drawImage-scale-2a.html canvas-drawImage-scale-2-ref.html +fuzzy(1,2) fails-if(Android&&AndroidVersion<15) == canvas-drawImage-scale-2a.html canvas-drawImage-scale-2-ref.html fails == canvas-drawImage-scale-2b.html canvas-drawImage-scale-2-ref.html skip-if(B2G) == canvas-drawImage-slice-1a.html lime100x100-ref.html From 4474ad6357b11fc34a4567deab2fea490b01d997 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 28 Jan 2014 06:47:41 -0700 Subject: [PATCH 60/88] Bug 927602 - (2) Skip reftest font-stretch-1.html on Android x86; r=dminor --- layout/reftests/font-matching/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/font-matching/reftest.list b/layout/reftests/font-matching/reftest.list index b2e7e1f38174..b4d64c2be9fa 100644 --- a/layout/reftests/font-matching/reftest.list +++ b/layout/reftests/font-matching/reftest.list @@ -68,7 +68,7 @@ HTTP(..) == stretchmapping-35.html stretchmapping-35-ref.html HTTP(..) == stretchmapping-137.html stretchmapping-137-ref.html # test for font-stretch using @font-face -skip-if(B2G) HTTP(..) == font-stretch-1.html font-stretch-1-ref.html # bug 773482 +skip-if(B2G) skip-if(Android&&AndroidVersion>15) HTTP(..) == font-stretch-1.html font-stretch-1-ref.html # bugs 773482, 927602 # bug 724231 - applying synthetic styles to a single @font-face font # should apply artificial obliquing, not switch to a true styled face From 6f4339d119f98fd3aeb87d6ce1b7b1499c5c61bd Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 29 Jan 2014 22:15:13 -0800 Subject: [PATCH 61/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/76cfb7597078 Author: Dietrich Ayala Desc: Merge pull request #15822 from autonome/961946 Bug 961946 - a bunch of errors at startup in desktop Firefox ======== https://hg.mozilla.org/integration/gaia-central/rev/2b9b7313403f Author: Dietrich Ayala Desc: Bug 961946 - a bunch of errors at startup in desktop Firefox (r=kgrandon) --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 6e63af9d932a..6102901d3086 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "d369bbb3b7c415097c7c1fa303843cf5683cd843", + "revision": "76cfb75970783fe9f99cca63701e8d357efc03b5", "repo_path": "/integration/gaia-central" } From efbf0448ec168d719e63d94bfac63d3b0209512b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 29 Jan 2014 22:16:05 -0800 Subject: [PATCH 62/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 62cee6e4e1ca..b508b4c2d0da 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6a9239214bc4..6f35171a3f8f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 62cee6e4e1ca..b508b4c2d0da 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 0f4af111ea25..f73e0c8b83b8 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index b155c02ba1af..08b573ad35d0 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index c0f13b12b83c..d15c735c8070 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index c0eb2da30967..182bc9b20746 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index 24b6ec7dd568..31351fc85fa2 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 64fe4292a242..1d71c07816e8 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From 2ac2e0390162e244dd998315d4988174aa5131fc Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 00:00:11 -0800 Subject: [PATCH 63/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/efe61b291757 Author: Kyle Machulis Desc: Merge pull request #15825 from qdot/936037-pin-failure-in-ftu Bug 963037 - Bring up PUK entry when PIN entry retries run out ======== https://hg.mozilla.org/integration/gaia-central/rev/6ce8c896d1db Author: Kyle Machulis Desc: Bug 963037 - Bring up PUK entry when PIN entry retries run out; r=mhenretty --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 6102901d3086..7464162d9e97 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "76cfb75970783fe9f99cca63701e8d357efc03b5", + "revision": "efe61b291757751c1ac1f7898d165d241e0c2113", "repo_path": "/integration/gaia-central" } From 2014c5327dbd4891858a5617c43913dea3035944 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 00:05:59 -0800 Subject: [PATCH 64/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b508b4c2d0da..b93c038f9430 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6f35171a3f8f..e5fdeb6e205c 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b508b4c2d0da..b93c038f9430 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index f73e0c8b83b8..612c6b443fe9 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 08b573ad35d0..15cbb43919fa 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index d15c735c8070..eb092a54073d 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index 182bc9b20746..aa06d9a92342 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index 31351fc85fa2..b8ed9099f635 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 1d71c07816e8..3daec32028b7 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From f172095e61a6a6dc600553328267be627605f6ed Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 01:00:10 -0800 Subject: [PATCH 65/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/f542fff871d9 Author: Fernando Jiménez Moreno Desc: Merge pull request #15713 from jankeromnes/developer Bug 963039 - [B2G][Settings] Developer settings are too hard to access. r=vingtetun ======== https://hg.mozilla.org/integration/gaia-central/rev/c5ce933f7cd0 Author: Jan Keromnes Desc: Bug 963039 - [B2G][Settings] Developer settings are too hard to access r=vingtetun --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7464162d9e97..dd21ba435f04 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "efe61b291757751c1ac1f7898d165d241e0c2113", + "revision": "f542fff871d9f50ba4fc217430d287fa5876c08d", "repo_path": "/integration/gaia-central" } From 48dcc41318d8caccf70e46b9a2b62039cb6ed749 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 01:05:57 -0800 Subject: [PATCH 66/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b93c038f9430..451dea6f123f 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e5fdeb6e205c..e93e08a57c5d 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b93c038f9430..451dea6f123f 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 612c6b443fe9..588ebbcfa53d 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 15cbb43919fa..b955c680419e 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index eb092a54073d..a2bce6bb0b37 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index aa06d9a92342..b40639eaf30b 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index b8ed9099f635..87d5ffec23ac 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 3daec32028b7..0b7456a16754 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From 9ecc40ac6d415dcca126a48ab306ceb9d2756c3e Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 01:25:10 -0800 Subject: [PATCH 67/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/a4df4b081ede Author: Germán Toro del Valle Desc: Merge pull request #15727 from gtorodelvalle/contacts-bug-962989-message-to-Facebook-contact Bug 962989 - [messages] sending message to a Facebook contact doesn't work (r=jmcanterafonseca) ======== https://hg.mozilla.org/integration/gaia-central/rev/0b87cc86a46a Author: Germán Toro del Valle Desc: Bug 962989 - [messages] sending message to a Facebook contact doesn't work --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index dd21ba435f04..087d5e0c7489 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "f542fff871d9f50ba4fc217430d287fa5876c08d", + "revision": "a4df4b081ede864308252ef09464423ab208ae32", "repo_path": "/integration/gaia-central" } From 1534722c045a59022015bbbf942bf5372c66d68a Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 01:30:58 -0800 Subject: [PATCH 68/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 451dea6f123f..92a9bd213ae1 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e93e08a57c5d..6901771c7d17 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 451dea6f123f..92a9bd213ae1 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 588ebbcfa53d..04955645198d 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index b955c680419e..ecb9e936033b 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index a2bce6bb0b37..f19eae9d3275 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index b40639eaf30b..4d54bc7a83df 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index 87d5ffec23ac..50b81f61d6d6 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 0b7456a16754..09b5b0f8d685 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From 716e5152085fd62a9c3d337c8ad03bd30fc7b6f9 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 05:00:10 -0800 Subject: [PATCH 69/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/df44abce9cf0 Author: Etienne Segonzac Desc: Merge pull request #15668 from mukeshk1990/Bug_947086_Dialer_may_call_CDMA-specific_bluetooth_functions_on_non-CDMA_phone Bug 947086 - [Dialer] Dialer may call CDMA-specific bluetooth functions r=etienne ======== https://hg.mozilla.org/integration/gaia-central/rev/4c06e7973b59 Author: mukeshk1990 Desc: Bug 947086 - [Dialer] Dialer may call CDMA-specific bluetooth functions on non-CDMA phone --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 087d5e0c7489..49373296f572 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "a4df4b081ede864308252ef09464423ab208ae32", + "revision": "df44abce9cf0db088eb2bfa06e545f43b9b8a812", "repo_path": "/integration/gaia-central" } From 05c23cd1416aaed47d62e9ceef960d1d97522b13 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 05:06:12 -0800 Subject: [PATCH 70/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 92a9bd213ae1..b2a6bfcc1523 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6901771c7d17..8364a630efa0 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 92a9bd213ae1..b2a6bfcc1523 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 04955645198d..e6e06a402566 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index ecb9e936033b..836562455e5a 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index f19eae9d3275..4d39ea22974a 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index 4d54bc7a83df..2e6f4a4da731 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index 50b81f61d6d6..21a3ab706503 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 09b5b0f8d685..22bee90c038b 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From eb8951e4dfd1d5f8f6e5594abcb06509f80006f8 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 05:35:10 -0800 Subject: [PATCH 71/88] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/cc6bfe9d45c4 Author: Kevin Grandon Desc: Bug 965380 - [Search] Abstract local result rendering r=daleharvey --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 49373296f572..65dc1e1900f2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "df44abce9cf0db088eb2bfa06e545f43b9b8a812", + "revision": "cc6bfe9d45c4d818167c78c2e9b39a5a9022f95e", "repo_path": "/integration/gaia-central" } From 16ff0e3f9286642065724c48e7fafc968df62302 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 05:36:00 -0800 Subject: [PATCH 72/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b2a6bfcc1523..55429d98fe67 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 8364a630efa0..0297a575dd4c 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b2a6bfcc1523..55429d98fe67 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index e6e06a402566..6f4552917f77 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 836562455e5a..5c9ace7971ba 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index 4d39ea22974a..8259b3a5a7d9 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index 2e6f4a4da731..a25e0cfae2f5 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index 21a3ab706503..e976405d5329 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 22bee90c038b..c133934745dc 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From fc8867f9a60c20d7d846d2b9faf92103232fbc6d Mon Sep 17 00:00:00 2001 From: Dale Harvey Date: Thu, 30 Jan 2014 14:50:14 +0000 Subject: [PATCH 73/88] Bug 958666 - Disable autofocus on b2g. r=vingetun --- b2g/app/b2g.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 975f7a2457d7..b402efa56c0c 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -886,3 +886,7 @@ pref("apz.asyncscroll.throttle", 40); // Using a software canvas can save memory when JS calls getImageData() // on the canvas frequently. See bug 884226. pref("gfx.canvas.willReadFrequently.enable", true); + +// Disable autofocus until we can have it not bring up the keyboard. +// https://bugzilla.mozilla.org/show_bug.cgi?id=965763 +pref("browser.autofocus", false); From 6e5f933bf2b02107c9fcfbb0ce253351cab39bb5 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 07:05:10 -0800 Subject: [PATCH 74/88] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/ba7efaf080eb Author: Gabriele Svelto Desc: Bug 960280 - Generate canvases that are not displayed with the appropriate tag to reduce memory usage r=arcturus --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 65dc1e1900f2..b2997e67641f 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "cc6bfe9d45c4d818167c78c2e9b39a5a9022f95e", + "revision": "ba7efaf080ebf86f5ad728cd8b02a81248b306b0", "repo_path": "/integration/gaia-central" } From 6afd9cc874ec01fe895dc7e69ddbfc252e573632 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 07:05:58 -0800 Subject: [PATCH 75/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 55429d98fe67..94581a472cb8 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 0297a575dd4c..63d40576989f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 55429d98fe67..94581a472cb8 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 6f4552917f77..6df573d87a9f 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 5c9ace7971ba..90d9021b11ce 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index 8259b3a5a7d9..67406154e1e1 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index a25e0cfae2f5..17eef32ed912 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index e976405d5329..7f0358dcc0b3 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index c133934745dc..7d444e1948d2 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From 0c268a146581840047c5dff1e8448fce73860349 Mon Sep 17 00:00:00 2001 From: Randy Lin Date: Wed, 29 Jan 2014 23:09:43 +0800 Subject: [PATCH 76/88] Bug 957841 - MediaRecorder crash [@ mozilla::dom::MediaRecorder::Session::AfterTracksAdded]. r=roc --- content/media/MediaRecorder.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/content/media/MediaRecorder.cpp b/content/media/MediaRecorder.cpp index 9bfc4ab34f9f..e8d55d0319b4 100644 --- a/content/media/MediaRecorder.cpp +++ b/content/media/MediaRecorder.cpp @@ -172,7 +172,8 @@ class MediaRecorder::Session: public nsIObserver // We need to switch MediaRecorder to "Stop" state first to make sure // MediaRecorder is not associated with this Session anymore, then, it's // safe to delete this Session. - if (recorder->mState != RecordingState::Inactive) { + // Also avoid to run if this session already call stop before + if (!mSession->mStopIssued) { ErrorResult result; recorder->Stop(result); NS_DispatchToMainThread(new DestroyRunnable(mSession.forget())); @@ -182,8 +183,8 @@ class MediaRecorder::Session: public nsIObserver // Dispatch stop event and clear MIME type. recorder->DispatchSimpleEvent(NS_LITERAL_STRING("stop")); - recorder->SetMimeType(NS_LITERAL_STRING("")); - + mSession->mMimeType = NS_LITERAL_STRING(""); + recorder->SetMimeType(mSession->mMimeType); return NS_OK; } @@ -200,7 +201,8 @@ class MediaRecorder::Session: public nsIObserver public: Session(MediaRecorder* aRecorder, int32_t aTimeSlice) : mRecorder(aRecorder), - mTimeSlice(aTimeSlice) + mTimeSlice(aTimeSlice), + mStopIssued(false) { MOZ_ASSERT(NS_IsMainThread()); @@ -226,6 +228,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); + mStopIssued = true; CleanupStreams(); nsContentUtils::UnregisterShutdownObserver(this); } @@ -248,10 +251,7 @@ public: already_AddRefed GetEncodedData() { - nsString mimeType; - mRecorder->GetMimeType(mimeType); - - return mEncodedBufferCache->ExtractBlob(mimeType); + return mEncodedBufferCache->ExtractBlob(mMimeType); } bool IsEncoderError() @@ -274,10 +274,8 @@ private: // Pull encoded media data from MediaEncoder nsTArray > encodedBuf; - nsString mimeType; - mEncoder->GetEncodedData(&encodedBuf, mimeType); - - mRecorder->SetMimeType(mimeType); + mEncoder->GetEncodedData(&encodedBuf, mMimeType); + mRecorder->SetMimeType(mMimeType); // Append pulled data into cache buffer. for (uint32_t i = 0; i < encodedBuf.Length(); i++) { @@ -325,8 +323,10 @@ private: return; } - // media stream is ready but has been issued stop command - if (mRecorder->mState == RecordingState::Inactive) { + // Media stream is ready but UA issues a stop method follow by start method. + // The Session::stop would clean the mTrackUnionStream. If the AfterTracksAdded + // comes after stop command, this function would crash. + if (!mTrackUnionStream) { DoSessionEndTask(NS_OK); return; } @@ -400,6 +400,8 @@ private: nsRefPtr mEncoder; // A buffer to cache encoded meda data. nsAutoPtr mEncodedBufferCache; + // Current session mimeType + nsString mMimeType; // Timestamp of the last fired dataavailable event. TimeStamp mLastBlobTimeStamp; // The interval of passing encoded data from EncodedBufferCache to onDataAvailable @@ -407,6 +409,8 @@ private: // onDataAvailable, instead, it passive wait the client side pull encoded data // by calling requestData API. const int32_t mTimeSlice; + // Indicate this session's stop has been called. + bool mStopIssued; }; NS_IMPL_ISUPPORTS1(MediaRecorder::Session, nsIObserver) From 70966ac27fa2dd1c11bcf2be948dc6fc291b7465 Mon Sep 17 00:00:00 2001 From: Randy Lin Date: Wed, 29 Jan 2014 23:09:46 +0800 Subject: [PATCH 77/88] Bug 957841 - Test case for MediaRecorder crash [@ mozilla::dom::MediaRecorder::Session::AfterTracksAdded]. r=jsmith --- content/media/test/mochitest.ini | 1 + ...t_mediarecorder_record_startstopstart.html | 76 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 content/media/test/test_mediarecorder_record_startstopstart.html diff --git a/content/media/test/mochitest.ini b/content/media/test/mochitest.ini index 0da92ad1dbbb..70b59f9be82d 100644 --- a/content/media/test/mochitest.ini +++ b/content/media/test/mochitest.ini @@ -256,6 +256,7 @@ support-files = [test_mediarecorder_reload_crash.html] [test_mediarecorder_record_immediate_stop.html] [test_mediarecorder_record_session.html] +[test_mediarecorder_record_startstopstart.html] [test_mediarecorder_unsupported_src.html] [test_playback.html] [test_seekLies.html] diff --git a/content/media/test/test_mediarecorder_record_startstopstart.html b/content/media/test/test_mediarecorder_record_startstopstart.html new file mode 100644 index 000000000000..8c460b21ed59 --- /dev/null +++ b/content/media/test/test_mediarecorder_record_startstopstart.html @@ -0,0 +1,76 @@ + + + + Test MediaRecorder crash on sequence start stop start method + + + + +
+
+
+
+ + + From 18845b2ec6438d89207134b499e488e0edc13f24 Mon Sep 17 00:00:00 2001 From: Alfredo Yang Date: Thu, 30 Jan 2014 11:06:11 -0500 Subject: [PATCH 78/88] Bug 959021 - Rename HAS_AUDIO/HAS_VIDEO and add swap in/out frame data. r=cpearce --- content/media/encoder/ContainerWriter.h | 4 ++-- content/media/encoder/EncodedFrameContainer.h | 19 +++++++++++++++---- content/media/encoder/MediaEncoder.cpp | 10 +++++----- content/media/encoder/MediaEncoder.h | 2 +- content/media/encoder/OmxTrackEncoder.cpp | 7 +++++-- content/media/encoder/OpusTrackEncoder.cpp | 2 +- content/media/encoder/VP8TrackEncoder.cpp | 4 +++- content/media/encoder/VorbisTrackEncoder.cpp | 2 +- .../encoder/fmp4_muxer/ISOMediaWriter.cpp | 4 ++-- content/media/webm/WebMWriter.cpp | 4 ++-- 10 files changed, 37 insertions(+), 21 deletions(-) diff --git a/content/media/encoder/ContainerWriter.h b/content/media/encoder/ContainerWriter.h index c8791ae9d6d1..39c413acea48 100644 --- a/content/media/encoder/ContainerWriter.h +++ b/content/media/encoder/ContainerWriter.h @@ -24,8 +24,8 @@ public: virtual ~ContainerWriter() {} // Mapping to DOMLocalMediaStream::TrackTypeHints enum { - HAS_AUDIO = 1 << 0, - HAS_VIDEO = 1 << 1, + CREATE_AUDIO_TRACK = 1 << 0, + CREATE_VIDEO_TRACK = 1 << 1, }; enum { END_OF_STREAM = 1 << 0 diff --git a/content/media/encoder/EncodedFrameContainer.h b/content/media/encoder/EncodedFrameContainer.h index 4335464ab88d..13d8f4a14dce 100644 --- a/content/media/encoder/EncodedFrameContainer.h +++ b/content/media/encoder/EncodedFrameContainer.h @@ -56,14 +56,25 @@ public: AVC_CSD, // AVC codec specific data UNKNOW // FrameType not set }; + nsresult SwapInFrameData(nsTArray& aData) + { + mFrameData.SwapElements(aData); + return NS_OK; + } + nsresult SwapOutFrameData(nsTArray& aData) + { + if (mFrameType != UNKNOW) { + // Reset this frame type to UNKNOW once the data is swapped out. + mFrameData.SwapElements(aData); + mFrameType = UNKNOW; + return NS_OK; + } + return NS_ERROR_FAILURE; + } const nsTArray& GetFrameData() const { return mFrameData; } - void SetFrameData(nsTArray *aData) - { - mFrameData.SwapElements(*aData); - } uint64_t GetTimeStamp() const { return mTimeStamp; } void SetTimeStamp(uint64_t aTimeStamp) { mTimeStamp = aTimeStamp; } diff --git a/content/media/encoder/MediaEncoder.cpp b/content/media/encoder/MediaEncoder.cpp index b82dbb616770..bd76a4d65846 100644 --- a/content/media/encoder/MediaEncoder.cpp +++ b/content/media/encoder/MediaEncoder.cpp @@ -100,8 +100,8 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes) #ifdef MOZ_WEBM_ENCODER else if (MediaEncoder::IsWebMEncoderEnabled() && (aMIMEType.EqualsLiteral(VIDEO_WEBM) || - (aTrackTypes & ContainerWriter::HAS_VIDEO))) { - if (aTrackTypes & ContainerWriter::HAS_AUDIO) { + (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) { + if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) { audioEncoder = new VorbisTrackEncoder(); NS_ENSURE_TRUE(audioEncoder, nullptr); } @@ -115,8 +115,8 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes) #ifdef MOZ_OMX_ENCODER else if (MediaEncoder::IsOMXEncoderEnabled() && (aMIMEType.EqualsLiteral(VIDEO_MP4) || - (aTrackTypes & ContainerWriter::HAS_VIDEO))) { - if (aTrackTypes & ContainerWriter::HAS_AUDIO) { + (aTrackTypes & ContainerWriter::CREATE_VIDEO_TRACK))) { + if (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK) { audioEncoder = new OmxAudioTrackEncoder(); NS_ENSURE_TRUE(audioEncoder, nullptr); } @@ -130,7 +130,7 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes) #ifdef MOZ_OGG else if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled() && (aMIMEType.EqualsLiteral(AUDIO_OGG) || - (aTrackTypes & ContainerWriter::HAS_AUDIO))) { + (aTrackTypes & ContainerWriter::CREATE_AUDIO_TRACK))) { writer = new OggWriter(); audioEncoder = new OpusTrackEncoder(); NS_ENSURE_TRUE(writer, nullptr); diff --git a/content/media/encoder/MediaEncoder.h b/content/media/encoder/MediaEncoder.h index f4e1d3087905..aa3c2bdc840e 100644 --- a/content/media/encoder/MediaEncoder.h +++ b/content/media/encoder/MediaEncoder.h @@ -93,7 +93,7 @@ public : * Ogg+Opus if it is empty. */ static already_AddRefed CreateEncoder(const nsAString& aMIMEType, - uint8_t aTrackTypes = ContainerWriter::HAS_AUDIO); + uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK); /** * Encodes the raw track data and returns the final container data. Assuming * it is called on a single worker thread. The buffer of container data is diff --git a/content/media/encoder/OmxTrackEncoder.cpp b/content/media/encoder/OmxTrackEncoder.cpp index 7e964eb6212b..3203ed40a5a7 100644 --- a/content/media/encoder/OmxTrackEncoder.cpp +++ b/content/media/encoder/OmxTrackEncoder.cpp @@ -121,6 +121,7 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData) } // Dequeue an encoded frame from the output buffers of OMXCodecWrapper. + nsresult rv; nsTArray buffer; int outFlags = 0; int64_t outTimeStampUs = 0; @@ -134,7 +135,8 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData) videoData->SetFrameType((outFlags & OMXCodecWrapper::BUFFER_SYNC_FRAME) ? EncodedFrame::I_FRAME : EncodedFrame::P_FRAME); } - videoData->SetFrameData(&buffer); + rv = videoData->SwapInFrameData(buffer); + NS_ENSURE_SUCCESS(rv, rv); videoData->SetTimeStamp(outTimeStampUs); aData.AppendEncodedFrame(videoData); } @@ -213,7 +215,8 @@ OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer) audiodata->SetFrameType(isCSD ? EncodedFrame::AAC_CSD : EncodedFrame::AUDIO_FRAME); audiodata->SetTimeStamp(outTimeUs); - audiodata->SetFrameData(&frameData); + rv = audiodata->SwapInFrameData(frameData); + NS_ENSURE_SUCCESS(rv, rv); aContainer.AppendEncodedFrame(audiodata); } diff --git a/content/media/encoder/OpusTrackEncoder.cpp b/content/media/encoder/OpusTrackEncoder.cpp index e1ce627feac5..66926265cbf6 100644 --- a/content/media/encoder/OpusTrackEncoder.cpp +++ b/content/media/encoder/OpusTrackEncoder.cpp @@ -374,7 +374,7 @@ OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData) } } - audiodata->SetFrameData(&frameData); + audiodata->SwapInFrameData(frameData); aData.AppendEncodedFrame(audiodata); return result >= 0 ? NS_OK : NS_ERROR_FAILURE; } diff --git a/content/media/encoder/VP8TrackEncoder.cpp b/content/media/encoder/VP8TrackEncoder.cpp index d4408fe9b6b0..7644481a79fa 100644 --- a/content/media/encoder/VP8TrackEncoder.cpp +++ b/content/media/encoder/VP8TrackEncoder.cpp @@ -164,6 +164,7 @@ VP8TrackEncoder::GetEncodedPartitions(EncodedFrameContainer& aData) vpx_codec_iter_t iter = nullptr; EncodedFrame::FrameType frameType = EncodedFrame::P_FRAME; nsTArray frameData; + nsresult rv; const vpx_codec_cx_pkt_t *pkt = nullptr; while ((pkt = vpx_codec_get_cx_data(mVPXContext, &iter)) != nullptr) { switch (pkt->kind) { @@ -202,7 +203,8 @@ VP8TrackEncoder::GetEncodedPartitions(EncodedFrameContainer& aData) videoData->SetDuration( (uint64_t)FramesToUsecs(pkt->data.frame.duration, mTrackRate).value()); } - videoData->SetFrameData(&frameData); + rv = videoData->SwapInFrameData(frameData); + NS_ENSURE_SUCCESS(rv, rv); VP8LOG("GetEncodedPartitions TimeStamp %lld Duration %lld\n", videoData->GetTimeStamp(), videoData->GetDuration()); VP8LOG("frameType %d\n", videoData->GetFrameType()); diff --git a/content/media/encoder/VorbisTrackEncoder.cpp b/content/media/encoder/VorbisTrackEncoder.cpp index e8ee529563fa..9c7d047e7016 100644 --- a/content/media/encoder/VorbisTrackEncoder.cpp +++ b/content/media/encoder/VorbisTrackEncoder.cpp @@ -147,7 +147,7 @@ VorbisTrackEncoder::GetEncodedFrames(EncodedFrameContainer& aData) audiodata->SetFrameType(EncodedFrame::AUDIO_FRAME); nsTArray frameData; frameData.AppendElements(oggPacket.packet, oggPacket.bytes); - audiodata->SetFrameData(&frameData); + audiodata->SwapInFrameData(frameData); aData.AppendEncodedFrame(audiodata); } } diff --git a/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp b/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp index 05baad14a754..3a46233de2aa 100644 --- a/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp +++ b/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp @@ -28,10 +28,10 @@ ISOMediaWriter::ISOMediaWriter(uint32_t aType) , mBlobReady(false) , mType(0) { - if (aType & HAS_AUDIO) { + if (aType & CREATE_AUDIO_TRACK) { mType |= Audio_Track; } - if (aType & HAS_VIDEO) { + if (aType & CREATE_VIDEO_TRACK) { mType |= Video_Track; } mControl = new ISOControl(); diff --git a/content/media/webm/WebMWriter.cpp b/content/media/webm/WebMWriter.cpp index 872b2e068286..8455edc44074 100644 --- a/content/media/webm/WebMWriter.cpp +++ b/content/media/webm/WebMWriter.cpp @@ -44,7 +44,7 @@ WebMWriter::SetMetadata(TrackMetadataBase* aMetadata) MOZ_ASSERT(meta, "Cannot find vp8 encoder metadata"); mEbmlComposer->SetVideoConfig(meta->mWidth, meta->mHeight, meta->mEncodedFrameRate); - mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::HAS_VIDEO; + mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::CREATE_VIDEO_TRACK; } if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VORBIS) { @@ -52,7 +52,7 @@ WebMWriter::SetMetadata(TrackMetadataBase* aMetadata) MOZ_ASSERT(meta, "Cannot find vorbis encoder metadata"); mEbmlComposer->SetAudioConfig(meta->mSamplingFrequency, meta->mChannels, meta->mBitDepth); mEbmlComposer->SetAudioCodecPrivateData(meta->mData); - mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::HAS_AUDIO; + mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::CREATE_AUDIO_TRACK; } if (!mMetadataRequiredFlag) { From a3abf4db62ce25cd968b2981d29ab0255b5ac2e5 Mon Sep 17 00:00:00 2001 From: Ethan Tseng Date: Thu, 30 Jan 2014 08:58:24 +0800 Subject: [PATCH 79/88] Bug 962309 - Video RTSP support should be disabled in 1.3. r=sworkman --- b2g/app/b2g.js | 1 + content/media/RtspMediaResource.cpp | 36 +++++++++++++++++++++++++++++ content/media/RtspMediaResource.h | 2 ++ 3 files changed, 39 insertions(+) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index b402efa56c0c..92b64ed76fcc 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -578,6 +578,7 @@ pref("dom.sysmsg.enabled", true); pref("media.plugins.enabled", false); pref("media.omx.enabled", true); pref("media.rtsp.enabled", true); +pref("media.rtsp.video.enabled", false); // Disable printing (particularly, window.print()) pref("dom.disable_window_print", true); diff --git a/content/media/RtspMediaResource.cpp b/content/media/RtspMediaResource.cpp index 4f5400f2eff3..dd0f063e378d 100644 --- a/content/media/RtspMediaResource.cpp +++ b/content/media/RtspMediaResource.cpp @@ -440,6 +440,32 @@ RtspMediaResource::OnMediaDataAvailable(uint8_t aTrackIdx, return NS_OK; } +// Bug 962309 - Video RTSP support should be disabled in 1.3 +bool +RtspMediaResource::IsVideoEnabled() +{ + return Preferences::GetBool("media.rtsp.video.enabled", false); +} + +bool +RtspMediaResource::IsVideo(uint8_t tracks, nsIStreamingProtocolMetaData *meta) +{ + bool isVideo = false; + for (int i = 0; i < tracks; ++i) { + nsCOMPtr trackMeta; + mMediaStreamController->GetTrackMetaData(i, getter_AddRefs(trackMeta)); + MOZ_ASSERT(trackMeta); + uint32_t w = 0, h = 0; + trackMeta->GetWidth(&w); + trackMeta->GetHeight(&h); + if (w > 0 || h > 0) { + isVideo = true; + break; + } + } + return isVideo; +} + nsresult RtspMediaResource::OnConnected(uint8_t aTrackIdx, nsIStreamingProtocolMetaData *meta) @@ -453,6 +479,16 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx, uint8_t tracks; mMediaStreamController->GetTotalTracks(&tracks); + + // If the preference of RTSP video feature is not enabled and the streaming is + // video, we give up moving forward. + if (!IsVideoEnabled() && IsVideo(tracks, meta)) { + // Give up, report error to media element. + nsCOMPtr event = + NS_NewRunnableMethod(mDecoder, &MediaDecoder::DecodeError); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + return NS_ERROR_FAILURE; + } uint64_t duration = 0; for (int i = 0; i < tracks; ++i) { nsCString rtspTrackId("RtspTrack"); diff --git a/content/media/RtspMediaResource.h b/content/media/RtspMediaResource.h index b7b0d091e432..9c13cdf56361 100644 --- a/content/media/RtspMediaResource.h +++ b/content/media/RtspMediaResource.h @@ -216,6 +216,8 @@ protected: nsRefPtr mListener; private: + bool IsVideoEnabled(); + bool IsVideo(uint8_t tracks, nsIStreamingProtocolMetaData *meta); // These two members are created at |RtspMediaResource::OnConnected|. nsCOMPtr mMediaStreamController; nsTArray> mTrackBuffer; From 27f450b1d8b3306975d7beb611f128a820a3bcad Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 08:45:13 -0800 Subject: [PATCH 80/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/888d0e718e08 Author: Jan Jongboom Desc: Merge pull request #15835 from comoyo/build-keyboard Bug 964216 - Use build_stage to build keyboard app. r=janjongboom ======== https://hg.mozilla.org/integration/gaia-central/rev/b77ac420c125 Author: Timothy Guan-tin Chien Desc: Bug 964216 - Use build_stage to build keyboard app --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index b2997e67641f..84f42f7db344 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "ba7efaf080ebf86f5ad728cd8b02a81248b306b0", + "revision": "888d0e718e089d93b8822d51add07e63f0921fc5", "repo_path": "/integration/gaia-central" } From 889d76ad2b27f011e5c6160979a9dc25048b1242 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 08:51:01 -0800 Subject: [PATCH 81/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 94581a472cb8..7ffce873005a 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@
- + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 63d40576989f..71c812aa6d44 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 94581a472cb8..7ffce873005a 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 6df573d87a9f..1c7370ccdebb 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 90d9021b11ce..5a8d16b1a681 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index 67406154e1e1..5f467e763a48 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index 17eef32ed912..08df40ee53d5 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index 7f0358dcc0b3..a2199770f79d 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 7d444e1948d2..eca04b9ef4d8 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From 72f02a1423b5200c87f4a942379916fedf236c4c Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 30 Jan 2014 12:53:33 -0500 Subject: [PATCH 82/88] Backed out changeset 93d6dfcc20e7 (bug 958666) for B2G reftest failures. --- b2g/app/b2g.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 92b64ed76fcc..a05c9cc40235 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -887,7 +887,3 @@ pref("apz.asyncscroll.throttle", 40); // Using a software canvas can save memory when JS calls getImageData() // on the canvas frequently. See bug 884226. pref("gfx.canvas.willReadFrequently.enable", true); - -// Disable autofocus until we can have it not bring up the keyboard. -// https://bugzilla.mozilla.org/show_bug.cgi?id=965763 -pref("browser.autofocus", false); From 1c9edb399f70572e6605080ffae1bee0e0ea3bea Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 09:57:38 -0800 Subject: [PATCH 83/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/1a92a507a2b0 Author: Julien Wajsberg Desc: Merge pull request #15839 from jaoo/964216-followup Bug 964216 - follow-up: fix getEnv issue r=julien ======== https://hg.mozilla.org/integration/gaia-central/rev/025501f1bc5f Author: Jose Antonio Olivera Ortega Desc: Bug 964216 - follow-up: fix getEnv issue --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 84f42f7db344..8e03608884f2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "888d0e718e089d93b8822d51add07e63f0921fc5", + "revision": "1a92a507a2b032117ef181b83f66ecf1b585ced9", "repo_path": "/integration/gaia-central" } From daeb2950067014d6a79fb83248b9f9afc7667f30 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 09:57:47 -0800 Subject: [PATCH 84/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 7ffce873005a..b08cca32a98d 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 71c812aa6d44..9963cbaf6f0a 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 7ffce873005a..b08cca32a98d 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 1c7370ccdebb..44a7c12f41c6 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 5a8d16b1a681..93de645753e4 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index 5f467e763a48..961d7e2d14e4 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index 08df40ee53d5..11f34cfc443f 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index a2199770f79d..df56fe81f0c6 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index eca04b9ef4d8..42c33199a0e2 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From ba204f3fcb74713237cb8bce90a91789ba831223 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 10:15:13 -0800 Subject: [PATCH 85/88] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/95c85e15e8ba Author: Jose Antonio Olivera Ortega Desc: Merge pull request #15654 from jaoo/962453 Bug 962453 - [DSDS] Once visit APN setting of one SIM, same APN of another SIM will be changed to "Custom". r=arthurcc ======== https://hg.mozilla.org/integration/gaia-central/rev/32dae85bf414 Author: Jose Antonio Olivera Ortega Desc: Bug 962453 - [DSDS] Once visit APN setting of one SIM, same APN of another SIM will be changed to Custom --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 8e03608884f2..d04a502af8c8 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "1a92a507a2b032117ef181b83f66ecf1b585ced9", + "revision": "95c85e15e8bafe6047c6c01609481c3cd89b6f47", "repo_path": "/integration/gaia-central" } From 6a1e535a4eeb8dc07021e10f5a50bd18a6764809 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 10:21:08 -0800 Subject: [PATCH 86/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b08cca32a98d..bf8b57c2be17 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 9963cbaf6f0a..353c614bccb8 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b08cca32a98d..bf8b57c2be17 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 44a7c12f41c6..aac458d48190 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 93de645753e4..7e4610bf88a6 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index 961d7e2d14e4..84728757ed20 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index 11f34cfc443f..a693880ad9fd 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index df56fe81f0c6..dc20f5f236d9 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 42c33199a0e2..5709f99e328c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - + From 8056ade289c627febd0b5a52de39f9c2b1853a7b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 11:30:11 -0800 Subject: [PATCH 87/88] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/7240a5ab28ef Author: James Burke Desc: Merge pull request #15821 from jrburke/bug905940-email-text-font Bug 905940 - [Buri][Email] E-mail app compose UI uses a non-monospace font r=asuth ======== https://hg.mozilla.org/integration/gaia-central/rev/afe8d1498d6a Author: jrburke Desc: Bug 905940 - [Buri][Email] E-mail app compose UI uses a non-monospace font ======== https://hg.mozilla.org/integration/gaia-central/rev/75c179f3b6ce Author: James Burke Desc: Merge pull request #15824 from jrburke/bug964530-email-unselectable-folder Bug 964530 - [B2G][Email] non-folders are selectable r=asuth ======== https://hg.mozilla.org/integration/gaia-central/rev/7097d02a44b6 Author: jrburke Desc: Bug 964530 - [B2G][Email] non-folders are selectable --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d04a502af8c8..8b5914827b50 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "95c85e15e8bafe6047c6c01609481c3cd89b6f47", + "revision": "7240a5ab28eff83c26891c7a9141613149f226e9", "repo_path": "/integration/gaia-central" } From 877bf15a219018aea9636fb6facf229ce6dda726 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 30 Jan 2014 11:36:11 -0800 Subject: [PATCH 88/88] Bumping manifests a=b2g-bump --- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/inari/sources.xml | 2 +- b2g/config/leo/sources.xml | 2 +- b2g/config/mako/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index bf8b57c2be17..521fc85ebf1a 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 353c614bccb8..e4fb97619d23 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index bf8b57c2be17..521fc85ebf1a 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index aac458d48190..752f1d6009ae 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 7e4610bf88a6..c0a3f2862573 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -10,7 +10,7 @@ - + diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml index 84728757ed20..1194a1e0c3fc 100644 --- a/b2g/config/inari/sources.xml +++ b/b2g/config/inari/sources.xml @@ -12,7 +12,7 @@ - + diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml index a693880ad9fd..120b6124f2d9 100644 --- a/b2g/config/leo/sources.xml +++ b/b2g/config/leo/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml index dc20f5f236d9..dbcc45de8bbd 100644 --- a/b2g/config/mako/sources.xml +++ b/b2g/config/mako/sources.xml @@ -11,7 +11,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 5709f99e328c..9201bf524aaa 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -11,7 +11,7 @@ - +