From b3a99e471678056977def7c57f230202f83aaf2a Mon Sep 17 00:00:00 2001 From: Wander Lairson Costa Date: Tue, 10 Feb 2015 17:36:18 -0200 Subject: [PATCH 01/33] Bug 1130327: Update phone-builder to use builder image 0.2.6. --- testing/docker/phone-builder/Dockerfile | 2 +- testing/docker/phone-builder/VERSION | 2 +- testing/docker/phone-builder/bin/build-phone.sh | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/testing/docker/phone-builder/Dockerfile b/testing/docker/phone-builder/Dockerfile index 68286a730706..e2a96d1f29b3 100644 --- a/testing/docker/phone-builder/Dockerfile +++ b/testing/docker/phone-builder/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/mozilla/builder:0.0.29 +FROM quay.io/mozilla/builder:0.2.6 MAINTAINER Wander Lairson Costa # Add utilities and configuration diff --git a/testing/docker/phone-builder/VERSION b/testing/docker/phone-builder/VERSION index 5a5831ab6bf6..d169b2f2d0a4 100644 --- a/testing/docker/phone-builder/VERSION +++ b/testing/docker/phone-builder/VERSION @@ -1 +1 @@ -0.0.7 +0.0.8 diff --git a/testing/docker/phone-builder/bin/build-phone.sh b/testing/docker/phone-builder/bin/build-phone.sh index 93628931e9e4..abe534bda281 100755 --- a/testing/docker/phone-builder/bin/build-phone.sh +++ b/testing/docker/phone-builder/bin/build-phone.sh @@ -29,6 +29,8 @@ if [ ! -d $OBJDIR ]; then mkdir -p $OBJDIR fi +# Figure out where the remote manifest is so we can use caches for it. +MANIFEST=$(repository-url.py $GECKO_HEAD_REPOSITORY $GECKO_HEAD_REV b2g/config/$TARGET/sources.xml) tc-vcs repo-checkout $OBJDIR/B2G https://git.mozilla.org/b2g/B2G.git $MANIFEST debug_flag="" From 6193a8d9da81a3d9984935e763f6d708f7506da8 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Tue, 10 Feb 2015 16:28:07 -0500 Subject: [PATCH 02/33] Bug 1125422 - Correctly determine whether a touch event was prevent-defaulted in the chrome process. r=kats --- widget/nsBaseWidget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index da110c67042f..4b16a79343ac 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -950,9 +950,12 @@ nsBaseWidget::DispatchEventForAPZ(WidgetGUIEvent* aEvent, = &APZCTreeManager::SetTargetAPZC; APZThreadUtils::RunOnControllerThread(NewRunnableMethod( mAPZC.get(), setTargetApzcFunc, aInputBlockId, aGuid)); + bool defaultPrevented = aEvent->AsTouchEvent() + ? (nsIPresShell::gPreventMouseEvents || aEvent->mFlags.mMultipleActionsPrevented) + : aEvent->mFlags.mDefaultPrevented; APZThreadUtils::RunOnControllerThread(NewRunnableMethod( mAPZC.get(), &APZCTreeManager::ContentReceivedInputBlock, aInputBlockId, - aEvent->mFlags.mDefaultPrevented)); + defaultPrevented)); } return status; From f5d90daf870835de345b273eaf9277b5b234934b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 10 Feb 2015 16:28:07 -0500 Subject: [PATCH 03/33] Bug 1125422 - Add a flag on ContainerLayer to indicate when the entire subtree of layers needs to be in the dispatch-to-content region. r=roc --- gfx/layers/Layers.cpp | 7 ++++++- gfx/layers/Layers.h | 19 +++++++++++++++++++ gfx/layers/ipc/LayerTransactionParent.cpp | 1 + gfx/layers/ipc/LayersMessages.ipdlh | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index a122a561e6ea..7564a4a3b28e 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -924,7 +924,8 @@ ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData) mUseIntermediateSurface(false), mSupportsComponentAlphaChildren(false), mMayHaveReadbackChild(false), - mChildrenChanged(false) + mChildrenChanged(false), + mForceDispatchToContentRegion(false) { mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT } @@ -1081,6 +1082,7 @@ ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs) aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale, mInheritedXScale, mInheritedYScale, mPresShellResolution, mScaleToResolution, + mForceDispatchToContentRegion, reinterpret_cast(mHMDInfo.get())); } @@ -1748,6 +1750,9 @@ ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix) if (mScaleToResolution) { aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get(); } + if (mForceDispatchToContentRegion) { + aStream << " [force-dtc]"; + } if (mHMDInfo) { aStream << nsPrintfCString(" [hmd=%p]", mHMDInfo.get()).get(); } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 00f682e69726..318aa83e751c 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -916,6 +916,10 @@ public: * outside the dispatch-to-content region, we can initiate a gesture without * consulting the content thread. Otherwise we must dispatch the event to * content. + * Note that if a layer or any ancestor layer returns true for + * GetForceDispatchToContentRegion() then we must treat the dispatch-to-content + * region as encompassing the hit region, and therefore must consult the + * content thread before initiating a gesture. */ /** * CONSTRUCTION PHASE ONLY @@ -1967,6 +1971,20 @@ public: mChildrenChanged = aVal; } + void SetForceDispatchToContentRegion(bool aVal) { + if (mForceDispatchToContentRegion == aVal) { + return; + } + + MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ForceDispatchToContentRegion", this)); + mForceDispatchToContentRegion = aVal; + Mutated(); + } + + bool GetForceDispatchToContentRegion() const { + return mForceDispatchToContentRegion; + } + /** * VR */ @@ -2023,6 +2041,7 @@ protected: // This is updated by ComputeDifferences. This will be true if we need to invalidate // the intermediate surface. bool mChildrenChanged; + bool mForceDispatchToContentRegion; nsRefPtr mHMDInfo; }; diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index 8fc424641415..55ca389fde8b 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -386,6 +386,7 @@ LayerTransactionParent::RecvUpdate(InfallibleTArray&& cset, containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale()); containerLayer->SetScaleToResolution(attrs.scaleToResolution(), attrs.presShellResolution()); + containerLayer->SetForceDispatchToContentRegion(attrs.forceDispatchToContentRegion()); if (attrs.hmdInfo()) { if (!IsSameProcess()) { diff --git a/gfx/layers/ipc/LayersMessages.ipdlh b/gfx/layers/ipc/LayersMessages.ipdlh index 1f2eca17c009..8e8e5519ba19 100644 --- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -234,6 +234,7 @@ struct ContainerLayerAttributes { float inheritedYScale; float presShellResolution; bool scaleToResolution; + bool forceDispatchToContentRegion; // This is a bare pointer; LayerTransactionParent::RecvUpdate prevents this // from being used when !IsSameProcess(), but we should make this truly // cross process at some point by passing the HMDConfig From 3832470e385a93d7d14c95c3529d9f6ef007dab5 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 10 Feb 2015 16:28:07 -0500 Subject: [PATCH 04/33] Bug 1125422 - Fold touch and scroll listener flags into a single apz-aware flag for better code reuse. r=roc --- layout/base/nsDisplayList.cpp | 7 ++----- layout/base/nsDisplayList.h | 23 +++++++---------------- layout/base/nsLayoutUtils.cpp | 13 +++++++++++++ layout/base/nsLayoutUtils.h | 3 +++ layout/generic/nsFrame.cpp | 14 ++------------ layout/generic/nsSubDocumentFrame.cpp | 3 +-- 6 files changed, 28 insertions(+), 35 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 29e0a32f15c3..ebc5a64b85eb 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -587,8 +587,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mIsPaintingToWindow(false), mIsCompositingCheap(false), mContainsPluginItem(false), - mAncestorHasTouchEventHandler(false), - mAncestorHasScrollEventHandler(false), + mAncestorHasApzAwareEventHandler(false), mHaveScrollableDisplayPort(false), mWindowDraggingAllowed(false), mIsBuildingForPopup(nsLayoutUtils::IsPopup(aReferenceFrame)) @@ -3151,9 +3150,7 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder, } else { mHitRegion.Or(mHitRegion, borderBox); } - if (aBuilder->GetAncestorHasTouchEventHandler() || - aBuilder->GetAncestorHasScrollEventHandler()) - { + if (aBuilder->GetAncestorHasApzAwareEventHandler()) { mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox); } } diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index db1aa2691d5e..8ce717464118 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -345,15 +345,10 @@ public: return CurrentPresShellState()->mInsidePointerEventsNoneDoc; } - bool GetAncestorHasTouchEventHandler() { return mAncestorHasTouchEventHandler; } - void SetAncestorHasTouchEventHandler(bool aValue) + bool GetAncestorHasApzAwareEventHandler() { return mAncestorHasApzAwareEventHandler; } + void SetAncestorHasApzAwareEventHandler(bool aValue) { - mAncestorHasTouchEventHandler = aValue; - } - bool GetAncestorHasScrollEventHandler() { return mAncestorHasScrollEventHandler; } - void SetAncestorHasScrollEventHandler(bool aValue) - { - mAncestorHasScrollEventHandler = aValue; + mAncestorHasApzAwareEventHandler = aValue; } bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; } @@ -578,8 +573,7 @@ public: mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame), mPrevDirtyRect(aBuilder->mDirtyRect), mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext), - mPrevAncestorHasTouchEventHandler(aBuilder->mAncestorHasTouchEventHandler), - mPrevAncestorHasScrollEventHandler(aBuilder->mAncestorHasScrollEventHandler) + mPrevAncestorHasApzAwareEventHandler(aBuilder->mAncestorHasApzAwareEventHandler) { if (aForChild->IsTransformed()) { aBuilder->mCurrentOffsetToReferenceFrame = nsPoint(); @@ -624,8 +618,7 @@ public: mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset; mBuilder->mDirtyRect = mPrevDirtyRect; mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext; - mBuilder->mAncestorHasTouchEventHandler = mPrevAncestorHasTouchEventHandler; - mBuilder->mAncestorHasScrollEventHandler = mPrevAncestorHasScrollEventHandler; + mBuilder->mAncestorHasApzAwareEventHandler = mPrevAncestorHasApzAwareEventHandler; mBuilder->mCurrentAnimatedGeometryRoot = mPrevAnimatedGeometryRoot; } private: @@ -637,8 +630,7 @@ public: nsPoint mPrevOffset; nsRect mPrevDirtyRect; bool mPrevIsAtRootOfPseudoStackingContext; - bool mPrevAncestorHasTouchEventHandler; - bool mPrevAncestorHasScrollEventHandler; + bool mPrevAncestorHasApzAwareEventHandler; }; /** @@ -920,8 +912,7 @@ private: bool mIsPaintingToWindow; bool mIsCompositingCheap; bool mContainsPluginItem; - bool mAncestorHasTouchEventHandler; - bool mAncestorHasScrollEventHandler; + bool mAncestorHasApzAwareEventHandler; // True when the first async-scrollable scroll frame for which we build a // display list has a display port. An async-scrollable scroll frame is one // which WantsAsyncScroll(). diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 8afe89e91a30..03f35bce3497 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -7838,3 +7838,16 @@ nsLayoutUtils::SetBSizeFromFontMetrics(const nsIFrame* aFrame, aFramePadding.BStart(aFrameWM)); aMetrics.BSize(aLineWM) += aFramePadding.BStartEnd(aFrameWM); } + +/* static */ bool +nsLayoutUtils::HasApzAwareListeners(EventListenerManager* aElm) +{ + if (!aElm) { + return false; + } + return aElm->HasListenersFor(nsGkAtoms::ontouchstart) || + aElm->HasListenersFor(nsGkAtoms::ontouchmove) || + aElm->HasListenersFor(nsGkAtoms::onwheel) || + aElm->HasListenersFor(nsGkAtoms::onDOMMouseScroll) || + aElm->HasListenersFor(nsHtml5Atoms::onmousewheel); +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 4b52970eadcd..7aeaef6aaf09 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -63,6 +63,7 @@ struct nsStyleImageOrientation; struct nsOverflowAreas; namespace mozilla { +class EventListenerManager; class SVGImageContext; struct IntrinsicSize; struct ContainerLayerParameters; @@ -2551,6 +2552,8 @@ public: mozilla::WritingMode aLineWM, mozilla::WritingMode aFrameWM); + static bool HasApzAwareListeners(mozilla::EventListenerManager* aElm); + private: static uint32_t sFontSizeInflationEmPerLine; static uint32_t sFontSizeInflationMinTwips; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index eced5d560eeb..c624acd45f8b 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1909,18 +1909,8 @@ CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) return; } EventListenerManager* elm = nsContentUtils::GetExistingListenerManagerForNode(content); - if (!elm) { - return; - } - if (elm->HasListenersFor(nsGkAtoms::ontouchstart) || - elm->HasListenersFor(nsGkAtoms::ontouchmove)) { - aBuilder->SetAncestorHasTouchEventHandler(true); - } - if (elm->HasListenersFor(nsGkAtoms::onwheel) || - elm->HasListenersFor(nsGkAtoms::onDOMMouseScroll) || - elm->HasListenersFor(nsHtml5Atoms::onmousewheel)) - { - aBuilder->SetAncestorHasScrollEventHandler(true); + if (nsLayoutUtils::HasApzAwareListeners(elm)) { + aBuilder->SetAncestorHasApzAwareEventHandler(true); } } diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 35e57ead9b76..4a74295513a1 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -487,8 +487,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, ? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent()) : aBuilder->GetCurrentScrollParentId()); - aBuilder->SetAncestorHasTouchEventHandler(false); - aBuilder->SetAncestorHasScrollEventHandler(false); + aBuilder->SetAncestorHasApzAwareEventHandler(false); subdocRootFrame-> BuildDisplayListForStackingContext(aBuilder, dirty, &childItems); } From 796beb9721770bc7562b865a96b6e171b68ad50f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 10 Feb 2015 16:28:07 -0500 Subject: [PATCH 05/33] Bug 1125422 - Change EventDispatcher::Dispatch to take an nsTArray instead of a nsCOMArray. r=smaug --- dom/events/EventDispatcher.cpp | 6 +++--- dom/events/EventDispatcher.h | 2 +- dom/events/EventListenerService.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index 4c64e8a48c7e..b669428f48d7 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -397,7 +397,7 @@ EventDispatcher::Dispatch(nsISupports* aTarget, nsIDOMEvent* aDOMEvent, nsEventStatus* aEventStatus, EventDispatchingCallback* aCallback, - nsCOMArray* aTargets) + nsTArray* aTargets) { PROFILER_LABEL("EventDispatcher", "Dispatch", js::ProfileEntry::Category::EVENTS); @@ -476,7 +476,7 @@ EventDispatcher::Dispatch(nsISupports* aTarget, } #ifdef DEBUG - if (!nsContentUtils::IsSafeToRunScript()) { + if (aEvent->message != NS_EVENT_NULL && !nsContentUtils::IsSafeToRunScript()) { nsresult rv = NS_ERROR_FAILURE; if (target->GetContextForEventHandlers(&rv) || NS_FAILED(rv)) { @@ -625,7 +625,7 @@ EventDispatcher::Dispatch(nsISupports* aTarget, aTargets->Clear(); aTargets->SetCapacity(chain.Length()); for (uint32_t i = 0; i < chain.Length(); ++i) { - aTargets->AppendObject(chain[i].CurrentTarget()->GetTargetForDOMEvent()); + aTargets->AppendElement(chain[i].CurrentTarget()->GetTargetForDOMEvent()); } } else { // Event target chain is created. Handle the chain. diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h index 12f2468efaf7..6795fe6f75c3 100644 --- a/dom/events/EventDispatcher.h +++ b/dom/events/EventDispatcher.h @@ -255,7 +255,7 @@ public: nsIDOMEvent* aDOMEvent = nullptr, nsEventStatus* aEventStatus = nullptr, EventDispatchingCallback* aCallback = nullptr, - nsCOMArray* aTargets = nullptr); + nsTArray* aTargets = nullptr); /** * Dispatches an event. diff --git a/dom/events/EventListenerService.cpp b/dom/events/EventListenerService.cpp index a0cc99ca5c5d..429b9ca3c0ce 100644 --- a/dom/events/EventListenerService.cpp +++ b/dom/events/EventListenerService.cpp @@ -171,11 +171,11 @@ EventListenerService::GetEventTargetChainFor(nsIDOMEventTarget* aEventTarget, *aOutArray = nullptr; NS_ENSURE_ARG(aEventTarget); WidgetEvent event(true, NS_EVENT_NULL); - nsCOMArray targets; + nsTArray targets; nsresult rv = EventDispatcher::Dispatch(aEventTarget, nullptr, &event, nullptr, nullptr, nullptr, &targets); NS_ENSURE_SUCCESS(rv, rv); - int32_t count = targets.Count(); + int32_t count = targets.Length(); if (count == 0) { return NS_OK; } From 4ea12e1645cb9f54b02f9a183e357074bca5b7d2 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 10 Feb 2015 16:28:07 -0500 Subject: [PATCH 06/33] Bug 1125422 - Populate the ContainerLayer flag to force events to be dispatched to content. r=roc --- layout/base/nsDisplayList.cpp | 10 +++++++++- layout/base/nsDisplayList.h | 1 + layout/base/nsLayoutUtils.cpp | 19 +++++++++++++++++++ layout/base/nsLayoutUtils.h | 1 + layout/ipc/RenderFrameParent.cpp | 14 ++++++++++++++ layout/ipc/RenderFrameParent.h | 6 ++---- 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index ebc5a64b85eb..da3954ccffc8 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1629,6 +1629,9 @@ already_AddRefed nsDisplayList::PaintRoot(nsDisplayListBuilder* aB 1.0f/containerParameters.mYScale); root->SetScaleToResolution(presShell->ScaleToResolution(), containerParameters.mXScale); + root->SetForceDispatchToContentRegion( + aBuilder->IsBuildingLayerEventRegions() && + nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell)); if (gfxPrefs::LayoutUseContainersForRootFrames()) { bool isRoot = presContext->IsRootContentDocument(); @@ -4061,6 +4064,9 @@ nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, , mScrollParentId(aBuilder->GetCurrentScrollParentId()) { MOZ_COUNT_CTOR(nsDisplaySubDocument); + mForceDispatchToContentRegion = + aBuilder->IsBuildingLayerEventRegions() && + nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresContext()->PresShell()); } #ifdef NS_BUILD_REFCNT_LOGGING @@ -4082,7 +4088,9 @@ nsDisplaySubDocument::BuildLayer(nsDisplayListBuilder* aBuilder, params.mInLowPrecisionDisplayPort = true; } - return nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, params); + nsRefPtr layer = nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, params); + layer->AsContainerLayer()->SetForceDispatchToContentRegion(mForceDispatchToContentRegion); + return layer.forget(); } UniquePtr diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 8ce717464118..91fa03800c74 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -3036,6 +3036,7 @@ public: protected: ViewID mScrollParentId; + bool mForceDispatchToContentRegion; }; /** diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 03f35bce3497..e95a4bd0f11c 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -20,6 +20,7 @@ #include "nsIDOMHTMLElement.h" #include "nsFrameList.h" #include "nsGkAtoms.h" +#include "nsHtml5Atoms.h" #include "nsIAtom.h" #include "nsCSSPseudoElements.h" #include "nsCSSAnonBoxes.h" @@ -7851,3 +7852,21 @@ nsLayoutUtils::HasApzAwareListeners(EventListenerManager* aElm) aElm->HasListenersFor(nsGkAtoms::onDOMMouseScroll) || aElm->HasListenersFor(nsHtml5Atoms::onmousewheel); } + +/* static */ bool +nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(nsIPresShell* aShell) +{ + if (nsIDocument* doc = aShell->GetDocument()) { + WidgetEvent event(true, NS_EVENT_NULL); + nsTArray targets; + nsresult rv = EventDispatcher::Dispatch(doc, nullptr, &event, nullptr, + nullptr, nullptr, &targets); + NS_ENSURE_SUCCESS(rv, false); + for (size_t i = 0; i < targets.Length(); i++) { + if (HasApzAwareListeners(targets[i]->GetExistingListenerManager())) { + return true; + } + } + } + return false; +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 7aeaef6aaf09..ff9cf4a9f89c 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2553,6 +2553,7 @@ public: mozilla::WritingMode aFrameWM); static bool HasApzAwareListeners(mozilla::EventListenerManager* aElm); + static bool HasDocumentLevelListenersForApzAwareEvents(nsIPresShell* aShell); private: static uint32_t sFontSizeInflationEmPerLine; diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 097adf90c3b2..5c9bfc784ea4 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -615,6 +615,17 @@ RenderFrameParent::TakeFocusForClick() } // namespace layout } // namespace mozilla +nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + RenderFrameParent* aRemoteFrame) + : nsDisplayItem(aBuilder, aFrame) + , mRemoteFrame(aRemoteFrame) +{ + mForceDispatchToContentRegion = + aBuilder->IsBuildingLayerEventRegions() && + nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresContext()->PresShell()); +} + already_AddRefed nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -624,6 +635,9 @@ nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder, nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel); visibleRect += aContainerParameters.mOffset; nsRefPtr layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect, this, aContainerParameters); + if (layer && layer->AsContainerLayer()) { + layer->AsContainerLayer()->SetForceDispatchToContentRegion(mForceDispatchToContentRegion); + } return layer.forget(); } diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index 69b1b04f5758..dbead6de77cb 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -166,10 +166,7 @@ class nsDisplayRemote : public nsDisplayItem public: nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - RenderFrameParent* aRemoteFrame) - : nsDisplayItem(aBuilder, aFrame) - , mRemoteFrame(aRemoteFrame) - {} + RenderFrameParent* aRemoteFrame); virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -187,6 +184,7 @@ public: private: RenderFrameParent* mRemoteFrame; + bool mForceDispatchToContentRegion; }; From e06065878469934af6999c39ce380f7eedc09235 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 10 Feb 2015 16:28:07 -0500 Subject: [PATCH 07/33] Bug 1125422 - Read the force-dispatch-to-content flag from the layer tree and use it in the APZ code. r=botond --- gfx/layers/LayerMetricsWrapper.h | 9 +++++++++ gfx/layers/apz/src/APZCTreeManager.cpp | 23 ++++++++++++++++++++--- gfx/layers/apz/src/HitTestingTreeNode.cpp | 18 +++++++++++++++--- gfx/layers/apz/src/HitTestingTreeNode.h | 10 +++++++++- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h index b390b5eda95f..68cd5651aff1 100644 --- a/gfx/layers/LayerMetricsWrapper.h +++ b/gfx/layers/LayerMetricsWrapper.h @@ -338,6 +338,15 @@ public: return mLayer->GetClipRect(); } + bool GetForceDispatchToContentRegion() const { + MOZ_ASSERT(IsValid()); + + if (mLayer->AsContainerLayer()) { + return mLayer->AsContainerLayer()->GetForceDispatchToContentRegion(); + } + return false; + } + // Expose an opaque pointer to the layer. Mostly used for printf // purposes. This is not intended to be a general-purpose accessor // for the underlying layer. diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index a488ecaac6a4..6e4abbaf167d 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -320,6 +320,20 @@ APZCTreeManager::RecycleOrCreateNode(TreeBuildingState& aState, return node.forget(); } +static bool +ShouldForceDispatchToContent(HitTestingTreeNode* aParent, + const LayerMetricsWrapper& aLayer) +{ + // Make it so that if the flag is set on the layer tree, it automatically + // propagates to all the nodes in the corresponding subtree rooted at that + // layer in the hit-test tree. This saves having to walk up the tree every + // we want to see if a hit-test node is affected by this flag. + if (aParent && aParent->GetForceDispatchToContent()) { + return true; + } + return aLayer.GetForceDispatchToContentRegion(); +} + HitTestingTreeNode* APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, const FrameMetrics& aMetrics, @@ -344,7 +358,8 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, node = RecycleOrCreateNode(aState, nullptr); AttachNodeToTree(node, aParent, aNextSibling); node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), - aLayer.GetClipRect() ? Some(nsIntRegion(*aLayer.GetClipRect())) : Nothing()); + aLayer.GetClipRect() ? Some(nsIntRegion(*aLayer.GetClipRect())) : Nothing(), + ShouldForceDispatchToContent(aParent, aLayer)); return node; } @@ -440,7 +455,8 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, MOZ_ASSERT(node->IsPrimaryHolder() && node->GetApzc() && node->GetApzc()->Matches(guid)); nsIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer); - node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion)); + node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion), + ShouldForceDispatchToContent(aParent, aLayer)); apzc->SetAncestorTransform(aAncestorTransform); PrintAPZCInfo(aLayer, apzc); @@ -494,7 +510,8 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, MOZ_ASSERT(aAncestorTransform == apzc->GetAncestorTransform()); nsIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer); - node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion)); + node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion), + ShouldForceDispatchToContent(aParent, aLayer)); } return node; diff --git a/gfx/layers/apz/src/HitTestingTreeNode.cpp b/gfx/layers/apz/src/HitTestingTreeNode.cpp index a20343bfe727..0ec356b40cee 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.cpp +++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp @@ -21,6 +21,7 @@ HitTestingTreeNode::HitTestingTreeNode(AsyncPanZoomController* aApzc, bool aIsPrimaryHolder) : mApzc(aApzc) , mIsPrimaryApzcHolder(aIsPrimaryHolder) + , mForceDispatchToContent(false) { if (mIsPrimaryApzcHolder) { MOZ_ASSERT(mApzc); @@ -155,11 +156,13 @@ HitTestingTreeNode::IsPrimaryHolder() const void HitTestingTreeNode::SetHitTestData(const EventRegions& aRegions, const gfx::Matrix4x4& aTransform, - const Maybe& aClipRegion) + const Maybe& aClipRegion, + bool aForceDispatchToContent) { mEventRegions = aRegions; mTransform = aTransform; mClipRegion = aClipRegion; + mForceDispatchToContent = aForceDispatchToContent; } bool @@ -210,20 +213,29 @@ HitTestingTreeNode::HitTest(const ParentLayerPoint& aPoint) const if (!mEventRegions.mHitRegion.Contains(point.x, point.y)) { return HitTestResult::HitNothing; } - if (mEventRegions.mDispatchToContentHitRegion.Contains(point.x, point.y)) { + if (mForceDispatchToContent || + mEventRegions.mDispatchToContentHitRegion.Contains(point.x, point.y)) + { return HitTestResult::HitDispatchToContentRegion; } return HitTestResult::HitLayer; } +bool +HitTestingTreeNode::GetForceDispatchToContent() const +{ + return mForceDispatchToContent; +} + void HitTestingTreeNode::Dump(const char* aPrefix) const { if (mPrevSibling) { mPrevSibling->Dump(aPrefix); } - printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) r=(%s) t=(%s) c=(%s)\n", + printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) %sr=(%s) t=(%s) c=(%s)\n", aPrefix, this, mApzc.get(), mApzc ? Stringify(mApzc->GetGuid()).c_str() : "", + mForceDispatchToContent ? "fdtc " : "", Stringify(mEventRegions).c_str(), Stringify(mTransform).c_str(), mClipRegion ? Stringify(mClipRegion.ref()).c_str() : "none"); if (mLastChild) { diff --git a/gfx/layers/apz/src/HitTestingTreeNode.h b/gfx/layers/apz/src/HitTestingTreeNode.h index 0fbc4898875c..a517d5ceb107 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.h +++ b/gfx/layers/apz/src/HitTestingTreeNode.h @@ -81,7 +81,8 @@ public: void SetHitTestData(const EventRegions& aRegions, const gfx::Matrix4x4& aTransform, - const Maybe& aClipRegion); + const Maybe& aClipRegion, + bool aForceDispatchToContent); bool IsOutsideClip(const ParentLayerPoint& aPoint) const; /* Convert aPoint into the LayerPixel space for the layer corresponding to * this node. */ @@ -89,6 +90,8 @@ public: /* Assuming aPoint is inside the clip region for this node, check which of the * event region spaces it falls inside. */ HitTestResult HitTest(const ParentLayerPoint& aPoint) const; + /* Returns the mForceDispatchToContent flag. */ + bool GetForceDispatchToContent() const; /* Debug helpers */ void Dump(const char* aPrefix = "") const; @@ -122,6 +125,11 @@ private: * because we may use the composition bounds of the layer if the clip is not * present. This value is in L's ParentLayerPixels. */ Maybe mClipRegion; + + /* If this flag is set, then events to this node and the entire subtree under + * should always be treated as dispatch-to-content. + */ + bool mForceDispatchToContent; }; } From 2b7b0f5811e17c4520266597c08f0067e1ad17eb Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 13:35:29 -0800 Subject: [PATCH 08/33] Bumping gaia.json for 3 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/61753609a6ac Author: Marta Piekarska Desc: Bug 1121232 - [Privacy Panel][Remote Privacy Protection] Closing Privacy Panel in the Task Manager prevents first received RPP feature from functioning r=kgrandon ======== https://hg.mozilla.org/integration/gaia-central/rev/57666f90921b Author: Eitan Isaacson Desc: Merge pull request #27932 from eeejay/bug-1068999 Bug 1068999 - Make video player seek bar accessible. r=djf ======== https://hg.mozilla.org/integration/gaia-central/rev/e9b16b142f76 Author: Eitan Isaacson Desc: Bug 1068999 - Make video player seek bar accessible. --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index e4db5c36a4d9..b0be32725b0f 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "8c7865486a1b11076b849bbf8f7fccbaffbfafe7", + "git_revision": "7efd55ffbbaf3b24fabe53717c354aa03edc8bac", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "c97ae9ec825f591d669e8b7128b81493b88dcf3f", + "revision": "61753609a6acdd8efd1554db5c6db6ea523070f5", "repo_path": "integration/gaia-central" } From 2aefb55c4a79b1b201a8232ef77da24c69d26cef Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 13:36:59 -0800 Subject: [PATCH 09/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 6 +++--- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 33bb212f13a3..d9f1eb0f0f54 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + @@ -134,9 +134,9 @@ - + - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 1fe360ec62a8..51a2e81de6bd 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 55a1a3723cf9..6f0044351bb6 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index a77b83279050..706b3a22db51 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 1fe360ec62a8..51a2e81de6bd 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 3ed81684c9d6..7916e6204298 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 141619945d25..e90d95cdfa39 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 158200e4142d..0813ea4e4219 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index b6546b11ea33..e2eda0d2b0d1 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 65d45dcdec6c6fd16cb243293d86694208bd7792 Mon Sep 17 00:00:00 2001 From: "jlal@mozilla.com" Date: Tue, 10 Feb 2015 10:53:02 -0800 Subject: [PATCH 10/33] Bug 1131450 - Implement chunk specific scheduling for tests r=garndt --HG-- extra : rebase_source : 5c9cc1f0551e09c98bf8dfbed979ee1c737b1ed7 --- testing/taskcluster/mach_commands.py | 4 ++ .../taskcluster_graph/commit_parser.py | 57 +++++++++++++++++-- .../taskcluster/tests/test_commit_parser.py | 56 ++++++++++++++++++ 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/testing/taskcluster/mach_commands.py b/testing/taskcluster/mach_commands.py index a02da77ef2f4..af244851a189 100644 --- a/testing/taskcluster/mach_commands.py +++ b/testing/taskcluster/mach_commands.py @@ -315,6 +315,10 @@ class Graph(object): test_parameters['total_chunks'] = test['chunks'] for chunk in range(1, test_parameters['total_chunks'] + 1): + if 'only_chunks' in test and \ + chunk not in test['only_chunks']: + continue; + test_parameters['chunk'] = chunk test_task = templates.load(test['task'], test_parameters) test_task['taskId'] = slugid() diff --git a/testing/taskcluster/taskcluster_graph/commit_parser.py b/testing/taskcluster/taskcluster_graph/commit_parser.py index 8f4460801676..12b4adf7322d 100644 --- a/testing/taskcluster/taskcluster_graph/commit_parser.py +++ b/testing/taskcluster/taskcluster_graph/commit_parser.py @@ -3,13 +3,15 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. -import shlex import argparse -import functools import copy +import functools +import re +import shlex from try_test_parser import parse_test_opts -TRY_DELIMITER='try:' +TRY_DELIMITER = 'try:' +TEST_CHUNK_SUFFIX = re.compile('(.*)-([0-9]+)$') # The build type aliases are very cryptic and only used in try flags these are # mappings from the single char alias to a longer more recognizable form. @@ -59,9 +61,41 @@ def normalize_test_list(all_tests, job_list): if 'platforms' in all_entry: entry['platforms'] = list(all_entry['platforms']) results.append(entry) - return results + return parse_test_chunks(results) else: - return tests + return parse_test_chunks(tests) + +def parse_test_chunks(tests): + ''' + Test flags may include parameters to narrow down the number of chunks in a + given push. We don't model 1 chunk = 1 job in taskcluster so we must check + each test flag to see if it is actually specifying a chunk. + + :param list tests: Result from normalize_test_list + :returns: List of jobs + ''' + + results = [] + seen_chunks = {} + for test in tests: + matches = TEST_CHUNK_SUFFIX.match(test['test']) + + if not matches: + results.append(test) + continue + + name = matches.group(1) + chunk = int(matches.group(2)) + + if name in seen_chunks: + seen_chunks[name].add(chunk) + else: + seen_chunks[name] = set([chunk]) + test['test'] = name + test['only_chunks'] = seen_chunks[name] + results.append(test) + + return results; def extract_tests_from_platform(test_jobs, build_platform, build_task, tests): ''' @@ -104,7 +138,18 @@ def extract_tests_from_platform(test_jobs, build_platform, build_task, tests): # Add the job to the list and ensure to copy it so we don't accidentally # mutate the state of the test job in the future... - results.append(copy.deepcopy(test_job)) + specific_test_job = copy.deepcopy(test_job) + + # Update the task configuration for all tests in the matrix... + for build_name in specific_test_job: + for test_task_name in specific_test_job[build_name]: + test_task = specific_test_job[build_name][test_task_name] + # Copy over the chunk restrictions if given... + if 'only_chunks' in test_entry: + test_task['only_chunks'] = \ + copy.copy(test_entry['only_chunks']) + + results.append(specific_test_job) return results diff --git a/testing/taskcluster/tests/test_commit_parser.py b/testing/taskcluster/tests/test_commit_parser.py index 7d614f7bc434..2b1a703096b7 100755 --- a/testing/taskcluster/tests/test_commit_parser.py +++ b/testing/taskcluster/tests/test_commit_parser.py @@ -343,6 +343,62 @@ class TestCommitParser(unittest.TestCase): result = parse_commit(commit, jobs) self.assertEqual(expected, result) + def test_specific_chunks(self): + ''' + This test covers specifying specific chunks for a given test suite. + ''' + commit = 'try: -b o -p linux -u mochitest-1,mochitest-2 -t none' + jobs = { + 'flags': { + 'builds': ['linux'], + 'tests': ['mochitest'], + }, + 'builds': { + 'linux': { + 'types': { + 'opt': { + 'task': 'task/linux', + }, + 'debug': { + 'task': 'task/linux-debug' + } + } + }, + }, + 'tests': { + 'mochitest': { + 'allowed_build_tasks': { + 'task/linux': { + 'task': 'task/mochitest', + 'chunks': 5 + }, + } + } + } + } + + expected = [ + { + 'task': 'task/linux', + 'dependents': [ + { + 'allowed_build_tasks': { + 'task/linux': { + 'task': 'task/mochitest', + 'chunks': 5, + 'only_chunks': set([1, 2]) + }, + } + } + ], + 'additional-parameters': {} + } + ] + result = parse_commit(commit, jobs) + self.assertEqual(expected, result) + + + def test_commit_with_builds_and_tests(self): ''' This test covers the broad case of a commit which has both builds and From 90ad8ca3b5141e33f0420d1aed1fb8251b0520bd Mon Sep 17 00:00:00 2001 From: Mike de Boer Date: Tue, 10 Feb 2015 23:35:39 +0100 Subject: [PATCH 11/33] Bug 1121210: notify UITour when the active tab changes and don't show the get started info panel when the rooms tab is not selected. r=MattN --- browser/base/content/browser-loop.js | 52 ++++++++++++++++- browser/components/loop/MozLoopAPI.jsm | 8 ++- browser/components/loop/content/js/panel.js | 13 ++++- browser/components/loop/content/js/panel.jsx | 13 ++++- .../test/mochitest/browser_toolbarbutton.js | 57 +++++++++++++++++-- browser/components/uitour/UITour.jsm | 14 ++--- .../uitour/test/browser_UITour_loop.js | 48 ++++++++++++++++ 7 files changed, 183 insertions(+), 22 deletions(-) diff --git a/browser/base/content/browser-loop.js b/browser/base/content/browser-loop.js index 0f27072bad18..ac6b2ed80627 100644 --- a/browser/base/content/browser-loop.js +++ b/browser/base/content/browser-loop.js @@ -13,16 +13,50 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel (function() { LoopUI = { + /** + * @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton + * instance for this window. + */ get toolbarButton() { delete this.toolbarButton; return this.toolbarButton = CustomizableUI.getWidget("loop-button").forWindow(window); }, + /** + * @var {XULElement} panel Getter for the Loop panel element. + */ get panel() { delete this.panel; return this.panel = document.getElementById("loop-notification-panel"); }, + /** + * @var {XULElement|null} browser Getter for the Loop panel browser element. + * Will be NULL if the panel hasn't loaded yet. + */ + get browser() { + let browser = document.querySelector("#loop-notification-panel > #loop-panel-iframe"); + if (browser) { + delete this.browser; + this.browser = browser; + } + return browser; + }, + + /** + * @var {String|null} selectedTab Getter for the name of the currently selected + * tab inside the Loop panel. Will be NULL if + * the panel hasn't loaded yet. + */ + get selectedTab() { + if (!this.browser) { + return null; + } + + let selectedTab = this.browser.contentDocument.querySelector(".tab-view > .selected"); + return selectedTab && selectedTab.getAttribute("data-tab-name"); + }, + /** * @return {Promise} */ @@ -39,12 +73,24 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel }); }, + /** + * Toggle between opening or hiding the Loop panel. + * + * @param {DOMEvent} [event] Optional event that triggered the call to this + * function. + * @param {String} [tabId] Optional name of the tab to select after the panel + * has opened. Does nothing when the panel is hidden. + * @return {Promise} + */ togglePanel: function(event, tabId = null) { if (this.panel.state == "open") { - this.panel.hidePopup(); - } else { - this.openCallPanel(event, tabId); + return new Promise(resolve => { + this.panel.hidePopup(); + resolve(); + }); } + + return this.openCallPanel(event, tabId); }, /** diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index a1a62faf6928..b7fdb597e3aa 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -738,13 +738,15 @@ function injectLoopAPI(targetWindow) { * Notifies the UITour module that an event occurred that it might be * interested in. * - * @param {String} subject Subject of the notification + * @param {String} subject Subject of the notification + * @param {mixed} [params] Optional parameters, providing more details to + * the notification subject */ notifyUITour: { enumerable: true, writable: true, - value: function(subject) { - UITour.notify(subject); + value: function(subject, params) { + UITour.notify(subject, params); } }, diff --git a/browser/components/loop/content/js/panel.js b/browser/components/loop/content/js/panel.js index 9eb82a556586..fdac7816b174 100644 --- a/browser/components/loop/content/js/panel.js +++ b/browser/components/loop/content/js/panel.js @@ -25,7 +25,8 @@ loop.panel = (function(_, mozL10n) { propTypes: { buttonsHidden: React.PropTypes.array, // The selectedTab prop is used by the UI showcase. - selectedTab: React.PropTypes.string + selectedTab: React.PropTypes.string, + mozLoop: React.PropTypes.object }, getDefaultProps: function() { @@ -34,6 +35,14 @@ loop.panel = (function(_, mozL10n) { }; }, + shouldComponentUpdate: function(nextProps, nextState) { + var tabChange = this.state.selectedTab !== nextState.selectedTab; + if (tabChange) { + this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab); + } + return tabChange; + }, + getInitialState: function() { // XXX Work around props.selectedTab being undefined initially. // When we don't need to rely on the pref, this can move back to @@ -799,7 +808,7 @@ loop.panel = (function(_, mozL10n) { React.createElement(NotificationListView, {notifications: this.props.notifications, clearOnDocumentHidden: true}), React.createElement(TabView, {ref: "tabView", selectedTab: this.props.selectedTab, - buttonsHidden: hideButtons}, + buttonsHidden: hideButtons, mozLoop: this.props.mozLoop}, React.createElement(Tab, {name: "rooms"}, React.createElement(RoomList, {dispatcher: this.props.dispatcher, store: this.props.roomStore, diff --git a/browser/components/loop/content/js/panel.jsx b/browser/components/loop/content/js/panel.jsx index 35ce9bb221c4..2470573c284c 100644 --- a/browser/components/loop/content/js/panel.jsx +++ b/browser/components/loop/content/js/panel.jsx @@ -25,7 +25,8 @@ loop.panel = (function(_, mozL10n) { propTypes: { buttonsHidden: React.PropTypes.array, // The selectedTab prop is used by the UI showcase. - selectedTab: React.PropTypes.string + selectedTab: React.PropTypes.string, + mozLoop: React.PropTypes.object }, getDefaultProps: function() { @@ -34,6 +35,14 @@ loop.panel = (function(_, mozL10n) { }; }, + shouldComponentUpdate: function(nextProps, nextState) { + var tabChange = this.state.selectedTab !== nextState.selectedTab; + if (tabChange) { + this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab); + } + return tabChange; + }, + getInitialState: function() { // XXX Work around props.selectedTab being undefined initially. // When we don't need to rely on the pref, this can move back to @@ -799,7 +808,7 @@ loop.panel = (function(_, mozL10n) { + buttonsHidden={hideButtons} mozLoop={this.props.mozLoop}> { - let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe"); - if (!loopBrowser) { + let loopUI = aDocument.defaultView.LoopUI; + if (loopUI.selectedTab != "rooms") { return null; } // Use the parentElement full-width container of the button so our arrow // doesn't overlap the panel contents much. - return loopBrowser.contentDocument.querySelector(".new-room-button").parentElement; + return loopUI.browser.contentDocument.querySelector(".new-room-button").parentElement; }, }], ["loop-roomList", { infoPanelPosition: "leftcenter topright", query: (aDocument) => { - let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe"); - if (!loopBrowser) { + let loopUI = aDocument.defaultView.LoopUI; + if (loopUI.selectedTab != "rooms") { return null; } - return loopBrowser.contentDocument.querySelector(".room-list"); + return loopUI.browser.contentDocument.querySelector(".room-list"); }, }], ["loop-selectedRoomButtons", { @@ -178,7 +178,7 @@ this.UITour = { }], ["loop-signInUpLink", { query: (aDocument) => { - let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe"); + let loopBrowser = aDocument.defaultView.LoopUI.browser; if (!loopBrowser) { return null; } diff --git a/browser/components/uitour/test/browser_UITour_loop.js b/browser/components/uitour/test/browser_UITour_loop.js index 88c842211d0b..64bfc69298bb 100644 --- a/browser/components/uitour/test/browser_UITour_loop.js +++ b/browser/components/uitour/test/browser_UITour_loop.js @@ -11,6 +11,7 @@ let loopPanel = document.getElementById("loop-notification-panel"); Components.utils.import("resource:///modules/UITour.jsm"); const { LoopRooms } = Components.utils.import("resource:///modules/loop/LoopRooms.jsm", {}); +const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); function test() { UITourTest(); @@ -181,6 +182,53 @@ let tests = [ }); }); }, + taskify(function* test_panelTabChangeNotifications() { + // First make sure the Loop panel looks like we're logged in to have more than + // just one tab to switch to. + const fxASampleToken = { + token_type: "bearer", + access_token: "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752", + scope: "profile" + }; + const fxASampleProfile = { + email: "test@example.com", + uid: "abcd1234" + }; + MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken; + MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile; + yield MozLoopServiceInternal.notifyStatusChanged("login"); + + // Show the Loop menu. + yield showMenuPromise("loop"); + + // Listen for and test the notifications that will arrive from now on. + let tabChangePromise = new Promise(resolve => { + gContentAPI.observe((event, params) => { + is(event, "Loop:PanelTabChanged", "Check Loop:PanelTabChanged notification"); + is(params, "contacts", "Check the tab name param"); + + gContentAPI.observe((event, params) => { + is(event, "Loop:PanelTabChanged", "Check Loop:PanelTabChanged notification"); + is(params, "rooms", "Check the tab name param"); + + gContentAPI.observe((event, params) => { + ok(false, "No more notifications should have arrived"); + }); + resolve(); + }); + }); + }); + + // Switch to the contacts tab. + yield window.LoopUI.openCallPanel(null, "contacts"); + + // Logout. The panel tab will switch back to 'rooms'. + MozLoopServiceInternal.fxAOAuthTokenData = + MozLoopServiceInternal.fxAOAuthProfile = null; + yield MozLoopServiceInternal.notifyStatusChanged(); + + yield tabChangePromise; + }), runOffline(function test_notifyLoopChatWindowOpenedClosed(done) { gContentAPI.observe((event, params) => { is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification"); From ba6b80db37d316b1e296b01c01bf67c73183e793 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 10 Feb 2015 15:19:43 -0800 Subject: [PATCH 12/33] Backed out changeset b04123c901ac (bug 1121210) for Mn failures --- browser/base/content/browser-loop.js | 52 +---------------- browser/components/loop/MozLoopAPI.jsm | 8 +-- browser/components/loop/content/js/panel.js | 13 +---- browser/components/loop/content/js/panel.jsx | 13 +---- .../test/mochitest/browser_toolbarbutton.js | 57 ++----------------- browser/components/uitour/UITour.jsm | 14 ++--- .../uitour/test/browser_UITour_loop.js | 48 ---------------- 7 files changed, 22 insertions(+), 183 deletions(-) diff --git a/browser/base/content/browser-loop.js b/browser/base/content/browser-loop.js index ac6b2ed80627..0f27072bad18 100644 --- a/browser/base/content/browser-loop.js +++ b/browser/base/content/browser-loop.js @@ -13,50 +13,16 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel (function() { LoopUI = { - /** - * @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton - * instance for this window. - */ get toolbarButton() { delete this.toolbarButton; return this.toolbarButton = CustomizableUI.getWidget("loop-button").forWindow(window); }, - /** - * @var {XULElement} panel Getter for the Loop panel element. - */ get panel() { delete this.panel; return this.panel = document.getElementById("loop-notification-panel"); }, - /** - * @var {XULElement|null} browser Getter for the Loop panel browser element. - * Will be NULL if the panel hasn't loaded yet. - */ - get browser() { - let browser = document.querySelector("#loop-notification-panel > #loop-panel-iframe"); - if (browser) { - delete this.browser; - this.browser = browser; - } - return browser; - }, - - /** - * @var {String|null} selectedTab Getter for the name of the currently selected - * tab inside the Loop panel. Will be NULL if - * the panel hasn't loaded yet. - */ - get selectedTab() { - if (!this.browser) { - return null; - } - - let selectedTab = this.browser.contentDocument.querySelector(".tab-view > .selected"); - return selectedTab && selectedTab.getAttribute("data-tab-name"); - }, - /** * @return {Promise} */ @@ -73,24 +39,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel }); }, - /** - * Toggle between opening or hiding the Loop panel. - * - * @param {DOMEvent} [event] Optional event that triggered the call to this - * function. - * @param {String} [tabId] Optional name of the tab to select after the panel - * has opened. Does nothing when the panel is hidden. - * @return {Promise} - */ togglePanel: function(event, tabId = null) { if (this.panel.state == "open") { - return new Promise(resolve => { - this.panel.hidePopup(); - resolve(); - }); + this.panel.hidePopup(); + } else { + this.openCallPanel(event, tabId); } - - return this.openCallPanel(event, tabId); }, /** diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index b7fdb597e3aa..a1a62faf6928 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -738,15 +738,13 @@ function injectLoopAPI(targetWindow) { * Notifies the UITour module that an event occurred that it might be * interested in. * - * @param {String} subject Subject of the notification - * @param {mixed} [params] Optional parameters, providing more details to - * the notification subject + * @param {String} subject Subject of the notification */ notifyUITour: { enumerable: true, writable: true, - value: function(subject, params) { - UITour.notify(subject, params); + value: function(subject) { + UITour.notify(subject); } }, diff --git a/browser/components/loop/content/js/panel.js b/browser/components/loop/content/js/panel.js index fdac7816b174..9eb82a556586 100644 --- a/browser/components/loop/content/js/panel.js +++ b/browser/components/loop/content/js/panel.js @@ -25,8 +25,7 @@ loop.panel = (function(_, mozL10n) { propTypes: { buttonsHidden: React.PropTypes.array, // The selectedTab prop is used by the UI showcase. - selectedTab: React.PropTypes.string, - mozLoop: React.PropTypes.object + selectedTab: React.PropTypes.string }, getDefaultProps: function() { @@ -35,14 +34,6 @@ loop.panel = (function(_, mozL10n) { }; }, - shouldComponentUpdate: function(nextProps, nextState) { - var tabChange = this.state.selectedTab !== nextState.selectedTab; - if (tabChange) { - this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab); - } - return tabChange; - }, - getInitialState: function() { // XXX Work around props.selectedTab being undefined initially. // When we don't need to rely on the pref, this can move back to @@ -808,7 +799,7 @@ loop.panel = (function(_, mozL10n) { React.createElement(NotificationListView, {notifications: this.props.notifications, clearOnDocumentHidden: true}), React.createElement(TabView, {ref: "tabView", selectedTab: this.props.selectedTab, - buttonsHidden: hideButtons, mozLoop: this.props.mozLoop}, + buttonsHidden: hideButtons}, React.createElement(Tab, {name: "rooms"}, React.createElement(RoomList, {dispatcher: this.props.dispatcher, store: this.props.roomStore, diff --git a/browser/components/loop/content/js/panel.jsx b/browser/components/loop/content/js/panel.jsx index 2470573c284c..35ce9bb221c4 100644 --- a/browser/components/loop/content/js/panel.jsx +++ b/browser/components/loop/content/js/panel.jsx @@ -25,8 +25,7 @@ loop.panel = (function(_, mozL10n) { propTypes: { buttonsHidden: React.PropTypes.array, // The selectedTab prop is used by the UI showcase. - selectedTab: React.PropTypes.string, - mozLoop: React.PropTypes.object + selectedTab: React.PropTypes.string }, getDefaultProps: function() { @@ -35,14 +34,6 @@ loop.panel = (function(_, mozL10n) { }; }, - shouldComponentUpdate: function(nextProps, nextState) { - var tabChange = this.state.selectedTab !== nextState.selectedTab; - if (tabChange) { - this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab); - } - return tabChange; - }, - getInitialState: function() { // XXX Work around props.selectedTab being undefined initially. // When we don't need to rely on the pref, this can move back to @@ -808,7 +799,7 @@ loop.panel = (function(_, mozL10n) { + buttonsHidden={hideButtons}> { - let loopUI = aDocument.defaultView.LoopUI; - if (loopUI.selectedTab != "rooms") { + let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe"); + if (!loopBrowser) { return null; } // Use the parentElement full-width container of the button so our arrow // doesn't overlap the panel contents much. - return loopUI.browser.contentDocument.querySelector(".new-room-button").parentElement; + return loopBrowser.contentDocument.querySelector(".new-room-button").parentElement; }, }], ["loop-roomList", { infoPanelPosition: "leftcenter topright", query: (aDocument) => { - let loopUI = aDocument.defaultView.LoopUI; - if (loopUI.selectedTab != "rooms") { + let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe"); + if (!loopBrowser) { return null; } - return loopUI.browser.contentDocument.querySelector(".room-list"); + return loopBrowser.contentDocument.querySelector(".room-list"); }, }], ["loop-selectedRoomButtons", { @@ -178,7 +178,7 @@ this.UITour = { }], ["loop-signInUpLink", { query: (aDocument) => { - let loopBrowser = aDocument.defaultView.LoopUI.browser; + let loopBrowser = aDocument.querySelector("#loop-notification-panel > #loop-panel-iframe"); if (!loopBrowser) { return null; } diff --git a/browser/components/uitour/test/browser_UITour_loop.js b/browser/components/uitour/test/browser_UITour_loop.js index 64bfc69298bb..88c842211d0b 100644 --- a/browser/components/uitour/test/browser_UITour_loop.js +++ b/browser/components/uitour/test/browser_UITour_loop.js @@ -11,7 +11,6 @@ let loopPanel = document.getElementById("loop-notification-panel"); Components.utils.import("resource:///modules/UITour.jsm"); const { LoopRooms } = Components.utils.import("resource:///modules/loop/LoopRooms.jsm", {}); -const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}); function test() { UITourTest(); @@ -182,53 +181,6 @@ let tests = [ }); }); }, - taskify(function* test_panelTabChangeNotifications() { - // First make sure the Loop panel looks like we're logged in to have more than - // just one tab to switch to. - const fxASampleToken = { - token_type: "bearer", - access_token: "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752", - scope: "profile" - }; - const fxASampleProfile = { - email: "test@example.com", - uid: "abcd1234" - }; - MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken; - MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile; - yield MozLoopServiceInternal.notifyStatusChanged("login"); - - // Show the Loop menu. - yield showMenuPromise("loop"); - - // Listen for and test the notifications that will arrive from now on. - let tabChangePromise = new Promise(resolve => { - gContentAPI.observe((event, params) => { - is(event, "Loop:PanelTabChanged", "Check Loop:PanelTabChanged notification"); - is(params, "contacts", "Check the tab name param"); - - gContentAPI.observe((event, params) => { - is(event, "Loop:PanelTabChanged", "Check Loop:PanelTabChanged notification"); - is(params, "rooms", "Check the tab name param"); - - gContentAPI.observe((event, params) => { - ok(false, "No more notifications should have arrived"); - }); - resolve(); - }); - }); - }); - - // Switch to the contacts tab. - yield window.LoopUI.openCallPanel(null, "contacts"); - - // Logout. The panel tab will switch back to 'rooms'. - MozLoopServiceInternal.fxAOAuthTokenData = - MozLoopServiceInternal.fxAOAuthProfile = null; - yield MozLoopServiceInternal.notifyStatusChanged(); - - yield tabChangePromise; - }), runOffline(function test_notifyLoopChatWindowOpenedClosed(done) { gContentAPI.observe((event, params) => { is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification"); From 934806df2e37cbeebb90ee89d697e182c98891d1 Mon Sep 17 00:00:00 2001 From: Victor Porof Date: Tue, 10 Feb 2015 18:36:31 -0500 Subject: [PATCH 13/33] Bug 1131572 - DetailsView.setAvailableViews should be a task, r=jsantell --- browser/devtools/performance/views/details.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/browser/devtools/performance/views/details.js b/browser/devtools/performance/views/details.js index fdb53d1594f7..97dae02f3a73 100644 --- a/browser/devtools/performance/views/details.js +++ b/browser/devtools/performance/views/details.js @@ -36,7 +36,7 @@ let DetailsView = { } yield this.selectView(DEFAULT_DETAILS_SUBVIEW); - this.setAvailableViews(); + yield this.setAvailableViews(); PerformanceController.on(EVENTS.PREF_CHANGED, this.setAvailableViews); }), @@ -61,7 +61,7 @@ let DetailsView = { * buttons that select them and going to default view if currently selected. * Called when a preference changes in `devtools.performance.ui.`. */ - setAvailableViews: function () { + setAvailableViews: Task.async(function* () { for (let [name, { view, pref }] of Iterator(this.components)) { if (!pref) { continue; @@ -72,10 +72,10 @@ let DetailsView = { // If the view is currently selected and not enabled, go back to the // default view. if (!value && this.isViewSelected(view)) { - this.selectView(DEFAULT_DETAILS_SUBVIEW); + yield this.selectView(DEFAULT_DETAILS_SUBVIEW); } } - }, + }), /** * Select one of the DetailView's subviews to be rendered, From 64b01fc5a36270ef89d0c7d6604496e9ddfa9215 Mon Sep 17 00:00:00 2001 From: Victor Porof Date: Tue, 10 Feb 2015 18:36:31 -0500 Subject: [PATCH 14/33] Bug 1131577 - Waterfall view can scroll outside the visible bounds if the flamegraph view was initialized before a recording was started, r=jsantell --- browser/devtools/performance/test/browser.ini | 1 + .../test/browser_perf-details-03.js | 38 ++++++-- .../test/browser_perf-details-04.js | 87 +++++++++++++++++++ ...ser_perf-details-memory-calltree-render.js | 3 + ...r_perf-details-memory-flamegraph-render.js | 3 + browser/devtools/performance/test/head.js | 4 + browser/devtools/performance/views/details.js | 24 +++-- 7 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 browser/devtools/performance/test/browser_perf-details-04.js diff --git a/browser/devtools/performance/test/browser.ini b/browser/devtools/performance/test/browser.ini index 0688697d4257..ac81c60c0793 100644 --- a/browser/devtools/performance/test/browser.ini +++ b/browser/devtools/performance/test/browser.ini @@ -24,6 +24,7 @@ support-files = [browser_perf-details-01.js] [browser_perf-details-02.js] [browser_perf-details-03.js] +[browser_perf-details-04.js] [browser_perf-events-calltree.js] [browser_perf-front-basic-profiler-01.js] [browser_perf-front-basic-timeline-01.js] diff --git a/browser/devtools/performance/test/browser_perf-details-03.js b/browser/devtools/performance/test/browser_perf-details-03.js index 42cc6b15aa91..8a5388d9372b 100644 --- a/browser/devtools/performance/test/browser_perf-details-03.js +++ b/browser/devtools/performance/test/browser_perf-details-03.js @@ -1,30 +1,31 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let MEMORY_PREF = "devtools.performance.ui.enable-memory"; - /** * Tests that the details view hides the memory buttons when `enable-memory` is toggled, * and that it switches to default panel if toggling while a memory panel is selected. */ function spawnTest () { let { panel } = yield initPerformance(SIMPLE_URL); - let { EVENTS, DetailsView } = panel.panelWin; + let { EVENTS, PerformanceController, OverviewView, DetailsView } = panel.panelWin; let { $, WaterfallView, MemoryCallTreeView, MemoryFlameGraphView } = panel.panelWin; - Services.prefs.setBoolPref(MEMORY_PREF, false); - ok(DetailsView.isViewSelected(WaterfallView), "The waterfall view is selected by default in the details view."); + // The toolbar buttons will always be hidden when a recording isn't available, + // so make sure we have one that's finished. + yield startRecording(panel); + yield stopRecording(panel); + let flameBtn = $("toolbarbutton[data-view='memory-flamegraph']"); let callBtn = $("toolbarbutton[data-view='memory-calltree']"); + Services.prefs.setBoolPref(MEMORY_PREF, false); is(flameBtn.hidden, true, "memory-flamegraph button hidden when enable-memory=false"); is(callBtn.hidden, true, "memory-calltree button hidden when enable-memory=false"); Services.prefs.setBoolPref(MEMORY_PREF, true); - is(flameBtn.hidden, false, "memory-flamegraph button shown when enable-memory=true"); is(callBtn.hidden, false, "memory-calltree button shown when enable-memory=true"); @@ -33,6 +34,17 @@ function spawnTest () { DetailsView.selectView("memory-calltree"); yield Promise.all([selected, notified]); + ok(DetailsView.isViewSelected(MemoryCallTreeView), + "The memory call tree view can now be selected."); + + selected = DetailsView.whenViewSelected(MemoryFlameGraphView); + notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED); + DetailsView.selectView("memory-flamegraph"); + yield Promise.all([selected, notified]); + + ok(DetailsView.isViewSelected(MemoryFlameGraphView), + "The memory flamegraph view can now be selected."); + selected = DetailsView.whenViewSelected(WaterfallView); notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED); Services.prefs.setBoolPref(MEMORY_PREF, false); @@ -43,16 +55,30 @@ function spawnTest () { Services.prefs.setBoolPref(MEMORY_PREF, true); + selected = DetailsView.whenViewSelected(MemoryCallTreeView); + notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED); + DetailsView.selectView("memory-calltree"); + yield Promise.all([selected, notified]); + + ok(DetailsView.isViewSelected(MemoryCallTreeView), + "The memory call tree view can be selected again after re-enabling memory."); + selected = DetailsView.whenViewSelected(MemoryFlameGraphView); notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED); DetailsView.selectView("memory-flamegraph"); yield Promise.all([selected, notified]); + ok(DetailsView.isViewSelected(MemoryFlameGraphView), + "The memory flamegraph view can be selected again after re-enabling memory."); + selected = DetailsView.whenViewSelected(WaterfallView); notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED); Services.prefs.setBoolPref(MEMORY_PREF, false); yield Promise.all([selected, notified]); + ok(DetailsView.isViewSelected(WaterfallView), + "The waterfall view is now selected when toggling off enable-memory when a memory panel is selected."); + yield teardown(panel); finish(); } diff --git a/browser/devtools/performance/test/browser_perf-details-04.js b/browser/devtools/performance/test/browser_perf-details-04.js new file mode 100644 index 000000000000..c19646b6d784 --- /dev/null +++ b/browser/devtools/performance/test/browser_perf-details-04.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests that the details view hides the toolbar buttons when a recording + * doesn't exist or is in progress. + */ +function spawnTest () { + let { panel } = yield initPerformance(SIMPLE_URL); + let { EVENTS, $, $$, PerformanceController, RecordingsView, DetailsView } = panel.panelWin; + + let waterfallBtn = $("toolbarbutton[data-view='waterfall']"); + let jsFlameBtn = $("toolbarbutton[data-view='js-flamegraph']"); + let jsCallBtn = $("toolbarbutton[data-view='js-calltree']"); + let memFlameBtn = $("toolbarbutton[data-view='memory-flamegraph']"); + let memCallBtn = $("toolbarbutton[data-view='memory-calltree']"); + + is(waterfallBtn.hidden, true, "waterfall button hidden when tool starts."); + is(jsFlameBtn.hidden, true, "js-flamegraph button hidden when tool starts."); + is(jsCallBtn.hidden, true, "js-calltree button hidden when tool starts."); + is(memFlameBtn.hidden, true, "memory-flamegraph button hidden when tool starts."); + is(memCallBtn.hidden, true, "memory-calltree button hidden when tool starts."); + + yield startRecording(panel); + + is(waterfallBtn.hidden, true, "waterfall button hidden when recording starts."); + is(jsFlameBtn.hidden, true, "js-flamegraph button hidden when recording starts."); + is(jsCallBtn.hidden, true, "js-calltree button hidden when recording starts."); + is(memFlameBtn.hidden, true, "memory-flamegraph button hidden when recording starts."); + is(memCallBtn.hidden, true, "memory-calltree button hidden when recording starts."); + + yield stopRecording(panel); + + is(waterfallBtn.hidden, false, "waterfall button visible when recording ends."); + is(jsFlameBtn.hidden, false, "js-flamegraph button visible when recording ends."); + is(jsCallBtn.hidden, false, "js-calltree button visible when recording ends."); + is(memFlameBtn.hidden, true, "memory-flamegraph button hidden when recording ends."); + is(memCallBtn.hidden, true, "memory-calltree button hidden when recording ends."); + + yield startRecording(panel); + + is(waterfallBtn.hidden, true, "waterfall button hidden when another recording starts."); + is(jsFlameBtn.hidden, true, "js-flamegraph button hidden when another recording starts."); + is(jsCallBtn.hidden, true, "js-calltree button hidden when another recording starts."); + is(memFlameBtn.hidden, true, "memory-flamegraph button hidden when another recording starts."); + is(memCallBtn.hidden, true, "memory-calltree button hidden when another recording starts."); + + let select = once(PerformanceController, EVENTS.RECORDING_SELECTED); + mousedown(panel.panelWin, $$(".recording-item")[0]); + yield select; + + is(RecordingsView.selectedIndex, 0, + "The first recording was selected again."); + + is(waterfallBtn.hidden, false, "waterfall button visible when first recording selected."); + is(jsFlameBtn.hidden, false, "js-flamegraph button visible when first recording selected."); + is(jsCallBtn.hidden, false, "js-calltree button visible when first recording selected."); + is(memFlameBtn.hidden, true, "memory-flamegraph button hidden when first recording selected."); + is(memCallBtn.hidden, true, "memory-calltree button hidden when first recording selected."); + + select = once(PerformanceController, EVENTS.RECORDING_SELECTED); + mousedown(panel.panelWin, $$(".recording-item")[1]); + yield select; + + is(RecordingsView.selectedIndex, 1, + "The second recording was selected again."); + + is(waterfallBtn.hidden, true, "waterfall button still hidden when second recording selected."); + is(jsFlameBtn.hidden, true, "js-flamegraph button still hidden when second recording selected."); + is(jsCallBtn.hidden, true, "js-calltree button still hidden when second recording selected."); + is(memFlameBtn.hidden, true, "memory-flamegraph button still hidden when second recording selected."); + is(memCallBtn.hidden, true, "memory-calltree button still hidden when second recording selected."); + + yield stopRecording(panel); + + is(RecordingsView.selectedIndex, 1, + "The second recording is still selected."); + + is(waterfallBtn.hidden, false, "waterfall button visible when second recording finished."); + is(jsFlameBtn.hidden, false, "js-flamegraph button visible when second recording finished."); + is(jsCallBtn.hidden, false, "js-calltree button visible when second recording finished."); + is(memFlameBtn.hidden, true, "memory-flamegraph button hidden when second recording finished."); + is(memCallBtn.hidden, true, "memory-calltree button hidden when second recording finished."); + + yield teardown(panel); + finish(); +} diff --git a/browser/devtools/performance/test/browser_perf-details-memory-calltree-render.js b/browser/devtools/performance/test/browser_perf-details-memory-calltree-render.js index 0c3f85e41c3d..432b790ae9ac 100644 --- a/browser/devtools/performance/test/browser_perf-details-memory-calltree-render.js +++ b/browser/devtools/performance/test/browser_perf-details-memory-calltree-render.js @@ -8,6 +8,9 @@ function spawnTest () { let { panel } = yield initPerformance(SIMPLE_URL); let { EVENTS, DetailsView, MemoryCallTreeView } = panel.panelWin; + // Enable memory to test. + Services.prefs.setBoolPref(MEMORY_PREF, true); + yield DetailsView.selectView("memory-calltree"); ok(DetailsView.isViewSelected(MemoryCallTreeView), "The call tree is now selected."); diff --git a/browser/devtools/performance/test/browser_perf-details-memory-flamegraph-render.js b/browser/devtools/performance/test/browser_perf-details-memory-flamegraph-render.js index a1e1e58ca2ce..7629b28b0441 100644 --- a/browser/devtools/performance/test/browser_perf-details-memory-flamegraph-render.js +++ b/browser/devtools/performance/test/browser_perf-details-memory-flamegraph-render.js @@ -8,6 +8,9 @@ function spawnTest () { let { panel } = yield initPerformance(SIMPLE_URL); let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin; + // Enable memory to test. + Services.prefs.setBoolPref(MEMORY_PREF, true); + yield DetailsView.selectView("memory-flamegraph"); ok(DetailsView.isViewSelected(MemoryFlameGraphView), "The flamegraph is now selected."); diff --git a/browser/devtools/performance/test/head.js b/browser/devtools/performance/test/head.js index 272be3fcd7ee..c090b7498d48 100644 --- a/browser/devtools/performance/test/head.js +++ b/browser/devtools/performance/test/head.js @@ -262,6 +262,10 @@ function click (win, button) { EventUtils.sendMouseEvent({ type: "click" }, button, win); } +function mousedown (win, button) { + EventUtils.sendMouseEvent({ type: "mousedown" }, button, win); +} + function* startRecording(panel) { let win = panel.panelWin; let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING); diff --git a/browser/devtools/performance/views/details.js b/browser/devtools/performance/views/details.js index 97dae02f3a73..866051e1b37b 100644 --- a/browser/devtools/performance/views/details.js +++ b/browser/devtools/performance/views/details.js @@ -29,6 +29,7 @@ let DetailsView = { this.toolbar = $("#performance-toolbar-controls-detail-views"); this._onViewToggle = this._onViewToggle.bind(this); + this._onRecordingStoppedOrSelected = this._onRecordingStoppedOrSelected.bind(this); this.setAvailableViews = this.setAvailableViews.bind(this); for (let button of $$("toolbarbutton[data-view]", this.toolbar)) { @@ -38,6 +39,8 @@ let DetailsView = { yield this.selectView(DEFAULT_DETAILS_SUBVIEW); yield this.setAvailableViews(); + PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStoppedOrSelected); + PerformanceController.on(EVENTS.RECORDING_SELECTED, this._onRecordingStoppedOrSelected); PerformanceController.on(EVENTS.PREF_CHANGED, this.setAvailableViews); }), @@ -53,6 +56,8 @@ let DetailsView = { component.initialized && (yield component.view.destroy()); } + PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStoppedOrSelected); + PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingStoppedOrSelected); PerformanceController.off(EVENTS.PREF_CHANGED, this.setAvailableViews); }), @@ -63,15 +68,15 @@ let DetailsView = { */ setAvailableViews: Task.async(function* () { for (let [name, { view, pref }] of Iterator(this.components)) { - if (!pref) { - continue; - } - let value = PerformanceController.getPref(pref); - $(`toolbarbutton[data-view=${name}]`).hidden = !value; + let recording = PerformanceController.getCurrentRecording(); + + let isRecorded = recording && !recording.isRecording(); + let isEnabled = !pref || PerformanceController.getPref(pref); + $(`toolbarbutton[data-view=${name}]`).hidden = !isRecorded || !isEnabled; // If the view is currently selected and not enabled, go back to the // default view. - if (!value && this.isViewSelected(view)) { + if (!isEnabled && this.isViewSelected(view)) { yield this.selectView(DEFAULT_DETAILS_SUBVIEW); } } @@ -159,6 +164,13 @@ let DetailsView = { } }), + /** + * Called when recording stops or is selected. + */ + _onRecordingStoppedOrSelected: function(_, recording) { + this.setAvailableViews(); + }, + /** * Called when a view button is clicked. */ From bc3c2931e6340093547547023f5b965691d2d78f Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 10 Feb 2015 16:11:24 -0800 Subject: [PATCH 15/33] Bug 1126240 - Correctly encode APK paths in SearchEngineManager. r=margaret This is the approach we already take everywhere else we make a jar:jar: URI. I've unified those places into GeckoJarReader, cleaned up imports, fixed a typo, and wrote a trivial test for this case. I made a few utility methods static to facilitate testing and future refactoring. --- mobile/android/base/BrowserLocaleManager.java | 6 +---- mobile/android/base/db/LocalBrowserDB.java | 11 +++----- mobile/android/base/favicons/Favicons.java | 5 +--- mobile/android/base/tests/testJarReader.java | 7 +++++ mobile/android/base/util/GeckoJarReader.java | 21 +++++++++++++++ .../search/providers/SearchEngineManager.java | 27 +++++++------------ 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/mobile/android/base/BrowserLocaleManager.java b/mobile/android/base/BrowserLocaleManager.java index 045e01d28399..86087fdc78fe 100644 --- a/mobile/android/base/BrowserLocaleManager.java +++ b/mobile/android/base/BrowserLocaleManager.java @@ -398,11 +398,7 @@ public class BrowserLocaleManager implements LocaleManager { */ public static Collection getPackagedLocaleTags(final Context context) { final String resPath = "res/multilocale.json"; - final String apkPath = context.getPackageResourcePath(); - - final String jarURL = "jar:jar:" + new File(apkPath).toURI() + "!/" + - AppConstants.OMNIJAR_NAME + "!/" + - resPath; + final String jarURL = GeckoJarReader.getJarURL(context, resPath); final String contents = GeckoJarReader.getText(jarURL); if (contents == null) { diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index 4ab2f7493026..0b6ff3addff7 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -468,18 +468,13 @@ public class LocalBrowserDB implements BrowserDB { * compatible with the favicon decoder (most probably a PNG or ICO file). */ private static ConsumedInputStream getDefaultFaviconFromPath(Context context, String name) { - int faviconId = getFaviconId(name); + final int faviconId = getFaviconId(name); if (faviconId == FAVICON_ID_NOT_FOUND) { return null; } - String path = context.getString(faviconId); - - String apkPath = context.getPackageResourcePath(); - File apkFile = new File(apkPath); - String bitmapPath = "jar:jar:" + apkFile.toURI() + "!/" + AppConstants.OMNIJAR_NAME + "!/" + path; - - InputStream iStream = GeckoJarReader.getStream(bitmapPath); + final String bitmapPath = GeckoJarReader.getJarURL(context, context.getString(faviconId)); + final InputStream iStream = GeckoJarReader.getStream(bitmapPath); return IOUtils.readFully(iStream, DEFAULT_FAVICON_BUFFER_SIZE); } diff --git a/mobile/android/base/favicons/Favicons.java b/mobile/android/base/favicons/Favicons.java index 3c467032f57c..8ff6ca342456 100644 --- a/mobile/android/base/favicons/Favicons.java +++ b/mobile/android/base/favicons/Favicons.java @@ -498,10 +498,7 @@ public class Favicons { * "jar:jar:file:///data/app/org.mozilla.firefox-1.apk!/assets/omni.ja!/chrome/chrome/content/branding/favicon64.png" */ private static String getBrandingBitmapPath(Context context, String name) { - final String apkPath = context.getPackageResourcePath(); - return "jar:jar:" + new File(apkPath).toURI() + "!/" + - AppConstants.OMNIJAR_NAME + "!/" + - "chrome/chrome/content/branding/" + name; + return GeckoJarReader.getJarURL(context, "chrome/chrome/content/branding/" + name); } private static Bitmap loadBrandingBitmap(Context context, String name) { diff --git a/mobile/android/base/tests/testJarReader.java b/mobile/android/base/tests/testJarReader.java index 478b099a2f6c..0b712057cd95 100644 --- a/mobile/android/base/tests/testJarReader.java +++ b/mobile/android/base/tests/testJarReader.java @@ -14,6 +14,13 @@ import org.mozilla.gecko.util.GeckoJarReader; * as loading some invalid jar urls. */ public class testJarReader extends BaseTest { + public void testGetJarURL() { + // Invalid characters are escaped. + final String s = GeckoJarReader.computeJarURI("some[1].apk", "something/else"); + mAsserter.ok(s.contains("["), "Illegal characters are escaped away."); + mAsserter.ok(s.toLowerCase().contains("%2f"), "Path characters aren't escaped."); + } + public void testJarReader() { String appPath = getActivity().getApplication().getPackageResourcePath(); mAsserter.isnot(appPath, null, "getPackageResourcePath is non-null"); diff --git a/mobile/android/base/util/GeckoJarReader.java b/mobile/android/base/util/GeckoJarReader.java index e10063f4a01e..828d7cf7a432 100644 --- a/mobile/android/base/util/GeckoJarReader.java +++ b/mobile/android/base/util/GeckoJarReader.java @@ -4,6 +4,8 @@ package org.mozilla.gecko.util; +import android.content.Context; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.mozglue.NativeZip; import android.content.res.Resources; @@ -13,6 +15,7 @@ import android.util.Log; import org.mozilla.gecko.mozglue.RobocopTarget; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -171,4 +174,22 @@ public final class GeckoJarReader { return results; } } + + public static String getJarURL(Context context, String pathInsideJAR) { + // We need to encode the package resource path, because it might contain illegal characters. For example: + // /mnt/asec2/[2]org.mozilla.fennec-1/pkg.apk + // The round-trip through a URI does this for us. + final String resourcePath = context.getPackageResourcePath(); + return computeJarURI(resourcePath, pathInsideJAR); + } + + /** + * Encodes its resource path correctly. + */ + public static String computeJarURI(String resourcePath, String pathInsideJAR) { + final String resURI = new File(resourcePath).toURI().toString(); + + // TODO: do we need to encode the file path, too? + return "jar:jar:" + resURI + "!/" + AppConstants.OMNIJAR_NAME + "!/" + pathInsideJAR; + } } diff --git a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java index 62e2e619fba0..465c78dfa61a 100644 --- a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java +++ b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java @@ -8,7 +8,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; import android.util.Log; - import org.json.JSONException; import org.json.JSONObject; import org.mozilla.gecko.AppConstants; @@ -16,20 +15,18 @@ import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.GeckoSharedPrefs; import org.mozilla.gecko.Locales; import org.mozilla.gecko.R; +import org.mozilla.gecko.distribution.Distribution; import org.mozilla.gecko.util.FileUtils; import org.mozilla.gecko.util.GeckoJarReader; import org.mozilla.gecko.util.HardwareUtils; import org.mozilla.gecko.util.RawResource; import org.mozilla.gecko.util.ThreadUtils; -import org.mozilla.gecko.distribution.Distribution; -import org.mozilla.search.Constants; import org.xmlpull.v1.XmlPullParserException; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -37,8 +34,6 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; public class SearchEngineManager implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -532,7 +527,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return engine; } } catch (IOException e) { - Log.e(LOG_TAG, "Error creating earch engine from name: " + name, e); + Log.e(LOG_TAG, "Error creating search engine from name: " + name, e); } } return null; @@ -573,7 +568,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // First, try a file path for the full locale. final String languageTag = Locales.getLanguageTag(locale); - String url = getSearchPluginsJarURL(languageTag, fileName); + String url = getSearchPluginsJarURL(context, languageTag, fileName); InputStream in = GeckoJarReader.getStream(url); if (in != null) { @@ -583,7 +578,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // If that doesn't work, try a file path for just the language. final String language = Locales.getLanguage(locale); if (!languageTag.equals(language)) { - url = getSearchPluginsJarURL(language, fileName); + url = getSearchPluginsJarURL(context, language, fileName); in = GeckoJarReader.getStream(url); if (in != null) { return in; @@ -591,7 +586,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference } // Finally, fall back to default locale defined in chrome registry. - url = getSearchPluginsJarURL(getFallbackLocale(), fileName); + url = getSearchPluginsJarURL(context, getFallbackLocale(), fileName); return GeckoJarReader.getStream(url); } @@ -606,7 +601,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return fallbackLocale; } - final InputStream in = GeckoJarReader.getStream(getJarURL("!/chrome/chrome.manifest")); + final InputStream in = GeckoJarReader.getStream(GeckoJarReader.getJarURL(context, "chrome/chrome.manifest")); final BufferedReader br = getBufferedReader(in); try { @@ -638,13 +633,9 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference * @param fileName The name of the file to read. * @return URL for jar file. */ - private String getSearchPluginsJarURL(String locale, String fileName) { - final String path = "!/chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName; - return getJarURL(path); - } - - private String getJarURL(String path) { - return "jar:jar:file://" + context.getPackageResourcePath() + "!/" + AppConstants.OMNIJAR_NAME + path; + private static String getSearchPluginsJarURL(Context context, String locale, String fileName) { + final String path = "chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName; + return GeckoJarReader.getJarURL(context, path); } private BufferedReader getBufferedReader(InputStream in) { From 8713840e2832d25eb2829641f9c9f9dbe0ff9951 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 10 Feb 2015 16:42:13 -0800 Subject: [PATCH 16/33] Bug 1131257 - Part 1: split LocalReadingListDB out of LocalBrowserDB. r=margaret Centralizing reading list access logic will make Bug 1130461 much easier. This bug is the first part of that. We follow the same pattern as for URLMetadata, TabsAccessor, and Searches; BrowserDB hands over a single class that's specialized to handle the Reading List. --- mobile/android/base/BrowserApp.java | 2 +- mobile/android/base/ReadingListHelper.java | 20 +-- mobile/android/base/db/BrowserDB.java | 13 +- mobile/android/base/db/LocalBrowserDB.java | 96 +------------ .../base/db/LocalReadingListAccessor.java | 128 ++++++++++++++++++ .../android/base/db/ReadingListAccessor.java | 32 +++++ mobile/android/base/db/StubBrowserDB.java | 48 +++++++ mobile/android/base/home/HomeFragment.java | 2 +- .../android/base/home/ReadingListPanel.java | 7 +- mobile/android/base/moz.build | 2 + .../sharemethods/AddToReadingList.java | 2 +- .../android/base/overlays/ui/ShareDialog.java | 2 +- 12 files changed, 236 insertions(+), 118 deletions(-) create mode 100644 mobile/android/base/db/LocalReadingListAccessor.java create mode 100644 mobile/android/base/db/ReadingListAccessor.java diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index 0749d358f489..b8f67a501065 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -1698,7 +1698,7 @@ public class BrowserApp extends GeckoApp Telemetry.addToHistogram("PLACES_BOOKMARKS_COUNT", db.getCount(cr, "bookmarks")); Telemetry.addToHistogram("FENNEC_FAVICONS_COUNT", db.getCount(cr, "favicons")); Telemetry.addToHistogram("FENNEC_THUMBNAILS_COUNT", db.getCount(cr, "thumbnails")); - Telemetry.addToHistogram("FENNEC_READING_LIST_COUNT", db.getCount(getContentResolver(), "readinglist")); + Telemetry.addToHistogram("FENNEC_READING_LIST_COUNT", db.getReadingListAccessor().getCount(cr)); Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT", (isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0)); if (Versions.feature16Plus) { Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT", (isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0)); diff --git a/mobile/android/base/ReadingListHelper.java b/mobile/android/base/ReadingListHelper.java index 85e05dfee5e8..4e3b96ec4b60 100644 --- a/mobile/android/base/ReadingListHelper.java +++ b/mobile/android/base/ReadingListHelper.java @@ -9,6 +9,7 @@ import org.json.JSONObject; import org.mozilla.gecko.db.BrowserContract.ReadingListItems; import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.DBUtils; +import org.mozilla.gecko.db.ReadingListAccessor; import org.mozilla.gecko.favicons.Favicons; import org.mozilla.gecko.util.EventCallback; import org.mozilla.gecko.util.NativeEventListener; @@ -30,18 +31,17 @@ public final class ReadingListHelper implements NativeEventListener { protected final Context context; private final BrowserDB db; - - private final Uri readingListUriWithProfile; + private final ReadingListAccessor readingListAccessor; private final ContentObserver contentObserver; public ReadingListHelper(Context context, GeckoProfile profile) { this.context = context; this.db = profile.getDB(); + this.readingListAccessor = db.getReadingListAccessor(); EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener) this, "Reader:AddToList", "Reader:UpdateList", "Reader:FaviconRequest", "Reader:ListStatusRequest", "Reader:RemoveFromList"); - readingListUriWithProfile = DBUtils.appendProfile(profile.getName(), ReadingListItems.CONTENT_URI); contentObserver = new ContentObserver(null) { @Override @@ -50,7 +50,7 @@ public final class ReadingListHelper implements NativeEventListener { } }; - context.getContentResolver().registerContentObserver(readingListUriWithProfile, false, contentObserver); + this.readingListAccessor.registerContentObserver(context, contentObserver); } public void uninit() { @@ -104,11 +104,11 @@ public final class ReadingListHelper implements NativeEventListener { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { - if (db.isReadingListItem(cr, url)) { + if (readingListAccessor.isReadingListItem(cr, url)) { showToast(R.string.reading_list_duplicate, Toast.LENGTH_SHORT); callback.sendError("URL already in reading list: " + url); } else { - db.addReadingListItem(cr, values); + readingListAccessor.addReadingListItem(cr, values); showToast(R.string.reading_list_added, Toast.LENGTH_SHORT); callback.sendSuccess(url); } @@ -126,7 +126,7 @@ public final class ReadingListHelper implements NativeEventListener { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { - db.updateReadingListItem(cr, values); + readingListAccessor.updateReadingListItem(cr, values); } }); } @@ -192,7 +192,7 @@ public final class ReadingListHelper implements NativeEventListener { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { - db.removeReadingListItemWithURL(context.getContentResolver(), url); + readingListAccessor.removeReadingListItemWithURL(context.getContentResolver(), url); GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:Removed", url)); showToast(R.string.page_removed, Toast.LENGTH_SHORT); } @@ -207,7 +207,7 @@ public final class ReadingListHelper implements NativeEventListener { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { - final int inReadingList = db.isReadingListItem(context.getContentResolver(), url) ? 1 : 0; + final int inReadingList = readingListAccessor.isReadingListItem(context.getContentResolver(), url) ? 1 : 0; final JSONObject json = new JSONObject(); try { @@ -239,7 +239,7 @@ public final class ReadingListHelper implements NativeEventListener { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { - final Cursor c = db.getReadingListUnfetched(context.getContentResolver()); + final Cursor c = readingListAccessor.getReadingListUnfetched(context.getContentResolver()); try { while (c.moveToNext()) { JSONObject json = new JSONObject(); diff --git a/mobile/android/base/db/BrowserDB.java b/mobile/android/base/db/BrowserDB.java index 9d4d5ee89fc4..876ad0fcbba4 100644 --- a/mobile/android/base/db/BrowserDB.java +++ b/mobile/android/base/db/BrowserDB.java @@ -16,7 +16,6 @@ import org.mozilla.gecko.favicons.decoders.LoadFaviconResult; import android.content.ContentProviderOperation; import android.content.ContentResolver; -import android.content.ContentValues; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; @@ -43,6 +42,7 @@ public interface BrowserDB { public abstract Searches getSearches(); public abstract TabsAccessor getTabsAccessor(); public abstract URLMetadata getURLMetadata(); + public abstract ReadingListAccessor getReadingListAccessor(); /** * Add default bookmarks to the database. @@ -118,17 +118,6 @@ public interface BrowserDB { */ public abstract Cursor getBookmarksInFolder(ContentResolver cr, long folderId); - /** - * Can return null. - */ - public abstract Cursor getReadingList(ContentResolver cr); - public abstract Cursor getReadingListUnfetched(ContentResolver cr); - public abstract boolean isReadingListItem(ContentResolver cr, String uri); - public abstract void addReadingListItem(ContentResolver cr, ContentValues values); - public abstract void updateReadingListItem(ContentResolver cr, ContentValues values); - public abstract void removeReadingListItemWithURL(ContentResolver cr, String uri); - - /** * Get the favicon from the database, if any, associated with the given favicon URL. (That is, * the URL of the actual favicon image, not the URL of the page with which the favicon is associated.) diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index 0b6ff3addff7..e09b3732a2ea 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -98,11 +98,11 @@ public class LocalBrowserDB implements BrowserDB { private final Uri mUpdateHistoryUriWithProfile; private final Uri mFaviconsUriWithProfile; private final Uri mThumbnailsUriWithProfile; - private final Uri mReadingListUriWithProfile; private LocalSearches searches; private LocalTabsAccessor tabsAccessor; private LocalURLMetadata urlMetadata; + private LocalReadingListAccessor readingListAccessor; private static final String[] DEFAULT_BOOKMARK_COLUMNS = new String[] { Bookmarks._ID, @@ -123,7 +123,6 @@ public class LocalBrowserDB implements BrowserDB { mCombinedUriWithProfile = DBUtils.appendProfile(profile, Combined.CONTENT_URI); mFaviconsUriWithProfile = DBUtils.appendProfile(profile, Favicons.CONTENT_URI); mThumbnailsUriWithProfile = DBUtils.appendProfile(profile, Thumbnails.CONTENT_URI); - mReadingListUriWithProfile = DBUtils.appendProfile(profile, ReadingListItems.CONTENT_URI); mUpdateHistoryUriWithProfile = mHistoryUriWithProfile.buildUpon() @@ -134,6 +133,7 @@ public class LocalBrowserDB implements BrowserDB { searches = new LocalSearches(mProfile); tabsAccessor = new LocalTabsAccessor(mProfile); urlMetadata = new LocalURLMetadata(mProfile); + readingListAccessor = new LocalReadingListAccessor(mProfile); } @Override @@ -151,6 +151,11 @@ public class LocalBrowserDB implements BrowserDB { return urlMetadata; } + @Override + public ReadingListAccessor getReadingListAccessor() { + return readingListAccessor; + } + /** * Not thread safe. A helper to allocate new IDs for arbitrary strings. */ @@ -576,9 +581,6 @@ public class LocalBrowserDB implements BrowserDB { } else if ("favicons".equals(database)) { uri = mFaviconsUriWithProfile; columns = new String[] { Favicons._ID }; - } else if ("readinglist".equals(database)) { - uri = mReadingListUriWithProfile; - columns = new String[] { ReadingListItems._ID }; } if (uri != null) { @@ -819,26 +821,6 @@ public class LocalBrowserDB implements BrowserDB { } } - @Override - public boolean isReadingListItem(ContentResolver cr, String uri) { - final Cursor c = cr.query(mReadingListUriWithProfile, - new String[] { ReadingListItems._ID }, - ReadingListItems.URL + " = ? ", - new String[] { uri }, - null); - - if (c == null) { - Log.e(LOGTAG, "Null cursor in isReadingListItem"); - return false; - } - - try { - return c.getCount() > 0; - } finally { - c.close(); - } - } - @Override public String getUrlForKeyword(ContentResolver cr, String keyword) { final Cursor c = cr.query(mBookmarksUriWithProfile, @@ -968,70 +950,6 @@ public class LocalBrowserDB implements BrowserDB { cr.delete(contentUri, urlEquals, urlArgs); } - @Override - public Cursor getReadingList(ContentResolver cr) { - return cr.query(mReadingListUriWithProfile, - ReadingListItems.DEFAULT_PROJECTION, - null, - null, - null); - } - - @Override - public Cursor getReadingListUnfetched(ContentResolver cr) { - return cr.query(mReadingListUriWithProfile, - new String[] { ReadingListItems._ID, ReadingListItems.URL }, - ReadingListItems.CONTENT_STATUS + " = " + ReadingListItems.STATUS_UNFETCHED, - null, - null); - - } - - @Override - public void addReadingListItem(ContentResolver cr, ContentValues values) { - // Check that required fields are present. - for (String field: ReadingListItems.REQUIRED_FIELDS) { - if (!values.containsKey(field)) { - throw new IllegalArgumentException("Missing required field for reading list item: " + field); - } - } - - // Clear delete flag if necessary - values.put(ReadingListItems.IS_DELETED, 0); - - // Restore deleted record if possible - final Uri insertUri = mReadingListUriWithProfile - .buildUpon() - .appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true") - .build(); - - final int updated = cr.update(insertUri, - values, - ReadingListItems.URL + " = ? ", - new String[] { values.getAsString(ReadingListItems.URL) }); - - debug("Updated " + updated + " rows to new modified time."); - } - - @Override - public void updateReadingListItem(ContentResolver cr, ContentValues values) { - if (!values.containsKey(ReadingListItems._ID)) { - throw new IllegalArgumentException("Cannot update reading list item without an ID"); - } - - final int updated = cr.update(mReadingListUriWithProfile, - values, - ReadingListItems._ID + " = ? ", - new String[] { values.getAsString(ReadingListItems._ID) }); - - debug("Updated " + updated + " reading list rows."); - } - - @Override - public void removeReadingListItemWithURL(ContentResolver cr, String uri) { - cr.delete(mReadingListUriWithProfile, ReadingListItems.URL + " = ? ", new String[] { uri }); - } - @Override public void registerBookmarkObserver(ContentResolver cr, ContentObserver observer) { cr.registerContentObserver(mBookmarksUriWithProfile, false, observer); diff --git a/mobile/android/base/db/LocalReadingListAccessor.java b/mobile/android/base/db/LocalReadingListAccessor.java new file mode 100644 index 000000000000..39e4c5cd0a35 --- /dev/null +++ b/mobile/android/base/db/LocalReadingListAccessor.java @@ -0,0 +1,128 @@ +/* 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/. */ + +package org.mozilla.gecko.db; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.ContentObserver; +import android.database.Cursor; +import android.net.Uri; +import android.util.Log; + +public class LocalReadingListAccessor implements ReadingListAccessor { + private static final String LOG_TAG = "GeckoReadingListAcc"; + + private final Uri mReadingListUriWithProfile; + + public LocalReadingListAccessor(final String profile) { + mReadingListUriWithProfile = DBUtils.appendProfile(profile, BrowserContract.ReadingListItems.CONTENT_URI); + } + + @Override + public int getCount(ContentResolver cr) { + final String[] columns = new String[]{BrowserContract.ReadingListItems._ID}; + final Cursor cursor = cr.query(mReadingListUriWithProfile, columns, null, null, null); + int count = 0; + + try { + count = cursor.getCount(); + } finally { + cursor.close(); + } + + Log.d(LOG_TAG, "Got count " + count + " for reading list."); + return count; + } + + @Override + public Cursor getReadingList(ContentResolver cr) { + return cr.query(mReadingListUriWithProfile, + BrowserContract.ReadingListItems.DEFAULT_PROJECTION, + null, + null, + null); + } + + @Override + public Cursor getReadingListUnfetched(ContentResolver cr) { + return cr.query(mReadingListUriWithProfile, + new String[] { BrowserContract.ReadingListItems._ID, BrowserContract.ReadingListItems.URL }, + BrowserContract.ReadingListItems.CONTENT_STATUS + " = " + BrowserContract.ReadingListItems.STATUS_UNFETCHED, + null, + null); + } + + @Override + public boolean isReadingListItem(ContentResolver cr, String uri) { + final Cursor c = cr.query(mReadingListUriWithProfile, + new String[] { BrowserContract.ReadingListItems._ID }, + BrowserContract.ReadingListItems.URL + " = ? ", + new String[] { uri }, + null); + + if (c == null) { + Log.e(LOG_TAG, "Null cursor in isReadingListItem"); + return false; + } + + try { + return c.getCount() > 0; + } finally { + c.close(); + } + } + + + @Override + public void addReadingListItem(ContentResolver cr, ContentValues values) { + // Check that required fields are present. + for (String field: BrowserContract.ReadingListItems.REQUIRED_FIELDS) { + if (!values.containsKey(field)) { + throw new IllegalArgumentException("Missing required field for reading list item: " + field); + } + } + + // Clear delete flag if necessary + values.put(BrowserContract.ReadingListItems.IS_DELETED, 0); + + // Restore deleted record if possible + final Uri insertUri = mReadingListUriWithProfile + .buildUpon() + .appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true") + .build(); + + final int updated = cr.update(insertUri, + values, + BrowserContract.ReadingListItems.URL + " = ? ", + new String[] { values.getAsString(BrowserContract.ReadingListItems.URL) }); + + Log.d(LOG_TAG, "Updated " + updated + " rows to new modified time."); + } + + @Override + public void updateReadingListItem(ContentResolver cr, ContentValues values) { + if (!values.containsKey(BrowserContract.ReadingListItems._ID)) { + throw new IllegalArgumentException("Cannot update reading list item without an ID"); + } + + final int updated = cr.update(mReadingListUriWithProfile, + values, + BrowserContract.ReadingListItems._ID + " = ? ", + new String[] { values.getAsString(BrowserContract.ReadingListItems._ID) }); + + Log.d(LOG_TAG, "Updated " + updated + " reading list rows."); + } + + @Override + public void removeReadingListItemWithURL(ContentResolver cr, String uri) { + cr.delete(mReadingListUriWithProfile, BrowserContract.ReadingListItems.URL + " = ? ", new String[]{uri}); + } + + @Override + public void registerContentObserver(Context context, ContentObserver observer) { + context.getContentResolver().registerContentObserver(mReadingListUriWithProfile, false, observer); + } +} diff --git a/mobile/android/base/db/ReadingListAccessor.java b/mobile/android/base/db/ReadingListAccessor.java new file mode 100644 index 000000000000..1e8197cd3d52 --- /dev/null +++ b/mobile/android/base/db/ReadingListAccessor.java @@ -0,0 +1,32 @@ +/* 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/. */ + +package org.mozilla.gecko.db; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.ContentObserver; +import android.database.Cursor; + +public interface ReadingListAccessor { + /** + * Can return null. + */ + Cursor getReadingList(ContentResolver cr); + + int getCount(ContentResolver cr); + + Cursor getReadingListUnfetched(ContentResolver cr); + + boolean isReadingListItem(ContentResolver cr, String uri); + + void addReadingListItem(ContentResolver cr, ContentValues values); + + void updateReadingListItem(ContentResolver cr, ContentValues values); + + void removeReadingListItemWithURL(ContentResolver cr, String uri); + + void registerContentObserver(Context context, ContentObserver observer); +} diff --git a/mobile/android/base/db/StubBrowserDB.java b/mobile/android/base/db/StubBrowserDB.java index 4b7ee21582e1..b67d483d1d6c 100644 --- a/mobile/android/base/db/StubBrowserDB.java +++ b/mobile/android/base/db/StubBrowserDB.java @@ -26,6 +26,48 @@ import android.database.ContentObserver; import android.database.Cursor; import android.graphics.drawable.BitmapDrawable; +class StubReadingListAccessor implements ReadingListAccessor { + @Override + public Cursor getReadingList(ContentResolver cr) { + return null; + } + + @Override + public int getCount(ContentResolver cr) { + return 0; + } + + @Override + public Cursor getReadingListUnfetched(ContentResolver cr) { + return null; + } + + @Override + public boolean isReadingListItem(ContentResolver cr, String uri) { + return false; + } + + @Override + public void addReadingListItem(ContentResolver cr, ContentValues values) { + + } + + @Override + public void updateReadingListItem(ContentResolver cr, ContentValues values) { + + } + + @Override + public void removeReadingListItemWithURL(ContentResolver cr, String uri) { + + } + + @Override + public void registerContentObserver(Context context, ContentObserver observer) { + + } +} + class StubSearches implements Searches { public StubSearches() { } @@ -91,6 +133,7 @@ public class StubBrowserDB implements BrowserDB { private final StubSearches searches = new StubSearches(); private final StubTabsAccessor tabsAccessor = new StubTabsAccessor(); private final StubURLMetadata urlMetadata = new StubURLMetadata(); + private final StubReadingListAccessor readingListAccessor = new StubReadingListAccessor(); @Override public Searches getSearches() { @@ -107,6 +150,11 @@ public class StubBrowserDB implements BrowserDB { return urlMetadata; } + @Override + public ReadingListAccessor getReadingListAccessor() { + return readingListAccessor; + } + protected static final Integer FAVICON_ID_NOT_FOUND = Integer.MIN_VALUE; public StubBrowserDB(String profile) { diff --git a/mobile/android/base/home/HomeFragment.java b/mobile/android/base/home/HomeFragment.java index 5ceedc84eb92..aeae417df7f4 100644 --- a/mobile/android/base/home/HomeFragment.java +++ b/mobile/android/base/home/HomeFragment.java @@ -363,7 +363,7 @@ public abstract class HomeFragment extends Fragment { break; case READING_LIST: - mDB.removeReadingListItemWithURL(cr, mUrl); + mDB.getReadingListAccessor().removeReadingListItemWithURL(cr, mUrl); GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:Removed", mUrl)); break; diff --git a/mobile/android/base/home/ReadingListPanel.java b/mobile/android/base/home/ReadingListPanel.java index f411ad57e46c..c8524d33e612 100644 --- a/mobile/android/base/home/ReadingListPanel.java +++ b/mobile/android/base/home/ReadingListPanel.java @@ -15,6 +15,7 @@ import org.mozilla.gecko.TelemetryContract; import org.mozilla.gecko.db.BrowserContract.ReadingListItems; import org.mozilla.gecko.db.BrowserContract.URLColumns; import org.mozilla.gecko.db.BrowserDB; +import org.mozilla.gecko.db.ReadingListAccessor; import org.mozilla.gecko.home.HomeContextMenuInfo.RemoveItemType; import org.mozilla.gecko.home.HomePager.OnUrlOpenListener; @@ -164,16 +165,16 @@ public class ReadingListPanel extends HomeFragment { * Cursor loader for the list of reading list items. */ private static class ReadingListLoader extends SimpleCursorLoader { - private final BrowserDB mDB; + private final ReadingListAccessor accessor; public ReadingListLoader(Context context) { super(context); - mDB = GeckoProfile.get(context).getDB(); + accessor = GeckoProfile.get(context).getDB().getReadingListAccessor(); } @Override public Cursor loadCursor() { - return mDB.getReadingList(getContext().getContentResolver()); + return accessor.getReadingList(getContext().getContentResolver()); } } diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 744e5d18dd70..80d35925df78 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -159,12 +159,14 @@ gbjar.sources += [ 'db/FormHistoryProvider.java', 'db/HomeProvider.java', 'db/LocalBrowserDB.java', + 'db/LocalReadingListAccessor.java', 'db/LocalSearches.java', 'db/LocalTabsAccessor.java', 'db/LocalURLMetadata.java', 'db/PasswordsProvider.java', 'db/PerProfileDatabaseProvider.java', 'db/PerProfileDatabases.java', + 'db/ReadingListAccessor.java', 'db/ReadingListProvider.java', 'db/RemoteClient.java', 'db/RemoteTab.java', diff --git a/mobile/android/base/overlays/service/sharemethods/AddToReadingList.java b/mobile/android/base/overlays/service/sharemethods/AddToReadingList.java index b445b3c57ac6..c4740cb9123c 100644 --- a/mobile/android/base/overlays/service/sharemethods/AddToReadingList.java +++ b/mobile/android/base/overlays/service/sharemethods/AddToReadingList.java @@ -34,7 +34,7 @@ public class AddToReadingList extends ShareMethod { values.put(Bookmarks.TITLE, shareData.title); values.put(Bookmarks.URL, shareData.url); - browserDB.addReadingListItem(resolver, values); + browserDB.getReadingListAccessor().addReadingListItem(resolver, values); return Result.SUCCESS; } diff --git a/mobile/android/base/overlays/ui/ShareDialog.java b/mobile/android/base/overlays/ui/ShareDialog.java index 70e6e07780be..b7c696e390d9 100644 --- a/mobile/android/base/overlays/ui/ShareDialog.java +++ b/mobile/android/base/overlays/ui/ShareDialog.java @@ -261,7 +261,7 @@ public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabT final ContentResolver contentResolver = getApplicationContext().getContentResolver(); isBookmark = browserDB.isBookmark(contentResolver, pageURL); - isReadingListItem = browserDB.isReadingListItem(contentResolver, pageURL); + isReadingListItem = browserDB.getReadingListAccessor().isReadingListItem(contentResolver, pageURL); return null; } From dc611f6b0a861d2210de18e3559ea894494f3ed3 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 10 Feb 2015 16:42:39 -0800 Subject: [PATCH 17/33] Backed out changeset ea1ed091f31e (bug 1126240) for android build failures --HG-- extra : rebase_source : 604d42d88e5221777ea441da8aed6199ae523b26 --- mobile/android/base/BrowserLocaleManager.java | 6 ++++- mobile/android/base/db/LocalBrowserDB.java | 11 +++++--- mobile/android/base/favicons/Favicons.java | 5 +++- mobile/android/base/tests/testJarReader.java | 7 ----- mobile/android/base/util/GeckoJarReader.java | 21 --------------- .../search/providers/SearchEngineManager.java | 27 ++++++++++++------- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/mobile/android/base/BrowserLocaleManager.java b/mobile/android/base/BrowserLocaleManager.java index 86087fdc78fe..045e01d28399 100644 --- a/mobile/android/base/BrowserLocaleManager.java +++ b/mobile/android/base/BrowserLocaleManager.java @@ -398,7 +398,11 @@ public class BrowserLocaleManager implements LocaleManager { */ public static Collection getPackagedLocaleTags(final Context context) { final String resPath = "res/multilocale.json"; - final String jarURL = GeckoJarReader.getJarURL(context, resPath); + final String apkPath = context.getPackageResourcePath(); + + final String jarURL = "jar:jar:" + new File(apkPath).toURI() + "!/" + + AppConstants.OMNIJAR_NAME + "!/" + + resPath; final String contents = GeckoJarReader.getText(jarURL); if (contents == null) { diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index e09b3732a2ea..1909cddb4ca5 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -473,13 +473,18 @@ public class LocalBrowserDB implements BrowserDB { * compatible with the favicon decoder (most probably a PNG or ICO file). */ private static ConsumedInputStream getDefaultFaviconFromPath(Context context, String name) { - final int faviconId = getFaviconId(name); + int faviconId = getFaviconId(name); if (faviconId == FAVICON_ID_NOT_FOUND) { return null; } - final String bitmapPath = GeckoJarReader.getJarURL(context, context.getString(faviconId)); - final InputStream iStream = GeckoJarReader.getStream(bitmapPath); + String path = context.getString(faviconId); + + String apkPath = context.getPackageResourcePath(); + File apkFile = new File(apkPath); + String bitmapPath = "jar:jar:" + apkFile.toURI() + "!/" + AppConstants.OMNIJAR_NAME + "!/" + path; + + InputStream iStream = GeckoJarReader.getStream(bitmapPath); return IOUtils.readFully(iStream, DEFAULT_FAVICON_BUFFER_SIZE); } diff --git a/mobile/android/base/favicons/Favicons.java b/mobile/android/base/favicons/Favicons.java index 8ff6ca342456..3c467032f57c 100644 --- a/mobile/android/base/favicons/Favicons.java +++ b/mobile/android/base/favicons/Favicons.java @@ -498,7 +498,10 @@ public class Favicons { * "jar:jar:file:///data/app/org.mozilla.firefox-1.apk!/assets/omni.ja!/chrome/chrome/content/branding/favicon64.png" */ private static String getBrandingBitmapPath(Context context, String name) { - return GeckoJarReader.getJarURL(context, "chrome/chrome/content/branding/" + name); + final String apkPath = context.getPackageResourcePath(); + return "jar:jar:" + new File(apkPath).toURI() + "!/" + + AppConstants.OMNIJAR_NAME + "!/" + + "chrome/chrome/content/branding/" + name; } private static Bitmap loadBrandingBitmap(Context context, String name) { diff --git a/mobile/android/base/tests/testJarReader.java b/mobile/android/base/tests/testJarReader.java index 0b712057cd95..478b099a2f6c 100644 --- a/mobile/android/base/tests/testJarReader.java +++ b/mobile/android/base/tests/testJarReader.java @@ -14,13 +14,6 @@ import org.mozilla.gecko.util.GeckoJarReader; * as loading some invalid jar urls. */ public class testJarReader extends BaseTest { - public void testGetJarURL() { - // Invalid characters are escaped. - final String s = GeckoJarReader.computeJarURI("some[1].apk", "something/else"); - mAsserter.ok(s.contains("["), "Illegal characters are escaped away."); - mAsserter.ok(s.toLowerCase().contains("%2f"), "Path characters aren't escaped."); - } - public void testJarReader() { String appPath = getActivity().getApplication().getPackageResourcePath(); mAsserter.isnot(appPath, null, "getPackageResourcePath is non-null"); diff --git a/mobile/android/base/util/GeckoJarReader.java b/mobile/android/base/util/GeckoJarReader.java index 828d7cf7a432..e10063f4a01e 100644 --- a/mobile/android/base/util/GeckoJarReader.java +++ b/mobile/android/base/util/GeckoJarReader.java @@ -4,8 +4,6 @@ package org.mozilla.gecko.util; -import android.content.Context; -import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.mozglue.NativeZip; import android.content.res.Resources; @@ -15,7 +13,6 @@ import android.util.Log; import org.mozilla.gecko.mozglue.RobocopTarget; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -174,22 +171,4 @@ public final class GeckoJarReader { return results; } } - - public static String getJarURL(Context context, String pathInsideJAR) { - // We need to encode the package resource path, because it might contain illegal characters. For example: - // /mnt/asec2/[2]org.mozilla.fennec-1/pkg.apk - // The round-trip through a URI does this for us. - final String resourcePath = context.getPackageResourcePath(); - return computeJarURI(resourcePath, pathInsideJAR); - } - - /** - * Encodes its resource path correctly. - */ - public static String computeJarURI(String resourcePath, String pathInsideJAR) { - final String resURI = new File(resourcePath).toURI().toString(); - - // TODO: do we need to encode the file path, too? - return "jar:jar:" + resURI + "!/" + AppConstants.OMNIJAR_NAME + "!/" + pathInsideJAR; - } } diff --git a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java index 465c78dfa61a..62e2e619fba0 100644 --- a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java +++ b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java @@ -8,6 +8,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; import android.util.Log; + import org.json.JSONException; import org.json.JSONObject; import org.mozilla.gecko.AppConstants; @@ -15,18 +16,20 @@ import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.GeckoSharedPrefs; import org.mozilla.gecko.Locales; import org.mozilla.gecko.R; -import org.mozilla.gecko.distribution.Distribution; import org.mozilla.gecko.util.FileUtils; import org.mozilla.gecko.util.GeckoJarReader; import org.mozilla.gecko.util.HardwareUtils; import org.mozilla.gecko.util.RawResource; import org.mozilla.gecko.util.ThreadUtils; +import org.mozilla.gecko.distribution.Distribution; +import org.mozilla.search.Constants; import org.xmlpull.v1.XmlPullParserException; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -34,6 +37,8 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; public class SearchEngineManager implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -527,7 +532,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return engine; } } catch (IOException e) { - Log.e(LOG_TAG, "Error creating search engine from name: " + name, e); + Log.e(LOG_TAG, "Error creating earch engine from name: " + name, e); } } return null; @@ -568,7 +573,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // First, try a file path for the full locale. final String languageTag = Locales.getLanguageTag(locale); - String url = getSearchPluginsJarURL(context, languageTag, fileName); + String url = getSearchPluginsJarURL(languageTag, fileName); InputStream in = GeckoJarReader.getStream(url); if (in != null) { @@ -578,7 +583,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // If that doesn't work, try a file path for just the language. final String language = Locales.getLanguage(locale); if (!languageTag.equals(language)) { - url = getSearchPluginsJarURL(context, language, fileName); + url = getSearchPluginsJarURL(language, fileName); in = GeckoJarReader.getStream(url); if (in != null) { return in; @@ -586,7 +591,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference } // Finally, fall back to default locale defined in chrome registry. - url = getSearchPluginsJarURL(context, getFallbackLocale(), fileName); + url = getSearchPluginsJarURL(getFallbackLocale(), fileName); return GeckoJarReader.getStream(url); } @@ -601,7 +606,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return fallbackLocale; } - final InputStream in = GeckoJarReader.getStream(GeckoJarReader.getJarURL(context, "chrome/chrome.manifest")); + final InputStream in = GeckoJarReader.getStream(getJarURL("!/chrome/chrome.manifest")); final BufferedReader br = getBufferedReader(in); try { @@ -633,9 +638,13 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference * @param fileName The name of the file to read. * @return URL for jar file. */ - private static String getSearchPluginsJarURL(Context context, String locale, String fileName) { - final String path = "chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName; - return GeckoJarReader.getJarURL(context, path); + private String getSearchPluginsJarURL(String locale, String fileName) { + final String path = "!/chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName; + return getJarURL(path); + } + + private String getJarURL(String path) { + return "jar:jar:file://" + context.getPackageResourcePath() + "!/" + AppConstants.OMNIJAR_NAME + path; } private BufferedReader getBufferedReader(InputStream in) { From d97cea2a4a8f5ccfaa65666c5cb914fe79e66e95 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 10 Feb 2015 16:11:24 -0800 Subject: [PATCH 18/33] Bug 1126240 - Correctly encode APK paths in SearchEngineManager. r=margaret This is the approach we already take everywhere else we make a jar:jar: URI. I've unified those places into GeckoJarReader, cleaned up imports, fixed a typo, and wrote a trivial test for this case. I made a few utility methods static to facilitate testing and future refactoring. --- mobile/android/base/BrowserLocaleManager.java | 6 +---- mobile/android/base/db/LocalBrowserDB.java | 11 +++----- mobile/android/base/favicons/Favicons.java | 5 +--- mobile/android/base/tests/testJarReader.java | 7 +++++ mobile/android/base/util/GeckoJarReader.java | 22 +++++++++++++++ .../search/providers/SearchEngineManager.java | 27 +++++++------------ 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/mobile/android/base/BrowserLocaleManager.java b/mobile/android/base/BrowserLocaleManager.java index 045e01d28399..86087fdc78fe 100644 --- a/mobile/android/base/BrowserLocaleManager.java +++ b/mobile/android/base/BrowserLocaleManager.java @@ -398,11 +398,7 @@ public class BrowserLocaleManager implements LocaleManager { */ public static Collection getPackagedLocaleTags(final Context context) { final String resPath = "res/multilocale.json"; - final String apkPath = context.getPackageResourcePath(); - - final String jarURL = "jar:jar:" + new File(apkPath).toURI() + "!/" + - AppConstants.OMNIJAR_NAME + "!/" + - resPath; + final String jarURL = GeckoJarReader.getJarURL(context, resPath); final String contents = GeckoJarReader.getText(jarURL); if (contents == null) { diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index 1909cddb4ca5..e09b3732a2ea 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -473,18 +473,13 @@ public class LocalBrowserDB implements BrowserDB { * compatible with the favicon decoder (most probably a PNG or ICO file). */ private static ConsumedInputStream getDefaultFaviconFromPath(Context context, String name) { - int faviconId = getFaviconId(name); + final int faviconId = getFaviconId(name); if (faviconId == FAVICON_ID_NOT_FOUND) { return null; } - String path = context.getString(faviconId); - - String apkPath = context.getPackageResourcePath(); - File apkFile = new File(apkPath); - String bitmapPath = "jar:jar:" + apkFile.toURI() + "!/" + AppConstants.OMNIJAR_NAME + "!/" + path; - - InputStream iStream = GeckoJarReader.getStream(bitmapPath); + final String bitmapPath = GeckoJarReader.getJarURL(context, context.getString(faviconId)); + final InputStream iStream = GeckoJarReader.getStream(bitmapPath); return IOUtils.readFully(iStream, DEFAULT_FAVICON_BUFFER_SIZE); } diff --git a/mobile/android/base/favicons/Favicons.java b/mobile/android/base/favicons/Favicons.java index 3c467032f57c..8ff6ca342456 100644 --- a/mobile/android/base/favicons/Favicons.java +++ b/mobile/android/base/favicons/Favicons.java @@ -498,10 +498,7 @@ public class Favicons { * "jar:jar:file:///data/app/org.mozilla.firefox-1.apk!/assets/omni.ja!/chrome/chrome/content/branding/favicon64.png" */ private static String getBrandingBitmapPath(Context context, String name) { - final String apkPath = context.getPackageResourcePath(); - return "jar:jar:" + new File(apkPath).toURI() + "!/" + - AppConstants.OMNIJAR_NAME + "!/" + - "chrome/chrome/content/branding/" + name; + return GeckoJarReader.getJarURL(context, "chrome/chrome/content/branding/" + name); } private static Bitmap loadBrandingBitmap(Context context, String name) { diff --git a/mobile/android/base/tests/testJarReader.java b/mobile/android/base/tests/testJarReader.java index 478b099a2f6c..82d82fbaa253 100644 --- a/mobile/android/base/tests/testJarReader.java +++ b/mobile/android/base/tests/testJarReader.java @@ -14,6 +14,13 @@ import org.mozilla.gecko.util.GeckoJarReader; * as loading some invalid jar urls. */ public class testJarReader extends BaseTest { + public void testGetJarURL() { + // Invalid characters are escaped. + final String s = GeckoJarReader.computeJarURI("some[1].apk", "something/else"); + mAsserter.ok(!s.contains("["), "Illegal characters are escaped away.", null); + mAsserter.ok(!s.toLowerCase().contains("%2f"), "Path characters aren't escaped.", null); + } + public void testJarReader() { String appPath = getActivity().getApplication().getPackageResourcePath(); mAsserter.isnot(appPath, null, "getPackageResourcePath is non-null"); diff --git a/mobile/android/base/util/GeckoJarReader.java b/mobile/android/base/util/GeckoJarReader.java index e10063f4a01e..b690e06a8a44 100644 --- a/mobile/android/base/util/GeckoJarReader.java +++ b/mobile/android/base/util/GeckoJarReader.java @@ -4,6 +4,8 @@ package org.mozilla.gecko.util; +import android.content.Context; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.mozglue.NativeZip; import android.content.res.Resources; @@ -13,6 +15,7 @@ import android.util.Log; import org.mozilla.gecko.mozglue.RobocopTarget; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -171,4 +174,23 @@ public final class GeckoJarReader { return results; } } + + public static String getJarURL(Context context, String pathInsideJAR) { + // We need to encode the package resource path, because it might contain illegal characters. For example: + // /mnt/asec2/[2]org.mozilla.fennec-1/pkg.apk + // The round-trip through a URI does this for us. + final String resourcePath = context.getPackageResourcePath(); + return computeJarURI(resourcePath, pathInsideJAR); + } + + /** + * Encodes its resource path correctly. + */ + @RobocopTarget + public static String computeJarURI(String resourcePath, String pathInsideJAR) { + final String resURI = new File(resourcePath).toURI().toString(); + + // TODO: do we need to encode the file path, too? + return "jar:jar:" + resURI + "!/" + AppConstants.OMNIJAR_NAME + "!/" + pathInsideJAR; + } } diff --git a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java index 62e2e619fba0..465c78dfa61a 100644 --- a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java +++ b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java @@ -8,7 +8,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; import android.util.Log; - import org.json.JSONException; import org.json.JSONObject; import org.mozilla.gecko.AppConstants; @@ -16,20 +15,18 @@ import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.GeckoSharedPrefs; import org.mozilla.gecko.Locales; import org.mozilla.gecko.R; +import org.mozilla.gecko.distribution.Distribution; import org.mozilla.gecko.util.FileUtils; import org.mozilla.gecko.util.GeckoJarReader; import org.mozilla.gecko.util.HardwareUtils; import org.mozilla.gecko.util.RawResource; import org.mozilla.gecko.util.ThreadUtils; -import org.mozilla.gecko.distribution.Distribution; -import org.mozilla.search.Constants; import org.xmlpull.v1.XmlPullParserException; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -37,8 +34,6 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; public class SearchEngineManager implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -532,7 +527,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return engine; } } catch (IOException e) { - Log.e(LOG_TAG, "Error creating earch engine from name: " + name, e); + Log.e(LOG_TAG, "Error creating search engine from name: " + name, e); } } return null; @@ -573,7 +568,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // First, try a file path for the full locale. final String languageTag = Locales.getLanguageTag(locale); - String url = getSearchPluginsJarURL(languageTag, fileName); + String url = getSearchPluginsJarURL(context, languageTag, fileName); InputStream in = GeckoJarReader.getStream(url); if (in != null) { @@ -583,7 +578,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference // If that doesn't work, try a file path for just the language. final String language = Locales.getLanguage(locale); if (!languageTag.equals(language)) { - url = getSearchPluginsJarURL(language, fileName); + url = getSearchPluginsJarURL(context, language, fileName); in = GeckoJarReader.getStream(url); if (in != null) { return in; @@ -591,7 +586,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference } // Finally, fall back to default locale defined in chrome registry. - url = getSearchPluginsJarURL(getFallbackLocale(), fileName); + url = getSearchPluginsJarURL(context, getFallbackLocale(), fileName); return GeckoJarReader.getStream(url); } @@ -606,7 +601,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference return fallbackLocale; } - final InputStream in = GeckoJarReader.getStream(getJarURL("!/chrome/chrome.manifest")); + final InputStream in = GeckoJarReader.getStream(GeckoJarReader.getJarURL(context, "chrome/chrome.manifest")); final BufferedReader br = getBufferedReader(in); try { @@ -638,13 +633,9 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference * @param fileName The name of the file to read. * @return URL for jar file. */ - private String getSearchPluginsJarURL(String locale, String fileName) { - final String path = "!/chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName; - return getJarURL(path); - } - - private String getJarURL(String path) { - return "jar:jar:file://" + context.getPackageResourcePath() + "!/" + AppConstants.OMNIJAR_NAME + path; + private static String getSearchPluginsJarURL(Context context, String locale, String fileName) { + final String path = "chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName; + return GeckoJarReader.getJarURL(context, path); } private BufferedReader getBufferedReader(InputStream in) { From 9e299b362a66b4a3113af4aad51779c825772387 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 17:25:24 -0800 Subject: [PATCH 19/33] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/33da6ab6711e Author: Sam Foster Desc: Merge pull request #28076 from sfoster/ftu-tutorial-video-update-bug-1129108 Bug 1129108 - Updated homescreen video assets via epang. r=me ======== https://hg.mozilla.org/integration/gaia-central/rev/7e7718f4f10a Author: Sam Foster Desc: Bug 1129108 - Updated homescreen video via epang. r=me --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index b0be32725b0f..6e12619a0d7b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "7efd55ffbbaf3b24fabe53717c354aa03edc8bac", + "git_revision": "2bef75b40bc570400f7d9180bea615148aca49a6", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "61753609a6acdd8efd1554db5c6db6ea523070f5", + "revision": "33da6ab6711ea7571869752f0c126b70c49c0215", "repo_path": "integration/gaia-central" } From 1046549c50deea7c49bbe9f8ec4c4659c874d30c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 17:27:54 -0800 Subject: [PATCH 20/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index d9f1eb0f0f54..6a2acd270673 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 51a2e81de6bd..280cb855f84f 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6f0044351bb6..48f5e3df566c 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 706b3a22db51..7de39f03c431 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 51a2e81de6bd..280cb855f84f 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 7916e6204298..974845fdb99b 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index e90d95cdfa39..553ca3a3a0c0 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 0813ea4e4219..0fb6309ab89e 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index e2eda0d2b0d1..2098ff823f79 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From f35b097ac20c840259948324d4f352765ab5f3de Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 19:09:15 -0800 Subject: [PATCH 21/33] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/455698f145c9 Author: John Hu Desc: Merge pull request #27868 from sean2449/Bug_1122428 Bug 1122428 - [Stingray] UI-Transition - Global Activity transition enter/exit, r=johnhu ======== https://hg.mozilla.org/integration/gaia-central/rev/5692363c5151 Author: Sung Chiu Desc: Bug 1122428 - [Stingray] UI-Transition - Global Activity transition enter / exit --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 6e12619a0d7b..e49f7a087a7e 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "2bef75b40bc570400f7d9180bea615148aca49a6", + "git_revision": "2461c572b5587f67a120a541de92bcce078ed6c3", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "33da6ab6711ea7571869752f0c126b70c49c0215", + "revision": "455698f145c978f51567a09bdb671a58ceea2c48", "repo_path": "integration/gaia-central" } From 576f9ac0aa3988d04c5ac9df6972c6233615256d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 19:12:11 -0800 Subject: [PATCH 22/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 6a2acd270673..6bf6f4982a91 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 280cb855f84f..84c8b4f413e5 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 48f5e3df566c..b6297e2496c4 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7de39f03c431..8292f4b33706 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 280cb855f84f..84c8b4f413e5 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 974845fdb99b..347d3e0188e4 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 553ca3a3a0c0..88be1026eb09 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 0fb6309ab89e..b6aa5702aa87 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 2098ff823f79..5bf90f2ac32c 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 678bb6d3716946051dc574a28102a179e19c9141 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 19:20:28 -0800 Subject: [PATCH 23/33] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/769403f166d4 Author: gasolin Desc: Merge pull request #28057 from gasolin/issue-1114476 Bug 1114476 - rename privacy panel to privacy controls, r=arthur,marta ======== https://hg.mozilla.org/integration/gaia-central/rev/a413fdc6f3ce Author: gasolin Desc: Bug 1114476 - rename privacy panel to privacy controls ======== https://hg.mozilla.org/integration/gaia-central/rev/db353dd92e19 Author: Arthur Chen Desc: Merge pull request #28021 from crh0716/1129630 Bug 1129630 - Add RTL support to the date picker r=alive ======== https://hg.mozilla.org/integration/gaia-central/rev/e4f1f867f7e1 Author: Arthur Chen Desc: Bug 1129630 - Add RTL support to the date picker --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index e49f7a087a7e..ac194d8d3044 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "2461c572b5587f67a120a541de92bcce078ed6c3", + "git_revision": "b077b97eead06bac34a7ba95eb2d77650a97ee2b", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "455698f145c978f51567a09bdb671a58ceea2c48", + "revision": "769403f166d40bac99ff0486381a55edaec5968d", "repo_path": "integration/gaia-central" } From 4e1bc4d42d1a34e6124409789a716440d28ba2a6 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 19:21:57 -0800 Subject: [PATCH 24/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 6bf6f4982a91..65e5b8bc1446 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 84c8b4f413e5..287696b14e4e 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index b6297e2496c4..01cb17b397cc 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 8292f4b33706..740f321b6ffe 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 84c8b4f413e5..287696b14e4e 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 347d3e0188e4..84f4dcc27885 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 88be1026eb09..9e7447d1cda5 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index b6aa5702aa87..08a3df26e81d 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 5bf90f2ac32c..17a2ce63d605 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 2eda48951a15fca959ca03324f60f424f84ec1fb Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 19:55:08 -0800 Subject: [PATCH 25/33] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/beea810aba49 Author: autolander Desc: Bug 1130317 - merge pull request #28052 from mnjul:bug_1130317_dict_blob_predetermine_length to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/b746bccf6af9 Author: John Lu [:mnjul] Desc: Bug 1130317 - Pre-determine length of Uint8Array of Keyboard user dictionary dict blob - The total byte length of serialized nodes can be inferred when filling each node's offset information, and is subsequently combined with header & character table size to initialize the Uint8Array total length. - We thus avoid pushing to a JS array one-byte-by-one-byte and convert the array to Uint8Array, which should lead to better performance. --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ac194d8d3044..242d97647670 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "b077b97eead06bac34a7ba95eb2d77650a97ee2b", + "git_revision": "3b20ace1a5456f91e750ed2a92db0b7e37098763", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "769403f166d40bac99ff0486381a55edaec5968d", + "revision": "beea810aba497bde0dfeca1f9f627f5869830b08", "repo_path": "integration/gaia-central" } From 15d98cb484e0d5a619faaeee7c49e8585695bec1 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 19:57:31 -0800 Subject: [PATCH 26/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 65e5b8bc1446..7dd28b4ccc0c 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 287696b14e4e..f61d5200f7b5 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 01cb17b397cc..f97aa3d121e7 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 740f321b6ffe..a46bc2912b88 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 287696b14e4e..f61d5200f7b5 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 84f4dcc27885..5d1de9aa870a 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 9e7447d1cda5..a2c28c83f415 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 08a3df26e81d..f02b06ad482a 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 17a2ce63d605..5a6e12212bd2 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From a6726bcd1be3e6659d1ae3a54899e454c548a673 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 20:14:05 -0800 Subject: [PATCH 27/33] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/141032bd342a Author: autolander Desc: Bug 1130479 - merge pull request #28026 from millermedeiros:1130479-rtl-swipe-month-view to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/7e61b9d74742 Author: Miller Medeiros Desc: Bug 1130479 - [Calendar][RTL] swipe direction should be mirrored on month view for RTL locales --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 242d97647670..c1f153621d89 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "3b20ace1a5456f91e750ed2a92db0b7e37098763", + "git_revision": "60012edd27515175f56612b2b716d8a664a048d1", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "beea810aba497bde0dfeca1f9f627f5869830b08", + "revision": "141032bd342a53d951361fd11c5686263e4c8ee4", "repo_path": "integration/gaia-central" } From 07fc27d7261a94334bbdf811615b76e17e760233 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 20:16:27 -0800 Subject: [PATCH 28/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 7dd28b4ccc0c..365c057ad23e 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f61d5200f7b5..0548a1a6fedb 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index f97aa3d121e7..5c2edb040e70 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index a46bc2912b88..8da17dd1bdbe 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f61d5200f7b5..0548a1a6fedb 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 5d1de9aa870a..8d0ffe1c068b 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index a2c28c83f415..5015741eef2f 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index f02b06ad482a..27160568ad27 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 5a6e12212bd2..4856989b9a4f 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 86fb7a67be6778b79a6482bd5981d61db7f8b8ad Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 22:35:20 -0800 Subject: [PATCH 29/33] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/e6a1cfc70305 Author: John Hu Desc: Merge pull request #28064 from sean2449/Bug_1130250 Bug 1130250 - [Stingray][AppDeck] The focused button at bottom the should be a complete circle, r=johnhu, r=dwi2 ======== https://hg.mozilla.org/integration/gaia-central/rev/a472262ac31a Author: Sung Chiu Desc: Bug 1130250 - [Demo][Stingray] The bottom app that you selected should be a complete circle ======== https://hg.mozilla.org/integration/gaia-central/rev/d87284aa9f02 Author: Timothy Guan-tin Chien Desc: Merge pull request #27951 from timdream/bug1128053 Bug 1128053, revert bug 1085233 ======== https://hg.mozilla.org/integration/gaia-central/rev/f96c97ff6367 Author: Timothy Guan-tin Chien Desc: Revert "Merge pull request #25305 from timdream/value-selector-focus" This reverts commit 47faa4651f8feb11152ef475850cc9641fd5cbeb, reversing changes made to 4c7e1e5f68ec57241d488568080732b318d652f5. Conflicts: build/jshint/xfail.list --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index c1f153621d89..f838dd980d53 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "60012edd27515175f56612b2b716d8a664a048d1", + "git_revision": "462a2ef9e98134255c144e373c7392440e3ee03b", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "141032bd342a53d951361fd11c5686263e4c8ee4", + "revision": "e6a1cfc70305b3695b694d7e66b03c51f2a45b1f", "repo_path": "integration/gaia-central" } From ce7fa9dee3c24f9eab592cc0e8f8f77109021454 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Tue, 10 Feb 2015 22:36:48 -0800 Subject: [PATCH 30/33] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 365c057ad23e..86c5a6794905 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 0548a1a6fedb..d360895364f2 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 5c2edb040e70..ab8764717a85 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 8da17dd1bdbe..9f018b3a646e 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 0548a1a6fedb..d360895364f2 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 8d0ffe1c068b..645b372c0c28 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 5015741eef2f..e5a01d4c7743 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 27160568ad27..c81e16ab2842 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 4856989b9a4f..13e243d9dcdb 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From ca6e00273fc5df46c84746dddeb7a2bb9a196606 Mon Sep 17 00:00:00 2001 From: Jessica Jong Date: Wed, 11 Feb 2015 16:01:08 +0800 Subject: [PATCH 31/33] Bug 973543 - Part 1: add reference counting to added routes. r=echen --- dom/system/gonk/NetworkManager.js | 174 ++++++++++++++++++++++++++---- dom/system/gonk/NetworkService.js | 131 ++++++++++++++++++++-- dom/system/gonk/NetworkUtils.cpp | 5 + 3 files changed, 280 insertions(+), 30 deletions(-) diff --git a/dom/system/gonk/NetworkManager.js b/dom/system/gonk/NetworkManager.js index 5c8f9ac2fcf2..88f3d3ea4b7b 100644 --- a/dom/system/gonk/NetworkManager.js +++ b/dom/system/gonk/NetworkManager.js @@ -134,12 +134,51 @@ function defineLazyRegExp(obj, name, pattern) { }); } +function NetworkInterfaceLinks() +{ + this.resetLinks(); +} +NetworkInterfaceLinks.prototype = { + linkRoutes: null, + gateways: null, + interfaceName: null, + extraRoutes: null, + + setLinks: function(linkRoutes, gateways, interfaceName) { + this.linkRoutes = linkRoutes; + this.gateways = gateways; + this.interfaceName = interfaceName; + }, + + resetLinks: function() { + this.linkRoutes = []; + this.gateways = []; + this.interfaceName = ""; + this.extraRoutes = []; + }, + + compareGateways: function(gateways) { + if (this.gateways.length != gateways.length) { + return false; + } + + for (let i = 0; i < this.gateways.length; i++) { + if (this.gateways[i] != gateways[i]) { + return false; + } + } + + return true; + } +}; + /** * This component watches for network interfaces changing state and then * adjusts routes etc. accordingly. */ function NetworkManager() { this.networkInterfaces = {}; + this.networkInterfaceLinks = {}; Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false); Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false); @@ -303,6 +342,7 @@ NetworkManager.prototype = { Cr.NS_ERROR_INVALID_ARG); } this.networkInterfaces[networkId] = network; + this.networkInterfaceLinks[networkId] = new NetworkInterfaceLinks(); if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) { debug("Force setting " + SETTINGS_DUN_REQUIRED + " to true."); @@ -320,7 +360,10 @@ NetworkManager.prototype = { for (let i = 0; i < length; i++) { debug('Adding subnet routes: ' + ips.value[i] + '/' + prefixLengths.value[i]); gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD, - network.name, ips.value[i], prefixLengths.value[i]); + network.name, ips.value[i], prefixLengths.value[i]) + .catch((aError) => { + debug("_addSubnetRoutes error: " + aError); + }); } }, @@ -346,8 +389,16 @@ NetworkManager.prototype = { gNetworkService.createNetwork(network.name, () => { // Add host route for data calls if (this.isNetworkTypeMobile(network.type)) { - gNetworkService.removeHostRoutes(network.name); - this.setHostRoutes(network); + let currentInterfaceLinks = this.networkInterfaceLinks[networkId]; + let newLinkRoutes = network.getDnses().concat(network.httpProxyHost); + // If gateways have changed, remove all old routes first. + this._handleGateways(networkId, network.getGateways()) + .then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes, + newLinkRoutes, + network.getGateways(), network.name)) + .then(() => currentInterfaceLinks.setLinks(newLinkRoutes, + network.getGateways(), + network.name)); } // Remove pre-created default route and let setAndConfigureActive() @@ -386,7 +437,7 @@ NetworkManager.prototype = { case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED: // Remove host route for data calls if (this.isNetworkTypeMobile(network.type)) { - this.removeHostRoutes(network); + this._cleanupAllHostRoutes(networkId); } // Remove secondary default route for dun. if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) { @@ -435,6 +486,13 @@ NetworkManager.prototype = { throw Components.Exception("No network with that type registered.", Cr.NS_ERROR_INVALID_ARG); } + + // This is for in case a network gets unregistered without being + // DISCONNECTED. + if (this.isNetworkTypeMobile(network.type)) { + this._cleanupAllHostRoutes(networkId); + } + delete this.networkInterfaces[networkId]; if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) { @@ -450,6 +508,8 @@ NetworkManager.prototype = { networkInterfaces: null, + networkInterfaceLinks: null, + _dataDefaultServiceId: null, _preferredNetworkType: DEFAULT_PREFERRED_NETWORK_TYPE, @@ -477,7 +537,24 @@ NetworkManager.prototype = { this.setAndConfigureActive(); }, - _updateRoutes: function(doAdd, ipAddresses, networkName, gateways) { + _updateRoutes: function(oldLinks, newLinks, gateways, interfaceName) { + // Returns items that are in base but not in target. + function getDifference(base, target) { + return base.filter(function(i) { return target.indexOf(i) < 0; }); + } + + let addedLinks = getDifference(newLinks, oldLinks); + let removedLinks = getDifference(oldLinks, newLinks); + + if (addedLinks.length === 0 && removedLinks.length === 0) { + return Promise.resolve(); + } + + return this._setHostRoutes(false, removedLinks, interfaceName, gateways) + .then(this._setHostRoutes(true, addedLinks, interfaceName, gateways)); + }, + + _setHostRoutes: function(doAdd, ipAddresses, networkName, gateways) { let getMaxPrefixLength = (aIp) => { return aIp.match(this.REGEXP_IPV4) ? IPV4_MAX_PREFIX_LENGTH : IPV6_MAX_PREFIX_LENGTH; } @@ -517,10 +594,20 @@ NetworkManager.prototype = { } return this.resolveHostname(network, host) - .then((ipAddresses) => this._updateRoutes(true, - ipAddresses, - network.name, - network.getGateways())); + .then((ipAddresses) => { + let promises = []; + let networkId = this.getNetworkId(network); + + ipAddresses.forEach((aIpAddress) => { + let promise = + this._setHostRoutes(true, [aIpAddress], network.name, network.getGateways()) + .then(() => this.networkInterfaceLinks[networkId].extraRoutes.push(aIpAddress)); + + promises.push(promise); + }); + + return Promise.all(promises); + }); }, removeHostRoute: function(network, host) { @@ -529,10 +616,29 @@ NetworkManager.prototype = { } return this.resolveHostname(network, host) - .then((ipAddresses) => this._updateRoutes(false, - ipAddresses, - network.name, - network.getGateways())); + .then((ipAddresses) => { + let promises = []; + let networkId = this.getNetworkId(network); + + ipAddresses.forEach((aIpAddress) => { + let found = this.networkInterfaceLinks[networkId].extraRoutes.indexOf(aIpAddress); + if (found < 0) { + return; // continue + } + + let promise = + this._setHostRoutes(false, [aIpAddress], network.name, network.getGateways()) + .then(() => { + this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1); + }, () => { + // We should remove it even if the operation failed. + this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1); + }); + promises.push(promise); + }); + + return Promise.all(promises); + }); }, isNetworkTypeSecondaryMobile: function(type) { @@ -547,16 +653,46 @@ NetworkManager.prototype = { this.isNetworkTypeSecondaryMobile(type)); }, - setHostRoutes: function(network) { - let hosts = network.getDnses().concat(network.httpProxyHost); + _handleGateways: function(networkId, gateways) { + let currentNetworkLinks = this.networkInterfaceLinks[networkId]; + if (currentNetworkLinks.gateways.length == 0 || + currentNetworkLinks.compareGateways(gateways)) { + return Promise.resolve(); + } - return this._updateRoutes(true, hosts, network.name, network.getGateways()); + let currentExtraRoutes = currentNetworkLinks.extraRoutes; + return this._cleanupAllHostRoutes(networkId) + .then(() => { + // If gateways have changed, re-add extra host routes with new gateways. + if (currentExtraRoutes.length > 0) { + this._setHostRoutes(true, + currentExtraRoutes, + currentNetworkLinks.interfaceName, + gateways) + .then(() => { + currentNetworkLinks.extraRoutes = currentExtraRoutes; + }); + } + }); }, - removeHostRoutes: function(network) { - let hosts = network.getDnses().concat(network.httpProxyHost); + _cleanupAllHostRoutes: function(networkId) { + let currentNetworkLinks = this.networkInterfaceLinks[networkId]; + let hostRoutes = currentNetworkLinks.linkRoutes.concat( + currentNetworkLinks.extraRoutes); - return this._updateRoutes(false, hosts, network.name, network.getGateways()); + if (hostRoutes.length === 0) { + return Promise.resolve(); + } + + return this._setHostRoutes(false, + hostRoutes, + currentNetworkLinks.interfaceName, + currentNetworkLinks.gateways) + .catch((aError) => { + debug("Error (" + aError + ") on _cleanupAllHostRoutes, keep proceeding."); + }) + .then(() => currentNetworkLinks.resetLinks()); }, selectGateway: function(gateways, host) { diff --git a/dom/system/gonk/NetworkService.js b/dom/system/gonk/NetworkService.js index 0789cb1a2aad..1136fec97fa4 100644 --- a/dom/system/gonk/NetworkService.js +++ b/dom/system/gonk/NetworkService.js @@ -56,6 +56,66 @@ function debug(msg) { dump("-*- NetworkService: " + msg + "\n"); } +function Task(id, params, setupFunction) { + this.id = id; + this.params = params; + this.setupFunction = setupFunction; +} + +function NetworkWorkerRequestQueue(networkService) { + this.networkService = networkService; + this.tasks = []; +} +NetworkWorkerRequestQueue.prototype = { + runQueue: function() { + if (this.tasks.length === 0) { + return; + } + + let task = this.tasks[0]; + if (DEBUG) debug("run task id: " + task.id); + + if (typeof task.setupFunction === 'function') { + // If setupFunction returns false, skip sending to Network Worker but call + // handleWorkerMessage() directly with task id, as if the response was + // returned from Network Worker. + if (!task.setupFunction()) { + this.networkService.handleWorkerMessage({id: task.id}); + return; + } + } + + gNetworkWorker.postMessage(task.params); + }, + + enqueue: function(id, params, setupFunction) { + if (DEBUG) debug("enqueue id: " + id); + this.tasks.push(new Task(id, params, setupFunction)); + + if (this.tasks.length === 1) { + this.runQueue(); + } + }, + + dequeue: function(id) { + if (DEBUG) debug("dequeue id: " + id); + + if (!this.tasks.length || this.tasks[0].id != id) { + if (DEBUG) debug("Id " + id + " is not on top of the queue"); + return; + } + + this.tasks.shift(); + if (this.tasks.length > 0) { + // Run queue on the next tick. + Services.tm.currentThread.dispatch(() => { + this.runQueue(); + }, Ci.nsIThread.DISPATCH_NORMAL); + } + } +}; + + /** * This component watches for network interfaces changing state and then * adjusts routes etc. accordingly. @@ -76,6 +136,8 @@ function NetworkService() { // Callbacks to invoke when a reply arrives from the net_worker. this.controlCallbacks = Object.create(null); + this.addedRoutes = new Map(); + this.netWorkerRequestQueue = new NetworkWorkerRequestQueue(this); this.shutdown = false; Services.obs.addObserver(this, "xpcom-shutdown", false); } @@ -90,17 +152,26 @@ NetworkService.prototype = { // Helpers + addedRoutes: null, idgen: 0, - controlMessage: function(params, callback) { + controlMessage: function(params, callback, setupFunction) { if (this.shutdown) { return; } + let id = this.idgen++; + params.id = id; if (callback) { - let id = this.idgen++; - params.id = id; this.controlCallbacks[id] = callback; } + + // For now, we use setupFunction to determine if this command needs to be + // queued or not. + if (setupFunction) { + this.netWorkerRequestQueue.enqueue(id, params, setupFunction); + return; + } + if (gNetworkWorker) { gNetworkWorker.postMessage(params); } @@ -118,6 +189,8 @@ NetworkService.prototype = { callback.call(this, response); delete this.controlCallbacks[id]; } + + this.netWorkerRequestQueue.dequeue(id); }, // nsINetworkService @@ -307,6 +380,10 @@ NetworkService.prototype = { this.controlMessage(options); }, + _routeToString: function(interfaceName, host, prefixLength, gateway) { + return host + "-" + prefixLength + "-" + gateway + "-" + interfaceName; + }, + modifyRoute: function(action, interfaceName, host, prefixLength, gateway) { let command; @@ -322,8 +399,22 @@ NetworkService.prototype = { return Promise.reject(); } + let route = this._routeToString(interfaceName, host, prefixLength, gateway); + let setupFunc = () => { + let count = this.addedRoutes.get(route); + if (DEBUG) debug(command + ": " + route + " -> " + count); + + // Return false if there is no need to send the command to network worker. + if ((action == Ci.nsINetworkService.MODIFY_ROUTE_ADD && count) || + (action == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE && + (!count || count > 1))) { + return false; + } + + return true; + }; + if (DEBUG) debug(command + " " + host + " on " + interfaceName); - let deferred = Promise.defer(); let options = { cmd: command, ifname: interfaceName, @@ -331,14 +422,32 @@ NetworkService.prototype = { prefixLength: prefixLength, ip: host }; - this.controlMessage(options, function(data) { - if (data.error) { - deferred.reject(data.reason); - return; - } - deferred.resolve(); + + return new Promise((aResolve, aReject) => { + this.controlMessage(options, (data) => { + let count = this.addedRoutes.get(route); + + // Remove route from addedRoutes on success or failure. + if (action == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE) { + if (count > 1) { + this.addedRoutes.set(route, count - 1); + } else { + this.addedRoutes.delete(route); + } + } + + if (data.error) { + aReject(data.reason); + return; + } + + if (action == Ci.nsINetworkService.MODIFY_ROUTE_ADD) { + this.addedRoutes.set(route, count ? count + 1 : 1); + } + + aResolve(); + }, setupFunc); }); - return deferred.promise; }, removeHostRoutes: function(ifname) { diff --git a/dom/system/gonk/NetworkUtils.cpp b/dom/system/gonk/NetworkUtils.cpp index 64ced69ed1de..14ae33651a01 100644 --- a/dom/system/gonk/NetworkUtils.cpp +++ b/dom/system/gonk/NetworkUtils.cpp @@ -1955,6 +1955,11 @@ CommandResult NetworkUtils::addHostRoute(NetworkParams& aOptions) */ CommandResult NetworkUtils::addHostRouteLegacy(NetworkParams& aOptions) { + if (aOptions.mGateway.IsEmpty()) { + ERROR("addHostRouteLegacy does not support empty gateway."); + return EINVAL; + } + NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname); NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp); NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateway); From fb18c7eadba496520940cf43c0fe8041643149fb Mon Sep 17 00:00:00 2001 From: Jessica Jong Date: Wed, 11 Feb 2015 16:01:10 +0800 Subject: [PATCH 32/33] Bug 973543 - Part 2: remove 'removeHostRoutes()' as it is no longer needed. r=echen --- dom/system/gonk/NetworkService.js | 9 --------- dom/system/gonk/NetworkUtils.cpp | 22 ---------------------- dom/system/gonk/NetworkUtils.h | 2 -- dom/system/gonk/nsINetworkService.idl | 10 +--------- 4 files changed, 1 insertion(+), 42 deletions(-) diff --git a/dom/system/gonk/NetworkService.js b/dom/system/gonk/NetworkService.js index 1136fec97fa4..9c4f9888d055 100644 --- a/dom/system/gonk/NetworkService.js +++ b/dom/system/gonk/NetworkService.js @@ -450,15 +450,6 @@ NetworkService.prototype = { }); }, - removeHostRoutes: function(ifname) { - if(DEBUG) debug("Going to remove all host routes on " + ifname); - let options = { - cmd: "removeHostRoutes", - ifname: ifname, - }; - this.controlMessage(options); - }, - addSecondaryRoute: function(ifname, route) { if(DEBUG) debug("Going to add route to secondary table on " + ifname); let options = { diff --git a/dom/system/gonk/NetworkUtils.cpp b/dom/system/gonk/NetworkUtils.cpp index 14ae33651a01..71aacbbfbdd4 100644 --- a/dom/system/gonk/NetworkUtils.cpp +++ b/dom/system/gonk/NetworkUtils.cpp @@ -1485,7 +1485,6 @@ void NetworkUtils::ExecuteCommand(NetworkParams aOptions) BUILD_ENTRY(removeDefaultRoute), BUILD_ENTRY(addHostRoute), BUILD_ENTRY(removeHostRoute), - BUILD_ENTRY(removeHostRoutes), BUILD_ENTRY(addSecondaryRoute), BUILD_ENTRY(removeSecondaryRoute), BUILD_ENTRY(setNetworkInterfaceAlarm), @@ -2031,27 +2030,6 @@ CommandResult NetworkUtils::removeHostRouteLegacy(NetworkParams& aOptions) prefix, autoGateway.get()); } -/** - * Remove the routes associated with the named interface. - */ -CommandResult NetworkUtils::removeHostRoutes(NetworkParams& aOptions) -{ - if (SDK_VERSION < 20) { - return removeHostRoutesLegacy(aOptions); - } - - NU_DBG("Don't know how to remove host routes on a interface"); - return SUCCESS; -} - -/** - * Remove the routes associated with the named interface. - */ -CommandResult NetworkUtils::removeHostRoutesLegacy(NetworkParams& aOptions) -{ - return mNetUtils->do_ifc_remove_host_routes(GET_CHAR(mIfname)); -} - CommandResult NetworkUtils::removeNetworkRoute(NetworkParams& aOptions) { if (SDK_VERSION < 20) { diff --git a/dom/system/gonk/NetworkUtils.h b/dom/system/gonk/NetworkUtils.h index 7e88231522d1..7f0f841d9f45 100644 --- a/dom/system/gonk/NetworkUtils.h +++ b/dom/system/gonk/NetworkUtils.h @@ -291,7 +291,6 @@ private: CommandResult addHostRoute(NetworkParams& aOptions); CommandResult removeDefaultRoute(NetworkParams& aOptions); CommandResult removeHostRoute(NetworkParams& aOptions); - CommandResult removeHostRoutes(NetworkParams& aOptions); CommandResult removeNetworkRoute(NetworkParams& aOptions); CommandResult setDNS(NetworkParams& aOptions); CommandResult addSecondaryRoute(NetworkParams& aOptions); @@ -310,7 +309,6 @@ private: CommandResult addHostRouteLegacy(NetworkParams& aOptions); CommandResult removeHostRouteLegacy(NetworkParams& aOptions); - CommandResult removeHostRoutesLegacy(NetworkParams& aOptions); CommandResult setDefaultRouteLegacy(NetworkParams& aOptions); CommandResult removeDefaultRouteLegacy(NetworkParams& aOptions); CommandResult removeNetworkRouteLegacy(NetworkParams& aOptions); diff --git a/dom/system/gonk/nsINetworkService.idl b/dom/system/gonk/nsINetworkService.idl index db229a3d1d9f..9ad56122cc47 100644 --- a/dom/system/gonk/nsINetworkService.idl +++ b/dom/system/gonk/nsINetworkService.idl @@ -159,7 +159,7 @@ interface nsIDhcpRequestCallback : nsISupports /** * Provide network services. */ -[scriptable, uuid(138ab267-0007-4c3e-8bfc-a7e1be0b5a6f)] +[scriptable, uuid(e40dd966-cb04-4dc7-ac4b-6382769c00b9)] interface nsINetworkService : nsISupports { const long MODIFY_ROUTE_ADD = 0; @@ -345,14 +345,6 @@ interface nsINetworkService : nsISupports in long prefixLength, [optional] in DOMString gateway); - /** - * Remove all host routes. - * - * @param interfaceName - * The interface name we want remove from the routing table. - */ - void removeHostRoutes(in DOMString interfaceName); - /** * Add route to secondary routing table. * From 2f54ae9e6de134e79dccb0ca95101b9b1861bb0e Mon Sep 17 00:00:00 2001 From: Greg Weng Date: Wed, 11 Feb 2015 09:28:10 +0800 Subject: [PATCH 33/33] Bug 1130938 - B2G RIL: Remove the duplicated RilWorkerBuffer in ril_worker.js r=:echen --- dom/system/gonk/ril_worker.js | 132 ---------------------------------- 1 file changed, 132 deletions(-) diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 084e99b2609f..59ad63d78763 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -82,138 +82,6 @@ let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND; // Ril quirk to control the uicc/data subscription. let RILQUIRKS_SUBSCRIPTION_CONTROL; -function BufObject(aContext) { - this.context = aContext; -} -BufObject.prototype = { - context: null, - - mToken: 0, - mTokenRequestMap: null, - - init: function() { - this._init(); - - // This gets incremented each time we send out a parcel. - this.mToken = 1; - - // Maps tokens we send out with requests to the request type, so that - // when we get a response parcel back, we know what request it was for. - this.mTokenRequestMap = new Map(); - }, - - /** - * Process one parcel. - */ - processParcel: function() { - let response_type = this.readInt32(); - - let request_type, options; - if (response_type == RESPONSE_TYPE_SOLICITED) { - let token = this.readInt32(); - let error = this.readInt32(); - - options = this.mTokenRequestMap.get(token); - if (!options) { - if (DEBUG) { - this.context.debug("Suspicious uninvited request found: " + - token + ". Ignored!"); - } - return; - } - - this.mTokenRequestMap.delete(token); - request_type = options.rilRequestType; - - options.rilRequestError = error; - if (DEBUG) { - this.context.debug("Solicited response for request type " + request_type + - ", token " + token + ", error " + error); - } - } else if (response_type == RESPONSE_TYPE_UNSOLICITED) { - request_type = this.readInt32(); - if (DEBUG) { - this.context.debug("Unsolicited response for request type " + request_type); - } - } else { - if (DEBUG) { - this.context.debug("Unknown response type: " + response_type); - } - return; - } - - this.context.RIL.handleParcel(request_type, this.readAvailable, options); - }, - - /** - * Start a new outgoing parcel. - * - * @param type - * Integer specifying the request type. - * @param options [optional] - * Object containing information about the request, e.g. the - * original main thread message object that led to the RIL request. - */ - newParcel: function(type, options) { - if (DEBUG) { - this.context.debug("New outgoing parcel of type " + type + - ", token " + this.mToken); - } - - // We're going to leave room for the parcel size at the beginning. - this.outgoingIndex = this.PARCEL_SIZE_SIZE; - this.writeInt32(this._reMapRequestType(type)); - this.writeInt32(this.mToken); - - if (!options) { - options = {}; - } - options.rilRequestType = type; - options.rilRequestError = null; - this.mTokenRequestMap.set(this.mToken, options); - this.mToken++; - return this.mToken; - }, - - simpleRequest: function(type, options) { - this.newParcel(type, options); - this.sendParcel(); - }, - - onSendParcel: function(parcel) { - postRILMessage(this.context.clientId, parcel); - }, - - /** - * Remapping the request type to different values based on RIL version. - * We only have to do this for SUBSCRIPTION right now, so I just make it - * simple. A generic logic or structure could be discussed if we have more - * use cases, especially the cases from different partners. - */ - _reMapRequestType: function(type) { - let newType = type; - switch (type) { - case REQUEST_SET_UICC_SUBSCRIPTION: - case REQUEST_SET_DATA_SUBSCRIPTION: - if (this.context.RIL.version < 9) { - // Shift the CAF's proprietary parcels. Please see - // https://www.codeaurora.org/cgit/quic/la/platform/hardware/ril/tree/include/telephony/ril.h?h=b2g_jb_3.2 - newType = type - 1; - } - break; - } - - return newType; - } -}; - -(function() { - let base = require("resource://gre/modules/workers/worker_buf.js").Buf; - for (let p in base) { - BufObject.prototype[p] = base[p]; - } -})(); - const TELEPHONY_REQUESTS = [ REQUEST_GET_CURRENT_CALLS, REQUEST_ANSWER,