From 865cfa577c9af1da7690f68990091bf9026f5072 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 23 Apr 2015 11:02:02 -0700 Subject: [PATCH 01/80] Bug 1157828 - Move ShouldMarkCrossCompartment adjacent to other marking invariant logic; r=jonco --- js/src/gc/Marking.cpp | 107 ++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 57 deletions(-) diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 5321a4d7c3e..604e5519105 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -72,13 +72,6 @@ IsThingPoisoned(T* thing) } #endif -static GCMarker* -AsGCMarker(JSTracer* trc) -{ - MOZ_ASSERT(trc->isMarkingTracer()); - return static_cast(trc); -} - template bool ThingIsPermanentAtomOrWellKnownSymbol(T* thing) { return false; } template <> bool ThingIsPermanentAtomOrWellKnownSymbol(JSString* str) { return str->isPermanentAtom(); @@ -193,6 +186,56 @@ FOR_EACH_GC_LAYOUT(IMPL_CHECK_TRACED_THING); #undef IMPL_CHECK_TRACED_THING } // namespace js +static bool +ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell) +{ + if (!trc->isMarkingTracer()) + return true; + + uint32_t color = static_cast(trc)->markColor(); + MOZ_ASSERT(color == BLACK || color == GRAY); + + if (!cell->isTenured()) { + MOZ_ASSERT(color == BLACK); + return false; + } + TenuredCell& tenured = cell->asTenured(); + + JS::Zone* zone = tenured.zone(); + if (color == BLACK) { + /* + * Having black->gray edges violates our promise to the cycle + * collector. This can happen if we're collecting a compartment and it + * has an edge to an uncollected compartment: it's possible that the + * source and destination of the cross-compartment edge should be gray, + * but the source was marked black by the conservative scanner. + */ + if (tenured.isMarked(GRAY)) { + MOZ_ASSERT(!zone->isCollecting()); + trc->runtime()->gc.setFoundBlackGrayEdges(); + } + return zone->isGCMarking(); + } else { + if (zone->isGCMarkingBlack()) { + /* + * The destination compartment is being not being marked gray now, + * but it will be later, so record the cell so it can be marked gray + * at the appropriate time. + */ + if (!tenured.isMarked()) + DelayCrossCompartmentGrayMarking(src); + return false; + } + return zone->isGCMarkingGray(); + } +} + +static bool +ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val) +{ + return val.isMarkable() && ShouldMarkCrossCompartment(trc, src, (Cell*)val.toGCThing()); +} + #define JS_ROOT_MARKING_ASSERT(trc) \ MOZ_ASSERT_IF(trc->isMarkingTracer(), \ trc->runtime()->gc.state() == NO_INCREMENTAL || \ @@ -833,56 +876,6 @@ gc::MarkObjectSlots(JSTracer* trc, NativeObject* obj, uint32_t start, uint32_t n } } -static bool -ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell) -{ - if (!trc->isMarkingTracer()) - return true; - - uint32_t color = AsGCMarker(trc)->markColor(); - MOZ_ASSERT(color == BLACK || color == GRAY); - - if (IsInsideNursery(cell)) { - MOZ_ASSERT(color == BLACK); - return false; - } - TenuredCell& tenured = cell->asTenured(); - - JS::Zone* zone = tenured.zone(); - if (color == BLACK) { - /* - * Having black->gray edges violates our promise to the cycle - * collector. This can happen if we're collecting a compartment and it - * has an edge to an uncollected compartment: it's possible that the - * source and destination of the cross-compartment edge should be gray, - * but the source was marked black by the conservative scanner. - */ - if (tenured.isMarked(GRAY)) { - MOZ_ASSERT(!zone->isCollecting()); - trc->runtime()->gc.setFoundBlackGrayEdges(); - } - return zone->isGCMarking(); - } else { - if (zone->isGCMarkingBlack()) { - /* - * The destination compartment is being not being marked gray now, - * but it will be later, so record the cell so it can be marked gray - * at the appropriate time. - */ - if (!tenured.isMarked()) - DelayCrossCompartmentGrayMarking(src); - return false; - } - return zone->isGCMarkingGray(); - } -} - -static bool -ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val) -{ - return val.isMarkable() && ShouldMarkCrossCompartment(trc, src, (Cell*)val.toGCThing()); -} - /*** Special Marking ***/ void From c4007f36c1191a64c4184124b400222489e6771f Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 23 Apr 2015 11:05:46 -0700 Subject: [PATCH 02/80] Bug 1157829 - The markAndScan functions are now just an additional assertion; r=sfink --- js/src/gc/Marking.cpp | 43 ++++++++++++++----------------------------- js/src/gc/Tracer.h | 6 +++--- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 604e5519105..ba1506c02a6 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -329,8 +329,6 @@ ConvertToBase(T* thingp) template void DispatchToTracer(JSTracer* trc, T* thingp, const char* name); template T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name); template void DoMarking(GCMarker* gcmarker, T thing); -static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell); -static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val); template void @@ -584,6 +582,15 @@ template <> void GCMarker::traverse(ObjectGroup* thing) { markAndPush(GroupTag, template <> void GCMarker::traverse(jit::JitCode* thing) { markAndPush(JitCodeTag, thing); } } // namespace js +template +void +GCMarker::traverse(JSObject* source, T* target) +{ + MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(target), + runtime()->isAtomsZone(target->zone()) || target->zone() == source->zone()); + traverse(target); +} + template bool js::GCMarker::mark(T* thing) @@ -1430,28 +1437,6 @@ GCMarker::processMarkStackOther(uintptr_t tag, uintptr_t addr) } } -MOZ_ALWAYS_INLINE void -GCMarker::markAndScanString(JSObject* source, JSString* str) -{ - if (!str->isPermanentAtom()) { - JS_COMPARTMENT_ASSERT(runtime(), str); - MOZ_ASSERT(runtime()->isAtomsZone(str->zone()) || str->zone() == source->zone()); - if (str->markIfUnmarked()) - eagerlyMarkChildren(str); - } -} - -MOZ_ALWAYS_INLINE void -GCMarker::markAndScanSymbol(JSObject* source, JS::Symbol* sym) -{ - if (!sym->isWellKnownSymbol()) { - JS_COMPARTMENT_ASSERT(runtime(), sym); - MOZ_ASSERT(runtime()->isAtomsZone(sym->zone()) || sym->zone() == source->zone()); - if (sym->markIfUnmarked()) - eagerlyMarkChildren(sym); - } -} - inline void GCMarker::processMarkStackTop(SliceBudget& budget) { @@ -1504,7 +1489,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget) const Value& v = *vp++; if (v.isString()) { - markAndScanString(obj, v.toString()); + traverse(obj, v.toString()); } else if (v.isObject()) { JSObject* obj2 = &v.toObject(); MOZ_ASSERT(obj->compartment() == obj2->compartment()); @@ -1515,7 +1500,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget) goto scan_obj; } } else if (v.isSymbol()) { - markAndScanSymbol(obj, v.toSymbol()); + traverse(obj, v.toSymbol()); } } return; @@ -1524,7 +1509,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget) { while (*unboxedTraceList != -1) { JSString* str = *reinterpret_cast(unboxedMemory + *unboxedTraceList); - markAndScanString(obj, str); + traverse(obj, str); unboxedTraceList++; } unboxedTraceList++; @@ -1539,14 +1524,14 @@ GCMarker::processMarkStackTop(SliceBudget& budget) while (*unboxedTraceList != -1) { const Value& v = *reinterpret_cast(unboxedMemory + *unboxedTraceList); if (v.isString()) { - markAndScanString(obj, v.toString()); + traverse(obj, v.toString()); } else if (v.isObject()) { JSObject* obj2 = &v.toObject(); MOZ_ASSERT(obj->compartment() == obj2->compartment()); if (mark(obj2)) repush(obj2); } else if (v.isSymbol()) { - markAndScanSymbol(obj, v.toSymbol()); + traverse(obj, v.toSymbol()); } unboxedTraceList++; } diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index a2885ebe460..c5aa699cc90 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -160,6 +160,9 @@ class GCMarker : public JSTracer // Mark the given GC thing and traverse its children at some point. template void traverse(T* thing); + // Calls traverse on target after making additional assertions. + template void traverse(JSObject* source, T* target); + /* * Care must be taken changing the mark color from gray to black. The cycle * collector depends on the invariant that there are no black to gray edges @@ -285,9 +288,6 @@ class GCMarker : public JSTracer inline void processMarkStackTop(SliceBudget& budget); void processMarkStackOther(uintptr_t tag, uintptr_t addr); - void markAndScanString(JSObject* source, JSString* str); - void markAndScanSymbol(JSObject* source, JS::Symbol* sym); - /* The color is only applied to objects and functions. */ uint32_t color; From 42ac24dd55662abc146a751aa5bb20becc626e18 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 16 Apr 2015 13:45:24 -0700 Subject: [PATCH 03/80] Bug 1156533 - Simplify how we trace Shapes for marking; r=sfink --- js/src/gc/Marking.cpp | 184 +++++++++++++----- js/src/gc/Tracer.h | 8 +- .../gc/incremental-AccessorShape-barrier.js | 15 ++ js/src/vm/Shape.h | 15 -- 4 files changed, 153 insertions(+), 69 deletions(-) create mode 100644 js/src/jit-test/tests/gc/incremental-AccessorShape-barrier.js diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index ba1506c02a6..fc603e82e84 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -38,6 +38,69 @@ using mozilla::IsBaseOf; using mozilla::IsSame; using mozilla::MakeRange; +// Tracing Overview +// ================ +// +// Tracing, in this context, refers to an abstract visitation of some or all of +// the GC-controlled heap. The effect of tracing an edge of the graph depends +// on the subclass of the JSTracer on whose behalf we are tracing. +// +// Marking +// ------- +// +// The primary JSTracer is the GCMarker. The marking tracer causes the target +// of each traversed edge to be marked black and the target edge's children to +// be marked either gray (in the gc algorithm sense) or immediately black. +// +// Callback +// -------- +// +// The secondary JSTracer is the CallbackTracer. This simply invokes a callback +// on each edge in a child. +// +// The following is a rough outline of the general struture of the tracing +// internals. +// +// // +// .---------. .---------. .--------------------------. .----------. // +// |TraceEdge| |TraceRoot| |TraceManuallyBarrieredEdge| ... |TraceRange| ... etc. // +// '---------' '---------' '--------------------------' '----------' // +// \ \ / / // +// \ \ .----------------. / / // +// o------------->o-|DispatchToTracer|-o<-----------------------o // +// '----------------' // +// / \ // +// / \ // +// .---------. .----------. .-----------------. // +// |DoMarking| |DoCallback|-------> ||-----------> // +// '---------' '----------' '-----------------' // +// | // +// | // +// .--------. // +// o---------------->|traverse| . // +// /_\ '--------' ' . // +// | . . ' . // +// | . . ' . // +// | . . ' . // +// | .-----------. .-----------. ' . .--------------------. // +// | |markAndScan| |markAndPush| ' - |markAndTraceChildren|----> // +// | '-----------' '-----------' '--------------------' // +// | | \ // +// | | \ // +// | .----------------------. .----------------. // +// | |T::eagerlyMarkChildren| |pushMarkStackTop|<===Oo // +// | '----------------------' '----------------' || // +// | | || || // +// | | || || // +// | | || || // +// o<-----------------o<========================OO============Oo // +// // +// // +// Legend: // +// ------ Direct calls // +// . . . Static dispatch // +// ====== Dispatch through a manual stack. // +// // void * const js::NullPtr::constNullValue = nullptr; JS_PUBLIC_DATA(void * const) JS::NullPtr::constNullValue = nullptr; @@ -531,20 +594,23 @@ DoMarking(GCMarker* gcmarker, jsid id) DispatchIdTyped(DoMarkingFunctor(), id, gcmarker); } -// The default traversal calls out to the fully generic traceChildren function -// to visit the child edges. In the absense of other traversal mechanisms, this +// The simplest traversal calls out to the fully generic traceChildren function +// to visit the child edges. In the absence of other traversal mechanisms, this // function will rapidly grow the stack past its bounds and crash the process. // Thus, this generic tracing should only be used in cases where subsequent // tracing will not recurse. template void -js::GCMarker::traverse(T* thing) +js::GCMarker::markAndTraceChildren(T* thing) { - auto asBase = static_cast::type*>(thing); - MOZ_ASSERT(!ThingIsPermanentAtomOrWellKnownSymbol(asBase)); - if (mark(asBase)) + MOZ_ASSERT(!ThingIsPermanentAtomOrWellKnownSymbol(thing)); + if (mark(thing)) thing->traceChildren(this); } +namespace js { +template <> void GCMarker::traverse(LazyScript* thing) { markAndTraceChildren(thing); } +template <> void GCMarker::traverse(JSScript* thing) { markAndTraceChildren(thing); } +} // namespace js // Shape, BaseShape, String, and Symbol are extremely common, but have simple // patterns of recursion. We traverse trees of these edges immediately, with @@ -582,15 +648,36 @@ template <> void GCMarker::traverse(ObjectGroup* thing) { markAndPush(GroupTag, template <> void GCMarker::traverse(jit::JitCode* thing) { markAndPush(JitCodeTag, thing); } } // namespace js -template +namespace js { +template <> void -GCMarker::traverse(JSObject* source, T* target) +GCMarker::traverse(AccessorShape* thing) { + MOZ_CRASH("AccessorShape must be marked as a Shape"); +} +} // namespace js + +template +void +js::GCMarker::traverse(S source, T target) { MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(target), runtime()->isAtomsZone(target->zone()) || target->zone() == source->zone()); traverse(target); } +template struct TraverseFunctor : public VoidDefaultAdaptor { + template void operator()(T t, GCMarker* gcmarker, S s) { + return gcmarker->traverse(s, t); + } +}; + +template +void +js::GCMarker::traverse(S source, jsid id) +{ + DispatchIdTyped(TraverseFunctor(), id, this, source); +} + template bool js::GCMarker::mark(T* thing) @@ -603,6 +690,39 @@ js::GCMarker::mark(T* thing) : gc::TenuredCell::fromPointer(thing)->markIfUnmarked(gc::BLACK); } +inline void +Shape::traceChildren(JSTracer* trc) +{ + TraceEdge(trc, &base_, "base"); + TraceEdge(trc, &propidRef(), "propid"); + if (parent) + TraceEdge(trc, &parent, "parent"); + + if (hasGetterObject()) + TraceManuallyBarrieredEdge(trc, &asAccessorShape().getterObj, "getter"); + if (hasSetterObject()) + TraceManuallyBarrieredEdge(trc, &asAccessorShape().setterObj, "setter"); +} +inline void +js::GCMarker::eagerlyMarkChildren(Shape* shape) +{ + MOZ_ASSERT(shape->isMarked(this->markColor())); + do { + traverse(shape, shape->base()); + traverse(shape, shape->propidRef().get()); + + // When triggered between slices on belhalf of a barrier, these + // objects may reside in the nursery, so require an extra check. + // FIXME: Bug 1157967 - remove the isTenured checks. + if (shape->hasGetterObject() && shape->getterObject()->isTenured()) + traverse(shape, shape->getterObject()); + if (shape->hasSetterObject() && shape->setterObject()->isTenured()) + traverse(shape, shape->setterObject()); + + shape = shape->previous(); + } while (shape && mark(shape)); +} + template static inline void CheckIsMarkedThing(T* thingp) @@ -900,22 +1020,6 @@ gc::MarkIdForBarrier(JSTracer* trc, jsid* idp, const char* name) /*** Push Mark Stack ***/ -/* - * GCMarker::traverse for BaseShape unpacks its children directly onto the mark - * stack. For a pre-barrier between incremental slices, this may result in - * objects in the nursery getting pushed onto the mark stack. It is safe to - * ignore these objects because they will be marked by the matching - * post-barrier during the minor GC at the start of each incremental slice. - */ -static void -MaybePushMarkStackBetweenSlices(GCMarker* gcmarker, JSObject* thing) -{ - MOZ_ASSERT_IF(gcmarker->runtime()->isHeapBusy(), !IsInsideNursery(thing)); - - if (!IsInsideNursery(thing)) - gcmarker->traverse(thing); -} - void BaseShape::traceChildren(JSTracer* trc) { @@ -926,30 +1030,6 @@ BaseShape::traceChildren(JSTracer* trc) if (global) TraceManuallyBarrieredEdge(trc, &global, "global"); } - -inline void -GCMarker::eagerlyMarkChildren(Shape* shape) -{ - restart: - traverse(shape->base()); - - const BarrieredBase& id = shape->propidRef(); - if (JSID_IS_STRING(id)) - traverse(JSID_TO_STRING(id)); - else if (JSID_IS_SYMBOL(id)) - traverse(JSID_TO_SYMBOL(id)); - - if (shape->hasGetterObject()) - MaybePushMarkStackBetweenSlices(this, shape->getterObject()); - - if (shape->hasSetterObject()) - MaybePushMarkStackBetweenSlices(this, shape->setterObject()); - - shape = shape->previous(); - if (shape && shape->markIfUnmarked(this->markColor())) - goto restart; -} - inline void GCMarker::eagerlyMarkChildren(BaseShape* base) { @@ -958,7 +1038,7 @@ GCMarker::eagerlyMarkChildren(BaseShape* base) base->compartment()->mark(); if (GlobalObject* global = base->compartment()->unsafeUnbarrieredMaybeGlobal()) - traverse(global); + traverse(static_cast(global)); /* * All children of the owned base shape are consistent with its @@ -1200,7 +1280,7 @@ ScanObjectGroup(GCMarker* gcmarker, ObjectGroup* group) group->compartment()->mark(); if (GlobalObject* global = group->compartment()->unsafeUnbarrieredMaybeGlobal()) - gcmarker->traverse(global); + gcmarker->traverse(static_cast(global)); if (group->newScript()) group->newScript()->trace(gcmarker); @@ -1215,10 +1295,10 @@ ScanObjectGroup(GCMarker* gcmarker, ObjectGroup* group) gcmarker->traverse(unboxedGroup); if (TypeDescr* descr = group->maybeTypeDescr()) - gcmarker->traverse(descr); + gcmarker->traverse(static_cast(descr)); if (JSFunction* fun = group->maybeInterpretedFunction()) - gcmarker->traverse(fun); + gcmarker->traverse(static_cast(fun)); } void diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index c5aa699cc90..5fc22aa528b 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -158,10 +158,13 @@ class GCMarker : public JSTracer void reset(); // Mark the given GC thing and traverse its children at some point. - template void traverse(T* thing); + template void traverse(T thing); // Calls traverse on target after making additional assertions. - template void traverse(JSObject* source, T* target); + template void traverse(S source, T target); + + // C++ requires explicit declarations of partial template instantiations. + template void traverse(S source, jsid target); /* * Care must be taken changing the mark color from gray to black. The cycle @@ -239,6 +242,7 @@ class GCMarker : public JSTracer pushTaggedPtr(ObjectTag, obj); } + template void markAndTraceChildren(T* thing); template void markAndPush(StackTag tag, T* thing); template void markAndScan(T* thing); void eagerlyMarkChildren(Shape* shape); diff --git a/js/src/jit-test/tests/gc/incremental-AccessorShape-barrier.js b/js/src/jit-test/tests/gc/incremental-AccessorShape-barrier.js new file mode 100644 index 00000000000..9dde938ecdb --- /dev/null +++ b/js/src/jit-test/tests/gc/incremental-AccessorShape-barrier.js @@ -0,0 +1,15 @@ +var o = {}; +function foo() { + var i = 0; + startgc(0); + Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; }, + set: function s() { return i; }}); + Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; }, + set: function s() { return i; }}); + Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; }, + set: function s() { return i; }}); + Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; }, + set: function s() { return i; }}); + abortgc(); +} +foo(); diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index c7f0f751ec2..439f8d77132 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1319,21 +1319,6 @@ Shape::searchLinear(jsid id) return nullptr; } -inline void -Shape::traceChildren(JSTracer* trc) -{ - TraceEdge(trc, &base_, "base"); - TraceEdge(trc, &propidRef(), "propid"); - if (parent) - TraceEdge(trc, &parent, "parent"); - - if (hasGetterObject()) - TraceManuallyBarrieredEdge(trc, &asAccessorShape().getterObj, "getter"); - - if (hasSetterObject()) - TraceManuallyBarrieredEdge(trc, &asAccessorShape().setterObj, "setter"); -} - /* * Keep this function in sync with search. It neither hashifies the start * shape nor increments linear search count. From adc03f3af575e457e22923f1c9312a0f5bb1303e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 21 Apr 2015 21:13:30 -0400 Subject: [PATCH 04/80] Bug 1156771 - Part 1: Ensure that each channel uses a unique ID to compute its cache entry extension; r=michal This makes sure that concurrent synthesized HTTP channels for the same URL do not try to use the same cache entry accidentally. We have so far observed this issue as an intermittent test failure (see bug 1136780), and it's hard to test this standalone, so enabling that test will serve as an automated test for this patch as well. --- netwerk/protocol/http/nsHttpChannel.cpp | 7 ++++++- netwerk/protocol/http/nsHttpChannel.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 72363e45426..3720723b4f6 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -83,6 +83,10 @@ namespace mozilla { namespace net { namespace { +// Monotonically increasing ID for generating unique cache entries per +// intercepted channel. +static uint64_t gNumIntercepted = 0; + // True if the local cache should be bypassed when processing a request. #define BYPASS_LOCAL_CACHE(loadFlags) \ (loadFlags & (nsIRequest::LOAD_BYPASS_CACHE | \ @@ -223,6 +227,7 @@ nsHttpChannel::nsHttpChannel() , mRequestTime(0) , mOfflineCacheLastModifiedTime(0) , mInterceptCache(DO_NOT_INTERCEPT) + , mInterceptionID(gNumIntercepted++) , mCachedContentIsValid(false) , mCachedContentIsPartial(false) , mCacheOnlyMetadata(false) @@ -2782,7 +2787,7 @@ nsHttpChannel::OpenCacheEntry(bool isHttps) extension.Append(nsPrintfCString("%d", mPostID)); } if (PossiblyIntercepted()) { - extension.Append('u'); + extension.Append(nsPrintfCString("u%lld", mInterceptionID)); } // If this channel should be intercepted, we do not open a cache entry for this channel diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 5cce4f50eba..53aca2327ca 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -418,6 +418,8 @@ private: MAYBE_INTERCEPT, // interception in progress, but can be cancelled INTERCEPTED, // a synthesized response has been provided } mInterceptCache; + // Unique ID of this channel for the interception purposes. + const uint64_t mInterceptionID; bool PossiblyIntercepted() { return mInterceptCache != DO_NOT_INTERCEPT; From de3aa08088fe183d20febda57281fc87f4089d6a Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 21 Apr 2015 21:25:30 -0400 Subject: [PATCH 05/80] Bug 1156771 - Part 2: Assert that the cache entry for the intercepted doesn't exist in the cache storage before we try to open it for the first time; r=michal --- netwerk/protocol/http/nsHttpChannel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 3720723b4f6..884042d9a38 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -41,6 +41,7 @@ #include "GeckoProfiler.h" #include "nsIConsoleService.h" #include "mozilla/Attributes.h" +#include "mozilla/DebugOnly.h" #include "mozilla/Preferences.h" #include "mozilla/VisualEventTracer.h" #include "nsISSLSocketControl.h" @@ -2793,6 +2794,10 @@ nsHttpChannel::OpenCacheEntry(bool isHttps) // If this channel should be intercepted, we do not open a cache entry for this channel // until the interception process is complete and the consumer decides what to do with it. if (mInterceptCache == MAYBE_INTERCEPT) { + DebugOnly exists; + MOZ_ASSERT(NS_FAILED(cacheStorage->Exists(openURI, extension, &exists)) || !exists, + "The entry must not exist in the cache before we create it here"); + nsCOMPtr entry; rv = cacheStorage->OpenTruncate(openURI, extension, getter_AddRefs(entry)); NS_ENSURE_SUCCESS(rv, rv); From 30b734813e36565635314e29bbe23def1d002cf0 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 21 Apr 2015 21:30:24 -0400 Subject: [PATCH 06/80] Bug 1136780 - Re-enable test_fetch_event.html now that bug 1156771 has been fixed; r=nsm --- dom/workers/test/serviceworkers/mochitest.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini index d143add0047..de15acf1330 100644 --- a/dom/workers/test/serviceworkers/mochitest.ini +++ b/dom/workers/test/serviceworkers/mochitest.ini @@ -80,7 +80,6 @@ support-files = [test_unregister.html] [test_installation_simple.html] [test_fetch_event.html] -skip-if = os != "linux" # Bug 1136780 [test_https_fetch.html] [test_https_fetch_cloned_response.html] [test_match_all.html] From a3884ac755f840ce75bfb89ab997eeb1347159b4 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 24 Apr 2015 23:59:42 -0400 Subject: [PATCH 07/80] Bug 1158442 - Remove the "Performance Entry buffer size maximum reached" warning; r=baku This happens far too often in our tests. For example, in our mochitest-3 debug mac test, we hit this warning 4,472 times. At this point, this warning is only adding unneeded noise, slowing down the tests and increasing the size of the logs unnecessarily. Let's remove it. --- dom/base/nsPerformance.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dom/base/nsPerformance.cpp b/dom/base/nsPerformance.cpp index 40bd4631b1b..cca01b339dc 100644 --- a/dom/base/nsPerformance.cpp +++ b/dom/base/nsPerformance.cpp @@ -595,7 +595,6 @@ nsPerformance::AddEntry(nsIHttpChannel* channel, // Don't add the entry if the buffer is full if (mEntries.Length() >= mPrimaryBufferSize) { - NS_WARNING("Performance Entry buffer size maximum reached!"); return; } From 7b1c0384ea0178ccfef71083f7380b88353ed54e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 24 Apr 2015 15:12:50 -0400 Subject: [PATCH 08/80] Bug 892973 - Add support for the YouCompleteMe vim plugin; r=gps --- .ycm_extra_conf.py | 27 ++++++ build/Makefile.in | 7 ++ build/mach_bootstrap.py | 1 + mach | 23 +++-- .../mozbuild/compilation/codecomplete.py | 85 +++++++++++++++++++ 5 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 .ycm_extra_conf.py create mode 100644 python/mozbuild/mozbuild/compilation/codecomplete.py diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 00000000000..332911ab744 --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,27 @@ +# 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/. + +import imp +import os +from StringIO import StringIO +import shlex + +path = os.path.join(os.path.dirname(__file__), 'mach') + +if not os.path.exists(path): + path = os.path.join(os.path.dirname(__file__), 'config.status') + config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE)) + path = os.path.join(config.topsrcdir, 'mach') +mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE)) + +def FlagsForFile(filename): + mach = mach_module.get_mach() + out = StringIO() + out.encoding = None + mach.run(['compileflags', filename], stdout=out, stderr=out) + + return { + 'flags': shlex.split(out.getvalue()), + 'do_cache': True + } diff --git a/build/Makefile.in b/build/Makefile.in index 5c6b151edca..61edfde57ad 100644 --- a/build/Makefile.in +++ b/build/Makefile.in @@ -53,6 +53,13 @@ LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET) INSTALL_TARGETS += LLDBINIT_FINAL_TARGET +# Put the .ycm_extra_conf.py file at the root of the objdir. It is used by +# the vim plugin YouCompleteMe. +YCM_FILES := $(topsrcdir)/.ycm_extra_conf.py +YCM_DEST := $(abspath $(DEPTH)) +YCM_TARGET := export +INSTALL_TARGETS += YCM + ifdef MOZTTDIR # Install the Firefox OS fonts. include $(MOZTTDIR)/fonts.mk diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py index d04ad7586b3..aa51125214b 100644 --- a/build/mach_bootstrap.py +++ b/build/mach_bootstrap.py @@ -83,6 +83,7 @@ MACH_MODULES = [ 'python/mozboot/mozboot/mach_commands.py', 'python/mozbuild/mozbuild/mach_commands.py', 'python/mozbuild/mozbuild/backend/mach_commands.py', + 'python/mozbuild/mozbuild/compilation/codecomplete.py', 'python/mozbuild/mozbuild/frontend/mach_commands.py', 'services/common/tests/mach_commands.py', 'testing/luciddream/mach_commands.py', diff --git a/mach b/mach index 2814f6fa666..f196d368f86 100755 --- a/mach +++ b/mach @@ -27,15 +27,14 @@ def load_mach(topsrcdir): return mach_bootstrap.bootstrap(topsrcdir) -def check_and_run_mach(dir_path, args): +def check_and_get_mach(dir_path): # If we find the mach bootstrap module, we are in the srcdir. mach_path = os.path.join(dir_path, 'build/mach_bootstrap.py') if os.path.isfile(mach_path): - mach = load_mach(dir_path) - sys.exit(mach.run(args)) + return load_mach(dir_path) + return None - -def main(args): +def get_mach(): # Check whether the current directory is within a mach src or obj dir. for dir_path in ancestors(os.getcwd()): # If we find a "mozinfo.json" file, we are in the objdir. @@ -56,14 +55,20 @@ def main(args): # Continue searching for mach_bootstrap in the source directory. dir_path = info['topsrcdir'] - check_and_run_mach(dir_path, args) + mach = check_and_get_mach(dir_path) + if mach: + return mach # If we didn't find a source path by scanning for a mozinfo.json, check # whether the directory containing this script is a source directory. - check_and_run_mach(os.path.dirname(__file__), args) + return check_and_get_mach(os.path.dirname(__file__)) - print('Could not run mach: No mach source directory found.') - sys.exit(1) +def main(args): + mach = get_mach() + if not mach: + print('Could not run mach: No mach source directory found.') + sys.exit(1) + sys.exit(mach.run(args)) if __name__ == '__main__': diff --git a/python/mozbuild/mozbuild/compilation/codecomplete.py b/python/mozbuild/mozbuild/compilation/codecomplete.py new file mode 100644 index 00000000000..276011da067 --- /dev/null +++ b/python/mozbuild/mozbuild/compilation/codecomplete.py @@ -0,0 +1,85 @@ +# 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/. + +# This modules provides functionality for dealing with code completion. + +import os + +from mach.decorators import ( + CommandArgument, + CommandProvider, + Command, +) + +from mozbuild.base import MachCommandBase + +@CommandProvider +class Introspection(MachCommandBase): + """Instropection commands.""" + + @Command('compileflags', category='devenv', + description='Display the compilation flags for a given source file') + @CommandArgument('what', default=None, + help='Source file to display compilation flags for') + def compileflags(self, what): + from mozbuild.util import resolve_target_to_make + import shlex + + top_make = os.path.join(self.topobjdir, 'Makefile') + if not os.path.exists(top_make): + print('Your tree has not been built yet. Please run ' + '|mach build| with no arguments.') + return 1 + + path_arg = self._wrap_path_argument(what) + + make_dir, make_target = resolve_target_to_make(self.topobjdir, + path_arg.relpath()) + + if make_dir is None and make_target is None: + return 1 + + build_vars = {} + + def on_line(line): + elements = [s.strip() for s in line.split('=', 1)] + + if len(elements) != 2: + return + + build_vars[elements[0]] = elements[1] + + try: + old_logger = self.log_manager.replace_terminal_handler(None) + self._run_make(directory=make_dir, target='showbuild', log=False, + print_directory=False, allow_parallel=False, silent=True, + line_handler=on_line) + finally: + self.log_manager.replace_terminal_handler(old_logger) + + if what.endswith('.c'): + name = 'COMPILE_CFLAGS' + else: + name = 'COMPILE_CXXFLAGS' + + if name not in build_vars: + return + + flags = ['-isystem', '-I', '-include', '-MF'] + new_args = [] + path = os.path.join(self.topobjdir, make_dir) + for arg in shlex.split(build_vars[name]): + if new_args and new_args[-1] in flags: + arg = os.path.normpath(os.path.join(path, arg)) + else: + flag = [(f, arg[len(f):]) for f in flags + ['--sysroot='] + if arg.startswith(f)] + if flag: + flag, val = flag[0] + if val: + arg = flag + os.path.normpath(os.path.join(path, val)) + new_args.append(arg) + + print(' '.join(new_args)) + From 7c563264f929a80f6935550305e498e3a5cd9dab Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 27 Apr 2015 13:38:12 -0400 Subject: [PATCH 09/80] Bug 1155984. Improve the performance of the "self" getter in both window and workers. r=peterv,jorendorff --- dom/base/nsGlobalWindow.cpp | 18 ++++++++++++------ dom/base/nsGlobalWindow.h | 2 +- dom/bindings/Codegen.py | 9 +++++---- dom/webidl/Window.webidl | 4 ++-- dom/webidl/WorkerGlobalScope.webidl | 1 + dom/workers/WorkerScope.h | 4 ++-- js/public/Class.h | 2 +- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 2816836e69b..8f7100be18a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2620,6 +2620,12 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, NS_ERROR("can't create the 'window' property"); return NS_ERROR_FAILURE; } + + // And same thing for the "self" property. + if (!JS_GetProperty(cx, newInnerGlobal, "self", &unused)) { + NS_ERROR("can't create the 'self' property"); + return NS_ERROR_FAILURE; + } } } @@ -3533,11 +3539,9 @@ nsGlobalWindow::GetWindow(nsIDOMWindow** aWindow) return NS_OK; } -nsIDOMWindow* -nsGlobalWindow::GetSelf(ErrorResult& aError) +nsGlobalWindow* +nsGlobalWindow::Self() { - FORWARD_TO_OUTER_OR_THROW(GetSelf, (aError), aError, nullptr); - return this; } @@ -3545,10 +3549,12 @@ NS_IMETHODIMP nsGlobalWindow::GetSelf(nsIDOMWindow** aWindow) { ErrorResult rv; - nsCOMPtr window = GetSelf(rv); + FORWARD_TO_OUTER_OR_THROW(GetSelf, (aWindow), rv, rv.StealNSResult()); + + nsCOMPtr window = Self(); window.forget(aWindow); - return rv.StealNSResult(); + return NS_OK; } Navigator* diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 0701b8c30f1..9570665638c 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -838,7 +838,7 @@ public: CreateNamedPropertiesObject(JSContext *aCx, JS::Handle aProto); nsGlobalWindow* Window(); - nsIDOMWindow* GetSelf(mozilla::ErrorResult& aError); + nsGlobalWindow* Self(); nsIDocument* GetDocument() { return GetDoc(); diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 518ce18a356..4db8650ef70 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -3555,11 +3555,12 @@ class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod): "JSJitGetterCallArgs args(&temp);\n") for m in self.descriptor.interface.members: if m.isAttr() and m.getExtendedAttribute("StoreInSlot"): - # Skip doing this for the "window" attribute on the Window - # interface, because that can't be gotten safely until we have - # hooked it up correctly to the outer window. + # Skip doing this for the "window" and "self" attributes on the + # Window interface, because those can't be gotten safely until + # we have hooked it up correctly to the outer window. The + # window code handles doing the get itself. if (self.descriptor.interface.identifier.name == "Window" and - m.identifier.name == "window"): + (m.identifier.name == "window" or m.identifier.name == "self")): continue body += fill( """ diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index e3350bcf0ed..8268ca415c7 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -29,8 +29,8 @@ typedef any Transferable; // the current browsing context [Unforgeable, Constant, StoreInSlot, CrossOriginReadable] readonly attribute Window window; - [Replaceable, Throws, - CrossOriginReadable] readonly attribute WindowProxy self; + [Replaceable, Constant, StoreInSlot, + CrossOriginReadable] readonly attribute Window self; [Unforgeable, StoreInSlot, Pure] readonly attribute Document? document; [Throws] attribute DOMString name; [PutForwards=href, Unforgeable, Throws, diff --git a/dom/webidl/WorkerGlobalScope.webidl b/dom/webidl/WorkerGlobalScope.webidl index 10487b667e1..b7f397154f4 100644 --- a/dom/webidl/WorkerGlobalScope.webidl +++ b/dom/webidl/WorkerGlobalScope.webidl @@ -14,6 +14,7 @@ [Exposed=(Worker)] interface WorkerGlobalScope : EventTarget { + [Constant, Cached] readonly attribute WorkerGlobalScope self; [Replaceable] diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 2644699fa6c..78f2dea3317 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -80,10 +80,10 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScope, DOMEventTargetHelper) - already_AddRefed + WorkerGlobalScope* Self() { - return nsRefPtr(this).forget(); + return this; } Console* diff --git a/js/public/Class.h b/js/public/Class.h index 34af88671f4..db59215b9ad 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -613,7 +613,7 @@ struct JSClass { // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at // the beginning of every global object's slots for use by the // application. -#define JSCLASS_GLOBAL_APPLICATION_SLOTS 4 +#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5 #define JSCLASS_GLOBAL_SLOT_COUNT (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 31) #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \ (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n))) From 29c754823ef5f148f2af1b463384f1c6d987628e Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Wed, 22 Apr 2015 16:34:21 -0700 Subject: [PATCH 10/80] Bug 1058695 - Add member to nsIGlobalObject to detect it is going away. Make promises use it. r=bholley --- dom/base/nsGlobalWindow.cpp | 2 ++ dom/base/nsIGlobalObject.h | 34 +++++++++++++++++++++++++++++ dom/promise/Promise.cpp | 24 +++++++++++++++++++-- dom/promise/PromiseCallback.cpp | 36 +++++++++++++++++-------------- dom/promise/PromiseCallback.h | 20 ++++++++--------- js/src/jsapi.cpp | 6 ++++++ js/src/jsapi.h | 4 +++- js/xpconnect/src/XPCJSRuntime.cpp | 7 +++++- 8 files changed, 103 insertions(+), 30 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8f7100be18a..5a0670bb0f2 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1439,6 +1439,8 @@ nsGlobalWindow::CleanUp() return; mCleanedUp = true; + StartDying(); + mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nullptr); mEventTargetObjects.Clear(); diff --git a/dom/base/nsIGlobalObject.h b/dom/base/nsIGlobalObject.h index c5b28041acc..35794d49ea2 100644 --- a/dom/base/nsIGlobalObject.h +++ b/dom/base/nsIGlobalObject.h @@ -17,13 +17,47 @@ class nsIPrincipal; class nsIGlobalObject : public nsISupports { + bool mIsDying; + +protected: + nsIGlobalObject() + : mIsDying(false) + {} + public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID) + /** + * This check is added to deal with Promise microtask queues. On the main + * thread, we do not impose restrictions about when script stops running or + * when runnables can no longer be dispatched to the main thread. This means + * it is possible for a Promise chain to keep resolving an infinite chain of + * promises, preventing the browser from shutting down. See Bug 1058695. To + * prevent this, the nsGlobalWindow subclass sets this flag when it is + * closed. The Promise implementation checks this and prohibits new runnables + * from being dispatched. + * + * We pair this with checks during processing the promise microtask queue + * that pops up the slow script dialog when the Promise queue is preventing + * a window from going away. + */ + bool + IsDying() const + { + return mIsDying; + } + virtual JSObject* GetGlobalJSObject() = 0; // This method is not meant to be overridden. nsIPrincipal* PrincipalOrNull(); + +protected: + void + StartDying() + { + mIsDying = true; + } }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject, diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index b323e78491c..528a958cc60 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -263,7 +263,7 @@ protected: // console though, for debugging. } - return NS_OK; + return rv.ErrorCode(); } private: @@ -489,13 +489,24 @@ Promise::PerformMicroTaskCheckpoint() return false; } + Maybe cx; + if (NS_IsMainThread()) { + cx.emplace(); + } + do { nsCOMPtr runnable = microtaskQueue.ElementAt(0); MOZ_ASSERT(runnable); // This function can re-enter, so we remove the element before calling. microtaskQueue.RemoveElementAt(0); - runnable->Run(); + nsresult rv = runnable->Run(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + if (cx.isSome()) { + JS_CheckForInterrupt(cx.ref()); + } } while (!microtaskQueue.IsEmpty()); return true; @@ -1071,6 +1082,10 @@ void Promise::AppendCallbacks(PromiseCallback* aResolveCallback, PromiseCallback* aRejectCallback) { + if (mGlobal->IsDying()) { + return; + } + MOZ_ASSERT(aResolveCallback); MOZ_ASSERT(aRejectCallback); @@ -1297,7 +1312,12 @@ Promise::RejectInternal(JSContext* aCx, void Promise::Settle(JS::Handle aValue, PromiseState aState) { + if (mGlobal->IsDying()) { + return; + } + mSettlementTimestamp = TimeStamp::Now(); + SetResult(aValue); SetState(aState); diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp index eff07757fe7..195beba7b49 100644 --- a/dom/promise/PromiseCallback.cpp +++ b/dom/promise/PromiseCallback.cpp @@ -71,7 +71,7 @@ ResolvePromiseCallback::~ResolvePromiseCallback() DropJSObjects(this); } -void +nsresult ResolvePromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -81,10 +81,11 @@ ResolvePromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } mPromise->ResolveInternal(aCx, value); + return NS_OK; } // RejectPromiseCallback @@ -129,7 +130,7 @@ RejectPromiseCallback::~RejectPromiseCallback() DropJSObjects(this); } -void +nsresult RejectPromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -139,11 +140,12 @@ RejectPromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } mPromise->RejectInternal(aCx, value); + return NS_OK; } // WrapperPromiseCallback @@ -190,7 +192,7 @@ WrapperPromiseCallback::~WrapperPromiseCallback() DropJSObjects(this); } -void +nsresult WrapperPromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -198,7 +200,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } ErrorResult rv; @@ -219,7 +221,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } } else { // Convert the ErrorResult to a JS exception object that we can reject @@ -232,7 +234,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, } mNextPromise->RejectInternal(aCx, value); - return; + return NS_OK; } // If the return value is the same as the promise itself, throw TypeError. @@ -270,7 +272,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!fn) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return; + return NS_ERROR_OUT_OF_MEMORY; } JS::Rooted message(aCx, @@ -279,7 +281,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!message) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return; + return NS_ERROR_OUT_OF_MEMORY; } JS::Rooted typeError(aCx); @@ -287,21 +289,22 @@ WrapperPromiseCallback::Call(JSContext* aCx, nullptr, message, &typeError)) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return; + return NS_ERROR_OUT_OF_MEMORY; } mNextPromise->RejectInternal(aCx, typeError); - return; + return NS_OK; } } // Otherwise, run resolver's resolve with value. if (!JS_WrapValue(aCx, &retValue)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } mNextPromise->ResolveInternal(aCx, retValue); + return NS_OK; } // NativePromiseCallback @@ -327,21 +330,22 @@ NativePromiseCallback::~NativePromiseCallback() { } -void +nsresult NativePromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { if (mState == Promise::Resolved) { mHandler->ResolvedCallback(aCx, aValue); - return; + return NS_OK; } if (mState == Promise::Rejected) { mHandler->RejectedCallback(aCx, aValue); - return; + return NS_OK; } NS_NOTREACHED("huh?"); + return NS_ERROR_FAILURE; } /* static */ PromiseCallback* diff --git a/dom/promise/PromiseCallback.h b/dom/promise/PromiseCallback.h index 64e870b1703..1802556410b 100644 --- a/dom/promise/PromiseCallback.h +++ b/dom/promise/PromiseCallback.h @@ -26,8 +26,8 @@ public: PromiseCallback(); - virtual void Call(JSContext* aCx, - JS::Handle aValue) = 0; + virtual nsresult Call(JSContext* aCx, + JS::Handle aValue) = 0; // Return the Promise that this callback will end up resolving or // rejecting, if any. @@ -54,8 +54,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -82,8 +82,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -108,8 +108,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -133,8 +133,8 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8b0e99ccb9e..02e16a09863 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4462,6 +4462,12 @@ JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs) return obj; } +JS_PUBLIC_API(bool) +JS_CheckForInterrupt(JSContext* cx) +{ + return js::CheckForInterrupt(cx); +} + JS_PUBLIC_API(JSInterruptCallback) JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d00b608f602..c148bedff6b 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3948,9 +3948,11 @@ extern JS_PUBLIC_API(bool) Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args, MutableHandleValue rval); - } /* namespace JS */ +extern JS_PUBLIC_API(bool) +JS_CheckForInterrupt(JSContext* cx); + /* * These functions allow setting an interrupt callback that will be called * from the JS thread some time after any thread triggered the callback using diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 77f39d35f77..92be6580624 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1461,8 +1461,13 @@ XPCJSRuntime::InterruptCallback(JSContext* cx) win = WindowGlobalOrNull(proto); } } - if (!win) + + if (!win) { + NS_WARNING("No active window"); return true; + } + + MOZ_ASSERT(!win->IsDying()); if (win->GetIsPrerendered()) { // We cannot display a dialog if the page is being prerendered, so From 26bce22eb4c73f8e0fb2065cf836138561306366 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Mon, 27 Apr 2015 10:43:25 -0700 Subject: [PATCH 11/80] Bug 1128586 - Properly look for Mercurial version; r=RyanVM `mercurial version` doesn't always print the version number. `mercurial --version` does. Use the latter. --- python/mozversioncontrol/mozversioncontrol/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mozversioncontrol/mozversioncontrol/__init__.py b/python/mozversioncontrol/mozversioncontrol/__init__.py index 66b15a804af..cb2b7bf4d29 100644 --- a/python/mozversioncontrol/mozversioncontrol/__init__.py +++ b/python/mozversioncontrol/mozversioncontrol/__init__.py @@ -16,7 +16,7 @@ def get_hg_version(hg): env = os.environ.copy() env[b'HGPLAIN'] = b'1' - info = subprocess.check_output([hg, 'version'], env=env) + info = subprocess.check_output([hg, '--version'], env=env) match = re.search('version ([^\+\)]+)', info) if not match: raise Exception('Unable to identify Mercurial version.') From 40fd1c6f73c42641334f72e82af157d2a9bad8aa Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Mon, 27 Apr 2015 10:43:49 -0700 Subject: [PATCH 12/80] Bug 1128586 - Prefer hg.exe over hg; r=RyanVM This is needed for compatibility with an upcoming release of MozillaBuild, which distributes Mercurial as a Python package, not as a standalone Windows program. As a result, it introduces "hg" into $PATH, which "which" will happily prefer as the "hg" binary. This upsets subprocess. So, we explicitly prefer "hg.exe" over "hg". We could accomplish the same thing by calling which.whichall() and sorting results. But this is more code and IMO not worth the effort to implement. --- tools/mercurial/hgsetup/wizard.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/mercurial/hgsetup/wizard.py b/tools/mercurial/hgsetup/wizard.py index f990a1127de..77be8c78de2 100644 --- a/tools/mercurial/hgsetup/wizard.py +++ b/tools/mercurial/hgsetup/wizard.py @@ -178,13 +178,21 @@ class MercurialSetupWizard(object): if e.errno != errno.EEXIST: raise + # We use subprocess in places, which expects a Win32 executable or + # batch script. On some versions of MozillaBuild, we have "hg.exe", + # "hg.bat," and "hg" (a Python script). "which" will happily return the + # Python script, which will cause subprocess to choke. Explicitly favor + # the Windows version over the plain script. try: - hg = which.which('hg') - except which.WhichError as e: - print(e) - print('Try running |mach bootstrap| to ensure your environment is ' - 'up to date.') - return 1 + hg = which.which('hg.exe') + except which.WhichError: + try: + hg = which.which('hg') + except which.WhichError as e: + print(e) + print('Try running |mach bootstrap| to ensure your environment is ' + 'up to date.') + return 1 try: c = MercurialConfig(config_paths) From 95cbfcf174892a339c2efc3ae02793d5a7711ae8 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 27 Apr 2015 10:57:06 -0700 Subject: [PATCH 13/80] Bug 1134865 - Part 1: Add JSObject::constructorDisplayAtom; r=djvj --- js/src/builtin/TestingFunctions.cpp | 31 +++++++++++++++++++ .../jit-test/tests/basic/constructor-name.js | 28 +++++++++++++++++ js/src/jsobj.cpp | 29 +++++++++++++++++ js/src/jsobj.h | 14 +++++++++ 4 files changed, 102 insertions(+) create mode 100644 js/src/jit-test/tests/basic/constructor-name.js diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index ba2cd99e80f..4b9c96215de 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2554,6 +2554,32 @@ SetDiscardSource(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +GetConstructorName(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + if (!args.requireAtLeast(cx, "getConstructorName", 1)) + return false; + + if (!args[0].isObject()) { + JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE, + "getConstructorName", "Object", + InformalValueTypeName(args[0])); + return false; + } + + RootedAtom name(cx); + if (!args[0].toObject().constructorDisplayAtom(cx, &name)) + return false; + + if (name) { + args.rval().setString(name); + } else { + args.rval().setNull(); + } + return true; +} + static const JSFunctionSpecWithHelp TestingFunctions[] = { JS_FN_HELP("gc", ::GC, 0, 0, "gc([obj] | 'compartment' [, 'shrinking'])", @@ -2960,6 +2986,11 @@ gc::ZealModeHelpText), " Explicitly enable source discarding in the current compartment. The default is that " " source discarding is not explicitly enabled."), + JS_FN_HELP("getConstructorName", GetConstructorName, 1, 0, +"getConstructorName(object)", +" If the given object was created with `new Ctor`, return the constructor's display name. " +" Otherwise, return null."), + JS_FS_HELP_END }; diff --git a/js/src/jit-test/tests/basic/constructor-name.js b/js/src/jit-test/tests/basic/constructor-name.js new file mode 100644 index 00000000000..4bc6a61ead0 --- /dev/null +++ b/js/src/jit-test/tests/basic/constructor-name.js @@ -0,0 +1,28 @@ +function Ctor() {} + +var nested = {}; +nested.Ctor = function () {}; +nested.object = {}; + +function makeInstance() { + let LexicalCtor = function () {}; + return new LexicalCtor; +} + +function makeObject() { + let object = {}; + return object; +} + +let tests = [ + { name: "Ctor", object: new Ctor }, + { name: "nested.Ctor", object: new nested.Ctor }, + { name: "makeInstance/LexicalCtor", object: makeInstance() }, + { name: null, object: {} }, + { name: null, object: nested.object }, + { name: null, object: makeObject() }, +]; + +for (let { name, object } of tests) { + assertEq(getConstructorName(object), name); +} diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index ec935dab1d7..21fadd3e325 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -4106,3 +4106,32 @@ JSObject::traceChildren(JSTracer* trc) } while (false); } } + +static JSAtom* +displayAtomFromObjectGroup(ObjectGroup& group) +{ + TypeNewScript* script = group.newScript(); + if (!script) + return nullptr; + + return script->function()->displayAtom(); +} + +bool +JSObject::constructorDisplayAtom(JSContext* cx, js::MutableHandleAtom name) +{ + ObjectGroup *g = getGroup(cx); + if (!g) + return false; + + name.set(displayAtomFromObjectGroup(*g)); + return true; +} + +JSAtom* +JSObject::maybeConstructorDisplayAtom() const +{ + if (hasLazyGroup()) + return nullptr; + return displayAtomFromObjectGroup(*group()); +} diff --git a/js/src/jsobj.h b/js/src/jsobj.h index d37ff91b58c..46b4972efed 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -254,6 +254,20 @@ class JSObject : public js::gc::Cell */ inline bool isIndexed() const; + /* + * If this object was instantiated with `new Ctor`, return the constructor's + * display atom. Otherwise, return nullptr. + */ + bool constructorDisplayAtom(JSContext* cx, js::MutableHandleAtom name); + + /* + * The same as constructorDisplayAtom above, however if this object has a + * lazy group, nullptr is returned. This allows for use in situations that + * cannot GC and where having some information, even if it is inconsistently + * available, is better than no information. + */ + JSAtom* maybeConstructorDisplayAtom() const; + /* GC support. */ void traceChildren(JSTracer* trc); From b4851189472370b428c4291afaf95f9d41c1149c Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 27 Apr 2015 10:57:06 -0700 Subject: [PATCH 14/80] Bug 1134865 - Part 2: Add constructor name to the allocations log; r=djvj --- js/src/doc/Debugger/Debugger.Memory.md | 23 ++++++--- .../debug/Memory-drainAllocationsLog-16.js | 47 +++++++++++++++++++ js/src/vm/Debugger.cpp | 26 +++++++++- js/src/vm/Debugger.h | 9 +++- js/src/vm/DebuggerMemory.cpp | 6 +++ 5 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 js/src/jit-test/tests/debug/Memory-drainAllocationsLog-16.js diff --git a/js/src/doc/Debugger/Debugger.Memory.md b/js/src/doc/Debugger/Debugger.Memory.md index 106e8e043f0..ee1f1dfd5c9 100644 --- a/js/src/doc/Debugger/Debugger.Memory.md +++ b/js/src/doc/Debugger/Debugger.Memory.md @@ -199,15 +199,26 @@ Function Properties of the `Debugger.Memory.prototype` Object { "timestamp": timestamp, "frame": allocationSite, - "class": className + "class": className, + "constructor": constructorName } - Here timestamp is the [timestamp][timestamps] of the allocation - event, allocationSite is an allocation site (as a - [captured stack][saved-frame]), and className is the string name of - the allocated object's internal `[[Class]]` property. allocationSite - is `null` for objects allocated with no JavaScript frames on the stack. + Where + + * *timestamp* is the [timestamp][timestamps] of the allocation event. + + * *allocationSite* is an allocation site (as a + [captured stack][saved-frame]). Note that this property can be null if the + object was allocated with no JavaScript frames on the stack. + + * *className* is the string name of the allocated object's internal + `[[Class]]` property, for example "Array", "Date", "RegExp", or (most + commonly) "Object". + + * *constructorName* is the constructor function's display name for objects + created by `new Ctor`. If that data is not available, or the object was + not created with a `new` expression, this property is `null`. When `trackingAllocationSites` is `false`, `drainAllocationsLog()` throws an `Error`. diff --git a/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-16.js b/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-16.js new file mode 100644 index 00000000000..b147d6ded0b --- /dev/null +++ b/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-16.js @@ -0,0 +1,47 @@ +// Test drainAllocationsLog() and constructor names. + +const root = newGlobal(); +const dbg = new Debugger(); +const wrappedRoot = dbg.addDebuggee(root); + +root.eval( + ` + function Ctor() {} + + var nested = {}; + nested.Ctor = function () {}; + + function makeInstance() { + let LexicalCtor = function () {}; + return new LexicalCtor; + } + + function makeObject() { + let object = {}; + return object; + } + + this.tests = [ + { name: "Ctor", fn: () => new Ctor }, + { name: "nested.Ctor", fn: () => new nested.Ctor }, + { name: "makeInstance/LexicalCtor", fn: () => makeInstance() }, + { name: null, fn: () => ({}) }, + { name: null, fn: () => (nested.object = {}) }, + { name: null, fn: () => makeObject() }, + ]; + ` +); + +for (let { name, fn } of root.tests) { + print(name); + + dbg.memory.trackingAllocationSites = true; + + fn(); + + let entries = dbg.memory.drainAllocationsLog(); + let ctors = entries.map(e => e.constructor); + assertEq(ctors.some(ctor => ctor === name), true); + + dbg.memory.trackingAllocationSites = false; +} diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index ec8db41fcbf..a5f4cc1fd0b 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1655,6 +1655,28 @@ Debugger::isDebuggee(const JSCompartment* compartment) const return compartment->isDebuggee() && debuggees.has(compartment->maybeGlobal()); } +/* static */ Debugger::AllocationSite* +Debugger::AllocationSite::create(JSContext* cx, HandleObject frame, int64_t when, HandleObject obj) +{ + assertSameCompartment(cx, frame); + + RootedAtom ctorName(cx); + { + AutoCompartment ac(cx, obj); + if (!obj->constructorDisplayAtom(cx, &ctorName)) + return nullptr; + } + + AllocationSite* allocSite = cx->new_(frame, when); + if (!allocSite) + return nullptr; + + allocSite->className = obj->getClass()->name; + allocSite->ctorName = ctorName.get(); + return allocSite; +} + + bool Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame, int64_t when) @@ -1664,7 +1686,7 @@ Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame if (!cx->compartment()->wrap(cx, &wrappedFrame)) return false; - AllocationSite* allocSite = cx->new_(wrappedFrame, when, obj->getClass()->name); + AllocationSite* allocSite = AllocationSite::create(cx, wrappedFrame, when, obj); if (!allocSite) return false; @@ -2324,6 +2346,8 @@ Debugger::trace(JSTracer* trc) for (AllocationSite* s = allocationsLog.getFirst(); s; s = s->getNext()) { if (s->frame) TraceEdge(trc, &s->frame, "allocation log SavedFrame"); + if (s->ctorName) + TraceEdge(trc, &s->ctorName, "allocation log constructor name"); } /* Trace the weak map from JSScript instances to Debugger.Script objects. */ diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 4cfd9801b58..453688f9aea 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -271,17 +271,22 @@ class Debugger : private mozilla::LinkedListElement struct AllocationSite : public mozilla::LinkedListElement { - AllocationSite(HandleObject frame, int64_t when, const char* className) + AllocationSite(HandleObject frame, int64_t when) : frame(frame), when(when), - className(className) + className(nullptr), + ctorName(nullptr) { MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is()); }; + static AllocationSite* create(JSContext* cx, HandleObject frame, int64_t when, + HandleObject obj); + RelocatablePtrObject frame; int64_t when; const char* className; + RelocatablePtrAtom ctorName; }; typedef mozilla::LinkedList AllocationSiteList; diff --git a/js/src/vm/DebuggerMemory.cpp b/js/src/vm/DebuggerMemory.cpp index a8e588b5e02..9cce11d8946 100644 --- a/js/src/vm/DebuggerMemory.cpp +++ b/js/src/vm/DebuggerMemory.cpp @@ -216,6 +216,12 @@ DebuggerMemory::drainAllocationsLog(JSContext* cx, unsigned argc, Value* vp) if (!DefineProperty(cx, obj, cx->names().class_, classNameValue)) return false; + RootedValue ctorName(cx, NullValue()); + if (allocSite->ctorName) + ctorName.setString(allocSite->ctorName); + if (!DefineProperty(cx, obj, cx->names().constructor, ctorName)) + return false; + result->setDenseElement(i, ObjectValue(*obj)); // Pop the front queue entry, and delete it immediately, so that From e7b9c549d9d5a05736555b0e15ea0b4bbfdf9e64 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 27 Apr 2015 10:57:06 -0700 Subject: [PATCH 15/80] Bug 1134865 - Part 3: Add JS::ubi::Node::jsObjectConstructorName; r=djvj --- js/public/UbiNode.h | 29 ++++++++++++++++++++++++++--- js/src/jsapi-tests/testUbiNode.cpp | 15 +++++++++++++++ js/src/vm/UbiNode.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index 2c97157f7ce..28f9ac7a222 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -13,6 +13,7 @@ #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" +#include "mozilla/UniquePtr.h" #include "jspubtd.h" @@ -142,6 +143,7 @@ namespace JS { namespace ubi { using mozilla::Maybe; +using mozilla::UniquePtr; class Edge; class EdgeRange; @@ -206,11 +208,26 @@ class Base { // nullptr is returned. virtual JSCompartment* compartment() const { return nullptr; } - // If this node references a JSObject in the live heap, or represents a - // previously existing JSObject from some deserialized heap snapshot, return - // the object's [[Class]]'s name. Otherwise, return nullptr. + // Methods for JSObject Referents + // + // These methods are only semantically valid if the referent is either a + // JSObject in the live heap, or represents a previously existing JSObject + // from some deserialized heap snapshot. + + // Return the object's [[Class]]'s name. virtual const char* jsObjectClassName() const { return nullptr; } + // If this object was constructed with `new` and we have the data available, + // place the contructor function's display name in the out parameter. + // Otherwise, place nullptr in the out parameter. Caller maintains ownership + // of the out parameter. True is returned on success, false is returned on + // OOM. + virtual bool jsObjectConstructorName(JSContext* cx, + UniquePtr& outName) const { + outName.reset(nullptr); + return true; + } + private: Base(const Base& rhs) = delete; Base& operator=(const Base& rhs) = delete; @@ -336,6 +353,10 @@ class Node { JS::Zone* zone() const { return base()->zone(); } JSCompartment* compartment() const { return base()->compartment(); } const char* jsObjectClassName() const { return base()->jsObjectClassName(); } + bool jsObjectConstructorName(JSContext* cx, + UniquePtr& outName) const { + return base()->jsObjectConstructorName(cx, outName); + } size_t size(mozilla::MallocSizeOf mallocSizeof) const { return base()->size(mallocSizeof); @@ -574,6 +595,8 @@ template<> struct Concrete : TracerConcreteWithCompartment { template<> class Concrete : public TracerConcreteWithCompartment { const char* jsObjectClassName() const override; + bool jsObjectConstructorName(JSContext* cx, + UniquePtr& outName) const override; size_t size(mozilla::MallocSizeOf mallocSizeOf) const override; protected: diff --git a/js/src/jsapi-tests/testUbiNode.cpp b/js/src/jsapi-tests/testUbiNode.cpp index 79925aae143..566efc80fa8 100644 --- a/js/src/jsapi-tests/testUbiNode.cpp +++ b/js/src/jsapi-tests/testUbiNode.cpp @@ -88,3 +88,18 @@ BEGIN_TEST(test_ubiNodeCompartment) return true; } END_TEST(test_ubiNodeCompartment) + +BEGIN_TEST(test_ubiNodeJSObjectConstructorName) +{ + JS::RootedValue val(cx); + EVAL("this.Ctor = function Ctor() {}; new Ctor", &val); + CHECK(val.isObject()); + + mozilla::UniquePtr ctorName; + CHECK(JS::ubi::Node(&val.toObject()).jsObjectConstructorName(cx, ctorName)); + CHECK(ctorName); + CHECK(js_strcmp(ctorName.get(), MOZ_UTF16("Ctor")) == 0); + + return true; +} +END_TEST(test_ubiNodeJSObjectConstructorName) diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index ee96b2e2ad2..139e3ad4d73 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -8,6 +8,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/Range.h" #include "mozilla/Scoped.h" #include "mozilla/UniquePtr.h" @@ -32,6 +33,7 @@ #include "vm/Debugger-inl.h" using mozilla::Some; +using mozilla::UniquePtr; using JS::HandleValue; using JS::Value; using JS::ZoneSet; @@ -228,6 +230,31 @@ Concrete::jsObjectClassName() const return Concrete::get().getClass()->name; } +bool +Concrete::jsObjectConstructorName(JSContext* cx, + UniquePtr& outName) const +{ + JSAtom* name = Concrete::get().maybeConstructorDisplayAtom(); + if (!name) { + outName.reset(nullptr); + return true; + } + + auto len = JS_GetStringLength(name); + auto size = len + 1; + + outName.reset(cx->pod_malloc(size * sizeof(char16_t))); + if (!outName) + return false; + + mozilla::Range chars(outName.get(), size); + if (!JS_CopyStringChars(cx, chars, name)) + return false; + + outName[len] = '\0'; + return true; +} + template<> const char16_t TracerConcrete::concreteTypeName[] = MOZ_UTF16("JS::Symbol"); template<> const char16_t TracerConcrete::concreteTypeName[] = From 4812be37bccda4164e1516154d6a762254a758ac Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 27 Apr 2015 10:58:24 -0700 Subject: [PATCH 16/80] Bug 1158257 - Gecko should always provide SpiderMonkey with a debuggerMallocSizeOf; r=mccr8 --- xpcom/base/CycleCollectedJSRuntime.cpp | 3 ++ .../unit/test_debugger_malloc_size_of.js | 34 +++++++++++++++++++ xpcom/tests/unit/xpcshell.ini | 1 + 3 files changed, 38 insertions(+) create mode 100644 xpcom/tests/unit/test_debugger_malloc_size_of.js diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index bd911987e70..283acec1458 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -64,6 +64,7 @@ #include "mozilla/dom/DOMJSClass.h" #include "mozilla/dom/ScriptSettings.h" #include "jsprf.h" +#include "js/Debug.h" #include "nsCycleCollectionNoteRootCallback.h" #include "nsCycleCollectionParticipant.h" #include "nsCycleCollector.h" @@ -503,6 +504,8 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSRuntime* aParentRuntime, }; SetDOMCallbacks(mJSRuntime, &DOMcallbacks); + JS::dbg::SetDebuggerMallocSizeOf(mJSRuntime, moz_malloc_size_of); + nsCycleCollector_registerJSRuntime(this); } diff --git a/xpcom/tests/unit/test_debugger_malloc_size_of.js b/xpcom/tests/unit/test_debugger_malloc_size_of.js new file mode 100644 index 00000000000..f69eba3b1d1 --- /dev/null +++ b/xpcom/tests/unit/test_debugger_malloc_size_of.js @@ -0,0 +1,34 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* 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/. */ + +// This is just a sanity test that Gecko is giving SpiderMonkey a MallocSizeOf +// function for new JSRuntimes. There is more extensive testing around the +// expected byte sizes within SpiderMonkey's jit-tests, we just want to make +// sure that Gecko is providing SpiderMonkey with the callback it needs. + +const Cu = Components.utils; +const { byteSize } = Cu.getJSTestingFunctions(); + +function run_test() +{ + const objects = [ + {}, + { w: 1, x: 2, y: 3, z:4, a: 5 }, + [], + Array(10).fill(null), + new RegExp("(2|two) problems", "g"), + new Date(), + new Uint8Array(64), + Promise.resolve(1), + function f() {}, + Object + ]; + + for (let obj of objects) { + do_print(uneval(obj)); + ok(byteSize(obj), "We should get some (non-zero) byte size"); + } +} diff --git a/xpcom/tests/unit/xpcshell.ini b/xpcom/tests/unit/xpcshell.ini index b9cf193a634..371b8a846a5 100644 --- a/xpcom/tests/unit/xpcshell.ini +++ b/xpcom/tests/unit/xpcshell.ini @@ -27,6 +27,7 @@ fail-if = os == "android" # Bug 676998: test fails consistently on Android fail-if = os == "android" [test_bug725015.js] +[test_debugger_malloc_size_of.js] [test_compmgr_warnings.js] # Bug 676998: test fails consistently on Android fail-if = os == "android" From 08c48e40ef508718ce770a38094a531506fc66f1 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 27 Apr 2015 14:04:24 -0400 Subject: [PATCH 17/80] Backed out changeset c839f283bf28 (bug 1058695) for bustage. CLOSED TREE --- dom/base/nsGlobalWindow.cpp | 2 -- dom/base/nsIGlobalObject.h | 34 ----------------------------- dom/promise/Promise.cpp | 24 ++------------------- dom/promise/PromiseCallback.cpp | 36 ++++++++++++++----------------- dom/promise/PromiseCallback.h | 20 ++++++++--------- js/src/jsapi.cpp | 6 ------ js/src/jsapi.h | 4 +--- js/xpconnect/src/XPCJSRuntime.cpp | 7 +----- 8 files changed, 30 insertions(+), 103 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 5a0670bb0f2..8f7100be18a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1439,8 +1439,6 @@ nsGlobalWindow::CleanUp() return; mCleanedUp = true; - StartDying(); - mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nullptr); mEventTargetObjects.Clear(); diff --git a/dom/base/nsIGlobalObject.h b/dom/base/nsIGlobalObject.h index 35794d49ea2..c5b28041acc 100644 --- a/dom/base/nsIGlobalObject.h +++ b/dom/base/nsIGlobalObject.h @@ -17,47 +17,13 @@ class nsIPrincipal; class nsIGlobalObject : public nsISupports { - bool mIsDying; - -protected: - nsIGlobalObject() - : mIsDying(false) - {} - public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID) - /** - * This check is added to deal with Promise microtask queues. On the main - * thread, we do not impose restrictions about when script stops running or - * when runnables can no longer be dispatched to the main thread. This means - * it is possible for a Promise chain to keep resolving an infinite chain of - * promises, preventing the browser from shutting down. See Bug 1058695. To - * prevent this, the nsGlobalWindow subclass sets this flag when it is - * closed. The Promise implementation checks this and prohibits new runnables - * from being dispatched. - * - * We pair this with checks during processing the promise microtask queue - * that pops up the slow script dialog when the Promise queue is preventing - * a window from going away. - */ - bool - IsDying() const - { - return mIsDying; - } - virtual JSObject* GetGlobalJSObject() = 0; // This method is not meant to be overridden. nsIPrincipal* PrincipalOrNull(); - -protected: - void - StartDying() - { - mIsDying = true; - } }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject, diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index 528a958cc60..b323e78491c 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -263,7 +263,7 @@ protected: // console though, for debugging. } - return rv.ErrorCode(); + return NS_OK; } private: @@ -489,24 +489,13 @@ Promise::PerformMicroTaskCheckpoint() return false; } - Maybe cx; - if (NS_IsMainThread()) { - cx.emplace(); - } - do { nsCOMPtr runnable = microtaskQueue.ElementAt(0); MOZ_ASSERT(runnable); // This function can re-enter, so we remove the element before calling. microtaskQueue.RemoveElementAt(0); - nsresult rv = runnable->Run(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - if (cx.isSome()) { - JS_CheckForInterrupt(cx.ref()); - } + runnable->Run(); } while (!microtaskQueue.IsEmpty()); return true; @@ -1082,10 +1071,6 @@ void Promise::AppendCallbacks(PromiseCallback* aResolveCallback, PromiseCallback* aRejectCallback) { - if (mGlobal->IsDying()) { - return; - } - MOZ_ASSERT(aResolveCallback); MOZ_ASSERT(aRejectCallback); @@ -1312,12 +1297,7 @@ Promise::RejectInternal(JSContext* aCx, void Promise::Settle(JS::Handle aValue, PromiseState aState) { - if (mGlobal->IsDying()) { - return; - } - mSettlementTimestamp = TimeStamp::Now(); - SetResult(aValue); SetState(aState); diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp index 195beba7b49..eff07757fe7 100644 --- a/dom/promise/PromiseCallback.cpp +++ b/dom/promise/PromiseCallback.cpp @@ -71,7 +71,7 @@ ResolvePromiseCallback::~ResolvePromiseCallback() DropJSObjects(this); } -nsresult +void ResolvePromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -81,11 +81,10 @@ ResolvePromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return NS_ERROR_FAILURE; + return; } mPromise->ResolveInternal(aCx, value); - return NS_OK; } // RejectPromiseCallback @@ -130,7 +129,7 @@ RejectPromiseCallback::~RejectPromiseCallback() DropJSObjects(this); } -nsresult +void RejectPromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -140,12 +139,11 @@ RejectPromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return NS_ERROR_FAILURE; + return; } mPromise->RejectInternal(aCx, value); - return NS_OK; } // WrapperPromiseCallback @@ -192,7 +190,7 @@ WrapperPromiseCallback::~WrapperPromiseCallback() DropJSObjects(this); } -nsresult +void WrapperPromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -200,7 +198,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return NS_ERROR_FAILURE; + return; } ErrorResult rv; @@ -221,7 +219,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return NS_ERROR_FAILURE; + return; } } else { // Convert the ErrorResult to a JS exception object that we can reject @@ -234,7 +232,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, } mNextPromise->RejectInternal(aCx, value); - return NS_OK; + return; } // If the return value is the same as the promise itself, throw TypeError. @@ -272,7 +270,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!fn) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return NS_ERROR_OUT_OF_MEMORY; + return; } JS::Rooted message(aCx, @@ -281,7 +279,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!message) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return NS_ERROR_OUT_OF_MEMORY; + return; } JS::Rooted typeError(aCx); @@ -289,22 +287,21 @@ WrapperPromiseCallback::Call(JSContext* aCx, nullptr, message, &typeError)) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return NS_ERROR_OUT_OF_MEMORY; + return; } mNextPromise->RejectInternal(aCx, typeError); - return NS_OK; + return; } } // Otherwise, run resolver's resolve with value. if (!JS_WrapValue(aCx, &retValue)) { NS_WARNING("Failed to wrap value into the right compartment."); - return NS_ERROR_FAILURE; + return; } mNextPromise->ResolveInternal(aCx, retValue); - return NS_OK; } // NativePromiseCallback @@ -330,22 +327,21 @@ NativePromiseCallback::~NativePromiseCallback() { } -nsresult +void NativePromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { if (mState == Promise::Resolved) { mHandler->ResolvedCallback(aCx, aValue); - return NS_OK; + return; } if (mState == Promise::Rejected) { mHandler->RejectedCallback(aCx, aValue); - return NS_OK; + return; } NS_NOTREACHED("huh?"); - return NS_ERROR_FAILURE; } /* static */ PromiseCallback* diff --git a/dom/promise/PromiseCallback.h b/dom/promise/PromiseCallback.h index 1802556410b..64e870b1703 100644 --- a/dom/promise/PromiseCallback.h +++ b/dom/promise/PromiseCallback.h @@ -26,8 +26,8 @@ public: PromiseCallback(); - virtual nsresult Call(JSContext* aCx, - JS::Handle aValue) = 0; + virtual void Call(JSContext* aCx, + JS::Handle aValue) = 0; // Return the Promise that this callback will end up resolving or // rejecting, if any. @@ -54,8 +54,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback, PromiseCallback) - nsresult Call(JSContext* aCx, - JS::Handle aValue) override; + void Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -82,8 +82,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback, PromiseCallback) - nsresult Call(JSContext* aCx, - JS::Handle aValue) override; + void Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -108,8 +108,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback, PromiseCallback) - nsresult Call(JSContext* aCx, - JS::Handle aValue) override; + void Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -133,8 +133,8 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback, PromiseCallback) - nsresult Call(JSContext* aCx, - JS::Handle aValue) override; + void Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 02e16a09863..8b0e99ccb9e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4462,12 +4462,6 @@ JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs) return obj; } -JS_PUBLIC_API(bool) -JS_CheckForInterrupt(JSContext* cx) -{ - return js::CheckForInterrupt(cx); -} - JS_PUBLIC_API(JSInterruptCallback) JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index c148bedff6b..d00b608f602 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3948,10 +3948,8 @@ extern JS_PUBLIC_API(bool) Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args, MutableHandleValue rval); -} /* namespace JS */ -extern JS_PUBLIC_API(bool) -JS_CheckForInterrupt(JSContext* cx); +} /* namespace JS */ /* * These functions allow setting an interrupt callback that will be called diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 92be6580624..77f39d35f77 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1461,13 +1461,8 @@ XPCJSRuntime::InterruptCallback(JSContext* cx) win = WindowGlobalOrNull(proto); } } - - if (!win) { - NS_WARNING("No active window"); + if (!win) return true; - } - - MOZ_ASSERT(!win->IsDying()); if (win->GetIsPrerendered()) { // We cannot display a dialog if the page is being prerendered, so From 050302155bebc2f0f1eb0e42b2d903479732124a Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 27 Apr 2015 07:55:32 -0400 Subject: [PATCH 18/80] Bug 1158772 - fix non-idiomatic memset call in nsDeque.cpp; r=erahm Coverty complains that we're using sizeof(mData) here instead of sizeof(*mData). They're equivalent for all the architectures we care about, but go ahead and tidy up the syntax to silence the static analyzer. --- xpcom/glue/nsDeque.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpcom/glue/nsDeque.cpp b/xpcom/glue/nsDeque.cpp index 41d9337c481..6e4be8aa279 100644 --- a/xpcom/glue/nsDeque.cpp +++ b/xpcom/glue/nsDeque.cpp @@ -135,7 +135,7 @@ void nsDeque::Empty() { if (mSize && mData) { - memset(mData, 0, mCapacity * sizeof(mData)); + memset(mData, 0, mCapacity * sizeof(*mData)); } mSize = 0; mOrigin = 0; From 1bcb2521b793c4e1be6b21c21aac263f3fc6c459 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 27 Apr 2015 13:08:12 -0400 Subject: [PATCH 19/80] Bug 1158896 - prevent dead code from being generated in lower.py; r=bent Coverity was complaining that we have things like: if ((!(actor))) { return false; } if ((!(actor))) { return false; } in the generated code, as the second return will clearly never be hit. To address this, let's remove a redundant call to dtorPrologue. --- ipc/ipdl/ipdl/lower.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ipc/ipdl/ipdl/lower.py b/ipc/ipdl/ipdl/lower.py index e4013dc13e3..05fbe19e74b 100644 --- a/ipc/ipdl/ipdl/lower.py +++ b/ipc/ipdl/ipdl/lower.py @@ -4972,7 +4972,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor): actorvar = actor.var() method = MethodDefn(self.makeDtorMethodDecl(md)) - method.addstmts(self.dtorPrologue(actor.var())) method.addstmts(self.dtorPrologue(actorvar)) msgvar, stmts = self.makeMessage(md, errfnSendDtor, actorvar) From 14c2a5a95ab757bb30ae7e1828836b7745166f39 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Mon, 27 Apr 2015 11:35:10 -0700 Subject: [PATCH 20/80] Bug 1157648 - Make nsScriptError::ToString use only the first 512 characters of mSourceName and mSourceLine. r=bholley This means that when mSourceName and mSourceLine are large, ToString is not excessively expensive. This is particularly important for CSS errors, where we don't make an attempt to truncate these prior to constructing the script error, but we do ensure that when we report multiple errors on the same line (which is common for minified CSS), we share from the same string buffer and avoid copying. --- js/xpconnect/src/nsScriptError.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/xpconnect/src/nsScriptError.cpp b/js/xpconnect/src/nsScriptError.cpp index 887c61b5126..426c67107c2 100644 --- a/js/xpconnect/src/nsScriptError.cpp +++ b/js/xpconnect/src/nsScriptError.cpp @@ -203,9 +203,11 @@ nsScriptError::ToString(nsACString& /*UTF8*/ aResult) if (!mMessage.IsEmpty()) tempMessage = ToNewUTF8String(mMessage); if (!mSourceName.IsEmpty()) - tempSourceName = ToNewUTF8String(mSourceName); + // Use at most 512 characters from mSourceName. + tempSourceName = ToNewUTF8String(StringHead(mSourceName, 512)); if (!mSourceLine.IsEmpty()) - tempSourceLine = ToNewUTF8String(mSourceLine); + // Use at most 512 characters from mSourceLine. + tempSourceLine = ToNewUTF8String(StringHead(mSourceLine, 512)); if (nullptr != tempSourceName && nullptr != tempSourceLine) temp = JS_smprintf(format0, From 27cb15e0ef0673240320c62a3989060da11e6f44 Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Mon, 27 Apr 2015 12:00:41 -0700 Subject: [PATCH 21/80] Bug 1058695 - Add member to nsIGlobalObject to detect it is going away. Make promises use it. r=bholley --- dom/base/nsGlobalWindow.cpp | 2 ++ dom/base/nsIGlobalObject.h | 34 +++++++++++++++++++++++++++++ dom/promise/Promise.cpp | 24 +++++++++++++++++++-- dom/promise/PromiseCallback.cpp | 36 +++++++++++++++++-------------- dom/promise/PromiseCallback.h | 20 ++++++++--------- js/src/jsapi.cpp | 6 ++++++ js/src/jsapi.h | 4 +++- js/xpconnect/src/XPCJSRuntime.cpp | 7 +++++- 8 files changed, 103 insertions(+), 30 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8f7100be18a..5a0670bb0f2 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1439,6 +1439,8 @@ nsGlobalWindow::CleanUp() return; mCleanedUp = true; + StartDying(); + mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nullptr); mEventTargetObjects.Clear(); diff --git a/dom/base/nsIGlobalObject.h b/dom/base/nsIGlobalObject.h index c5b28041acc..35794d49ea2 100644 --- a/dom/base/nsIGlobalObject.h +++ b/dom/base/nsIGlobalObject.h @@ -17,13 +17,47 @@ class nsIPrincipal; class nsIGlobalObject : public nsISupports { + bool mIsDying; + +protected: + nsIGlobalObject() + : mIsDying(false) + {} + public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID) + /** + * This check is added to deal with Promise microtask queues. On the main + * thread, we do not impose restrictions about when script stops running or + * when runnables can no longer be dispatched to the main thread. This means + * it is possible for a Promise chain to keep resolving an infinite chain of + * promises, preventing the browser from shutting down. See Bug 1058695. To + * prevent this, the nsGlobalWindow subclass sets this flag when it is + * closed. The Promise implementation checks this and prohibits new runnables + * from being dispatched. + * + * We pair this with checks during processing the promise microtask queue + * that pops up the slow script dialog when the Promise queue is preventing + * a window from going away. + */ + bool + IsDying() const + { + return mIsDying; + } + virtual JSObject* GetGlobalJSObject() = 0; // This method is not meant to be overridden. nsIPrincipal* PrincipalOrNull(); + +protected: + void + StartDying() + { + mIsDying = true; + } }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject, diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index b323e78491c..f424e19c07f 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -263,7 +263,7 @@ protected: // console though, for debugging. } - return NS_OK; + return rv.StealNSResult(); } private: @@ -489,13 +489,24 @@ Promise::PerformMicroTaskCheckpoint() return false; } + Maybe cx; + if (NS_IsMainThread()) { + cx.emplace(); + } + do { nsCOMPtr runnable = microtaskQueue.ElementAt(0); MOZ_ASSERT(runnable); // This function can re-enter, so we remove the element before calling. microtaskQueue.RemoveElementAt(0); - runnable->Run(); + nsresult rv = runnable->Run(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + if (cx.isSome()) { + JS_CheckForInterrupt(cx.ref()); + } } while (!microtaskQueue.IsEmpty()); return true; @@ -1071,6 +1082,10 @@ void Promise::AppendCallbacks(PromiseCallback* aResolveCallback, PromiseCallback* aRejectCallback) { + if (mGlobal->IsDying()) { + return; + } + MOZ_ASSERT(aResolveCallback); MOZ_ASSERT(aRejectCallback); @@ -1297,7 +1312,12 @@ Promise::RejectInternal(JSContext* aCx, void Promise::Settle(JS::Handle aValue, PromiseState aState) { + if (mGlobal->IsDying()) { + return; + } + mSettlementTimestamp = TimeStamp::Now(); + SetResult(aValue); SetState(aState); diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp index eff07757fe7..195beba7b49 100644 --- a/dom/promise/PromiseCallback.cpp +++ b/dom/promise/PromiseCallback.cpp @@ -71,7 +71,7 @@ ResolvePromiseCallback::~ResolvePromiseCallback() DropJSObjects(this); } -void +nsresult ResolvePromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -81,10 +81,11 @@ ResolvePromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } mPromise->ResolveInternal(aCx, value); + return NS_OK; } // RejectPromiseCallback @@ -129,7 +130,7 @@ RejectPromiseCallback::~RejectPromiseCallback() DropJSObjects(this); } -void +nsresult RejectPromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -139,11 +140,12 @@ RejectPromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } mPromise->RejectInternal(aCx, value); + return NS_OK; } // WrapperPromiseCallback @@ -190,7 +192,7 @@ WrapperPromiseCallback::~WrapperPromiseCallback() DropJSObjects(this); } -void +nsresult WrapperPromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { @@ -198,7 +200,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, JS::Rooted value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } ErrorResult rv; @@ -219,7 +221,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } } else { // Convert the ErrorResult to a JS exception object that we can reject @@ -232,7 +234,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, } mNextPromise->RejectInternal(aCx, value); - return; + return NS_OK; } // If the return value is the same as the promise itself, throw TypeError. @@ -270,7 +272,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!fn) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return; + return NS_ERROR_OUT_OF_MEMORY; } JS::Rooted message(aCx, @@ -279,7 +281,7 @@ WrapperPromiseCallback::Call(JSContext* aCx, if (!message) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return; + return NS_ERROR_OUT_OF_MEMORY; } JS::Rooted typeError(aCx); @@ -287,21 +289,22 @@ WrapperPromiseCallback::Call(JSContext* aCx, nullptr, message, &typeError)) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); - return; + return NS_ERROR_OUT_OF_MEMORY; } mNextPromise->RejectInternal(aCx, typeError); - return; + return NS_OK; } } // Otherwise, run resolver's resolve with value. if (!JS_WrapValue(aCx, &retValue)) { NS_WARNING("Failed to wrap value into the right compartment."); - return; + return NS_ERROR_FAILURE; } mNextPromise->ResolveInternal(aCx, retValue); + return NS_OK; } // NativePromiseCallback @@ -327,21 +330,22 @@ NativePromiseCallback::~NativePromiseCallback() { } -void +nsresult NativePromiseCallback::Call(JSContext* aCx, JS::Handle aValue) { if (mState == Promise::Resolved) { mHandler->ResolvedCallback(aCx, aValue); - return; + return NS_OK; } if (mState == Promise::Rejected) { mHandler->RejectedCallback(aCx, aValue); - return; + return NS_OK; } NS_NOTREACHED("huh?"); + return NS_ERROR_FAILURE; } /* static */ PromiseCallback* diff --git a/dom/promise/PromiseCallback.h b/dom/promise/PromiseCallback.h index 64e870b1703..1802556410b 100644 --- a/dom/promise/PromiseCallback.h +++ b/dom/promise/PromiseCallback.h @@ -26,8 +26,8 @@ public: PromiseCallback(); - virtual void Call(JSContext* aCx, - JS::Handle aValue) = 0; + virtual nsresult Call(JSContext* aCx, + JS::Handle aValue) = 0; // Return the Promise that this callback will end up resolving or // rejecting, if any. @@ -54,8 +54,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -82,8 +82,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -108,8 +108,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { @@ -133,8 +133,8 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback, PromiseCallback) - void Call(JSContext* aCx, - JS::Handle aValue) override; + nsresult Call(JSContext* aCx, + JS::Handle aValue) override; Promise* GetDependentPromise() override { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8b0e99ccb9e..02e16a09863 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4462,6 +4462,12 @@ JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs) return obj; } +JS_PUBLIC_API(bool) +JS_CheckForInterrupt(JSContext* cx) +{ + return js::CheckForInterrupt(cx); +} + JS_PUBLIC_API(JSInterruptCallback) JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d00b608f602..c148bedff6b 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3948,9 +3948,11 @@ extern JS_PUBLIC_API(bool) Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args, MutableHandleValue rval); - } /* namespace JS */ +extern JS_PUBLIC_API(bool) +JS_CheckForInterrupt(JSContext* cx); + /* * These functions allow setting an interrupt callback that will be called * from the JS thread some time after any thread triggered the callback using diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 77f39d35f77..92be6580624 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1461,8 +1461,13 @@ XPCJSRuntime::InterruptCallback(JSContext* cx) win = WindowGlobalOrNull(proto); } } - if (!win) + + if (!win) { + NS_WARNING("No active window"); return true; + } + + MOZ_ASSERT(!win->IsDying()); if (win->GetIsPrerendered()) { // We cannot display a dialog if the page is being prerendered, so From bb5762dcf61ebeacc8942824fb5c651656cf955e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 27 Apr 2015 15:08:10 -0400 Subject: [PATCH 22/80] Bug 1158920 - Yield to the event loop before reading the spelling suggestions --- editor/libeditor/tests/test_bug1154791.html | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/editor/libeditor/tests/test_bug1154791.html b/editor/libeditor/tests/test_bug1154791.html index 4c3a3ebcac5..12c76206112 100644 --- a/editor/libeditor/tests/test_bug1154791.html +++ b/editor/libeditor/tests/test_bug1154791.html @@ -36,12 +36,14 @@ SimpleTest.waitForFocus(function() { setTimeout(function() { synthesizeKey(" ", {}); - var sel = getSpellCheckSelection(); - is(sel.rangeCount, 2, "We should have two misspelled words"); - is(String(sel.getRangeAt(0)), "thiss", "Correct misspelled word"); - is(String(sel.getRangeAt(1)), "onee", "Correct misspelled word"); + setTimeout(function() { + var sel = getSpellCheckSelection(); + is(sel.rangeCount, 2, "We should have two misspelled words"); + is(String(sel.getRangeAt(0)), "thiss", "Correct misspelled word"); + is(String(sel.getRangeAt(1)), "onee", "Correct misspelled word"); - SimpleTest.finish(); + SimpleTest.finish(); + },0); },0); },0); From 3c61b43f0223faa7205ac43bea30d1a84d0daa0e Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 27 Apr 2015 14:59:17 -0400 Subject: [PATCH 23/80] Bug 1157936 - Put the correct ratio on the scrollbar layer. r=tn --- layout/xul/nsSliderFrame.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index cafc37dbd43..9ad1d07e7ac 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -333,7 +333,6 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder, uint32_t flags = 0; mozilla::layers::FrameMetrics::ViewID scrollTargetId = mozilla::layers::FrameMetrics::NULL_SCROLL_ID; - float scrollbarThumbRatio = 0.0f; aBuilder->GetScrollbarInfo(&scrollTargetId, &flags); bool thumbGetsLayer = (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID); nsLayoutUtils::SetScrollbarThumbLayerization(thumb, thumbGetsLayer); @@ -355,7 +354,7 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder, // Wrap the list to make it its own layer. aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayOwnLayer(aBuilder, this, &masterList, flags, scrollTargetId, - scrollbarThumbRatio)); + GetThumbRatio())); return; } From f21de90e5bfa9f0a1c3de1a61a13599beaed47b4 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 27 Apr 2015 15:29:22 -0400 Subject: [PATCH 24/80] Bug 1158452. Pass in the right node when messing with font sizes in editor. r=ehsan --- editor/libeditor/crashtests/1158452.html | 10 ++++++++++ editor/libeditor/crashtests/crashtests.list | 1 + editor/libeditor/nsHTMLEditorStyle.cpp | 5 +---- 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 editor/libeditor/crashtests/1158452.html diff --git a/editor/libeditor/crashtests/1158452.html b/editor/libeditor/crashtests/1158452.html new file mode 100644 index 00000000000..56c74abd612 --- /dev/null +++ b/editor/libeditor/crashtests/1158452.html @@ -0,0 +1,10 @@ + +
+
+aaaaaaa + + diff --git a/editor/libeditor/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list index 03bf9d7ca9a..ae8e2a391c7 100644 --- a/editor/libeditor/crashtests/crashtests.list +++ b/editor/libeditor/crashtests/crashtests.list @@ -61,3 +61,4 @@ needs-focus load 793866.html load 1057677.html needs-focus load 1128787.html load 1134545.html +load 1158452.html diff --git a/editor/libeditor/nsHTMLEditorStyle.cpp b/editor/libeditor/nsHTMLEditorStyle.cpp index 9eaf2d485a9..5e06917afe5 100644 --- a/editor/libeditor/nsHTMLEditorStyle.cpp +++ b/editor/libeditor/nsHTMLEditorStyle.cpp @@ -1502,11 +1502,8 @@ nsHTMLEditor::RelativeFontChange(FontSize aDir) NS_ENSURE_SUCCESS(res, res); } if (IsTextNode(endNode) && IsEditable(endNode)) { - nsCOMPtr nodeAsText = do_QueryInterface(endNode); - int32_t endOffset; - range->GetEndOffset(&endOffset); res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1, - static_cast(startNode->AsDOMNode()), + static_cast(endNode->AsDOMNode()), 0, range->EndOffset()); NS_ENSURE_SUCCESS(res, res); } From 743ce3c39b98070ee058e57dc37e6c8c782b4dd3 Mon Sep 17 00:00:00 2001 From: Nathan Toone Date: Mon, 27 Apr 2015 14:23:00 -0600 Subject: [PATCH 25/80] Bug 1158931 - Fix static assertion compilation error; r=snorp Move the destructor for WebrtcAndroidMediaCodec to be protected instead of public. --- .../src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/media/webrtc/signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp b/media/webrtc/signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp index c74925126c6..bee26eac266 100644 --- a/media/webrtc/signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp +++ b/media/webrtc/signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp @@ -174,9 +174,6 @@ public: CSFLogDebug(logTag, "%s ", __FUNCTION__); } - virtual ~WebrtcAndroidMediaCodec() { - } - nsresult Configure(uint32_t width, uint32_t height, const jobject aSurface, @@ -507,6 +504,10 @@ public: mEncoderCallback = aCallback; } +protected: + virtual ~WebrtcAndroidMediaCodec() { + } + private: class OutputDrain : public MediaCodecOutputDrain { From ea83c403508d68b8e7e2f3cff4de6e7e7e7fb32b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 27 Apr 2015 16:13:29 -0400 Subject: [PATCH 26/80] Bug 1154739 - Rename flag to be more general. r=billm --- widget/nsBaseWidget.cpp | 2 +- widget/nsBaseWidget.h | 4 +--- widget/nsWidgetInitData.h | 7 +++---- xpfe/appshell/nsAppShellService.cpp | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 20641f6712f..edab43a905a 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -295,7 +295,7 @@ void nsBaseWidget::BaseCreate(nsIWidget *aParent, mBorderStyle = aInitData->mBorderStyle; mPopupLevel = aInitData->mPopupLevel; mPopupType = aInitData->mPopupHint; - mRequireOffMainThreadCompositing = aInitData->mRequireOffMainThreadCompositing; + mMultiProcessWindow = aInitData->mMultiProcessWindow; } if (aParent) { diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index ba8c4eaff92..63747e42648 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -482,9 +482,7 @@ protected: nsBorderStyle mBorderStyle; bool mUseLayersAcceleration; bool mForceLayersAcceleration; - // Windows with out-of-process tabs always require OMTC. This flag designates - // such windows. - bool mRequireOffMainThreadCompositing; + bool mMultiProcessWindow; bool mUseAttachedEvents; nsIntRect mBounds; nsIntRect* mOriginalBounds; diff --git a/widget/nsWidgetInitData.h b/widget/nsWidgetInitData.h index 12dd1d6ecb6..ea65de9e9f6 100644 --- a/widget/nsWidgetInitData.h +++ b/widget/nsWidgetInitData.h @@ -105,7 +105,7 @@ struct nsWidgetInitData { mIsAnimationSuppressed(false), mSupportTranslucency(false), mMouseTransparent(false), - mRequireOffMainThreadCompositing(false) + mMultiProcessWindow(false) { } @@ -127,9 +127,8 @@ struct nsWidgetInitData { // true if the window should be transparent to mouse events. Currently this is // only valid for eWindowType_popup widgets bool mMouseTransparent; - // Windows with out-of-process tabs always require OMTC. This flag designates - // such windows. - bool mRequireOffMainThreadCompositing; + // This flag designates windows with out-of-process tabs. + bool mMultiProcessWindow; }; #endif // nsWidgetInitData_h__ diff --git a/xpfe/appshell/nsAppShellService.cpp b/xpfe/appshell/nsAppShellService.cpp index 9375a097425..b4e30479b52 100644 --- a/xpfe/appshell/nsAppShellService.cpp +++ b/xpfe/appshell/nsAppShellService.cpp @@ -527,7 +527,7 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent, widgetInitData.mIsAnimationSuppressed = true; if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW) - widgetInitData.mRequireOffMainThreadCompositing = true; + widgetInitData.mMultiProcessWindow = true; #ifdef XP_MACOSX // Mac OS X sheet support From 9e778de02ea444a9fb0f21f54e65c584fd56bb9a Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 27 Apr 2015 16:13:29 -0400 Subject: [PATCH 27/80] Bug 1154739 - On desktop platforms, only enable APZ in e10s windows. r=dvander,mstange --- widget/cocoa/nsChildView.h | 1 + widget/cocoa/nsChildView.mm | 10 ++++++++++ widget/nsBaseWidget.cpp | 10 ++++++++++ widget/nsBaseWidget.h | 1 + 4 files changed, 22 insertions(+) diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index c1f8c470983..c2bafd79a49 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -479,6 +479,7 @@ public: #endif virtual void CreateCompositor() override; + virtual bool IsMultiProcessWindow() override; virtual void PrepareWindowEffects() override; virtual void CleanupWindowEffects() override; virtual bool PreRender(LayerManagerComposite* aManager) override; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 14025a56f04..9c4c55d444d 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1885,6 +1885,16 @@ nsChildView::CreateCompositor() } } +bool +nsChildView::IsMultiProcessWindow() +{ + // On OS X the XULWindowWidget object gets the widget's init-data, which + // is what has the electrolysis window flag. So here in the child view + // we need to get the flag from that window instead. + nsCocoaWindow* parent = GetXULWindowWidget(); + return parent ? parent->IsMultiProcessWindow() : false; +} + void nsChildView::ConfigureAPZCTreeManager() { diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index edab43a905a..ca155f46363 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -953,6 +953,10 @@ private: nsRefPtr mTreeManager; }; +bool nsBaseWidget::IsMultiProcessWindow() +{ + return mMultiProcessWindow; +} void nsBaseWidget::ConfigureAPZCTreeManager() { @@ -1145,6 +1149,12 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) mCompositorParent->SetOtherProcessId(base::GetCurrentProcId()); if (gfxPrefs::AsyncPanZoomEnabled() && +#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_GTK) + // For desktop platforms we only want to use APZ in e10s-enabled windows. + // If we ever get input events off the main thread we can consider + // relaxing this requirement. + IsMultiProcessWindow() && +#endif (WindowType() == eWindowType_toplevel || WindowType() == eWindowType_child)) { ConfigureAPZCTreeManager(); } diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 63747e42648..ee34d08e446 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -154,6 +154,7 @@ public: virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight); virtual void CreateCompositor(); virtual void CreateCompositor(int aWidth, int aHeight); + virtual bool IsMultiProcessWindow(); virtual void PrepareWindowEffects() override {} virtual void CleanupWindowEffects() override {} virtual bool PreRender(LayerManagerComposite* aManager) override { return true; } From fc307748863130be448249d7b0df0bf8bd7ed757 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 23 Apr 2015 16:59:12 +0100 Subject: [PATCH 28/80] Bug 1157253: Port ListenerProxy to use Proxy instead of __noSuchMethod__ r=chmanchester --- testing/marionette/driver.js | 66 +++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js index ddb5089196a..fc522e94626 100644 --- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -96,7 +96,7 @@ this.Context.fromString = function(s) { * passed literally. The latter specialisation is temporary to achieve * backwards compatibility with listener.js. * - * @param {function(): nsIMessageManager} mmFn + * @param {function(): (nsIMessageSender|nsIMessageBroadcaster)} mmFn * Function returning the current message manager. * @param {function(string, Object, number)} sendAsyncFn * Callback for sending async messages to the current listener. @@ -104,6 +104,34 @@ this.Context.fromString = function(s) { * Function that returns the current browser. */ let ListenerProxy = function(mmFn, sendAsyncFn, curBrowserFn) { + let sender = new ContentSender(mmFn, sendAsyncFn, curBrowserFn); + let handler = { + set: (obj, prop, val) => { obj[prop] = val; return true; }, + get: (obj, prop) => (...args) => obj.send(prop, args), + }; + return new Proxy(sender, handler); +}; + +/** + * The ContentSender allows one to make synchronous calls to the + * message listener of the content frame of the current browsing context. + * + * Presumptions about the responses from content space are made so we + * can provide a nicer API on top of the message listener primitives that + * make calls from chrome- to content space seem synchronous by leveraging + * promises. + * + * The promise is guaranteed not to resolve until the execution of the + * command in content space is complete. + * + * @param {function(): (nsIMessageSender|nsIMessageBroadcaster)} mmFn + * Function returning the current message manager. + * @param {function(string, Object, number)} sendAsyncFn + * Callback for sending async messages to the current listener. + * @param {function(): BrowserObj} curBrowserFn + * Function that returns the current browser. + */ +let ContentSender = function(mmFn, sendAsyncFn, curBrowserFn) { this.curCmdId = null; this.sendAsync = sendAsyncFn; @@ -111,15 +139,30 @@ let ListenerProxy = function(mmFn, sendAsyncFn, curBrowserFn) { this.curBrowserFn_ = curBrowserFn; }; -Object.defineProperty(ListenerProxy.prototype, "mm", { +Object.defineProperty(ContentSender.prototype, "mm", { get: function() { return this.mmFn_(); } }); -Object.defineProperty(ListenerProxy.prototype, "curBrowser", { +Object.defineProperty(ContentSender.prototype, "curBrowser", { get: function() { return this.curBrowserFn_(); } }); -ListenerProxy.prototype.__noSuchMethod__ = function*(name, args) { +/** + * Call registered function in the frame script environment of the + * current browsing context's content frame. + * + * @param {string} name + * Function to call in the listener, e.g. for "Marionette:foo8", + * use "foo". + * @param {Array} args + * Argument list to pass the function. If args has a single entry + * that is an object, we assume it's an old style dispatch, and + * the object will passed literally. + * + * @return {Promise} + * A promise that resolves to the result of the command. + */ +ContentSender.prototype.send = function(name, args) { const ok = "Marionette:ok"; const val = "Marionette:done"; const err = "Marionette:error"; @@ -169,12 +212,11 @@ ListenerProxy.prototype.__noSuchMethod__ = function*(name, args) { listeners.add(); modal.addHandler(handleDialog); - // convert to array if passed arguments - let msg; - if (args.length == 1 && typeof args[0] == "object" && args[0] !== null) { + // new style dispatches are arrays of arguments, old style dispatches + // are key-value objects + let msg = args; + if (args.length == 1 && typeof args[0] == "object") { msg = args[0]; - } else { - msg = Array.prototype.slice.call(args); } this.sendAsync(name, msg, this.curCmdId); @@ -183,7 +225,7 @@ ListenerProxy.prototype.__noSuchMethod__ = function*(name, args) { return proxy; }; -ListenerProxy.prototype.isOutOfSync = function(id) { +ContentSender.prototype.isOutOfSync = function(id) { return this.curCmdId !== id; }; @@ -268,7 +310,7 @@ this.GeckoDriver = function(appName, device, emulator) { }; this.mm = globalMessageManager; - this.listener = new ListenerProxy( + this.listener = ListenerProxy( () => this.mm, this.sendAsync.bind(this), () => this.curBrowser); @@ -1281,7 +1323,7 @@ GeckoDriver.prototype.get = function(cmd, resp) { // We need to re-issue this request to correctly poll for readyState and // send errors. this.curBrowser.pendingCommands.push(() => { - cmd.parameters.command_id = this.listener.curCmdId; + cmd.parameters.command_id = cmd.id; this.mm.broadcastAsyncMessage( "Marionette:pollForReadyState" + this.curBrowser.curFrameId, cmd.parameters); From 33b1c7c3da7357df2d1f5985def6a991d011cb52 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 27 Apr 2015 13:19:17 -0700 Subject: [PATCH 29/80] Bug 1149476 - Lengthen timeout because we are hitting it with SM(cgc), r=me (also jonco for a more complex version) The previous attempt seemed to cause problems with preventing the test script from exiting, which I was defending against by closing all file descriptors (even though I wasn't sure if it was necessary.) Sadly, I have no way to report the failure, but for now just lengthening the timeout seems like the simplest to make the intermittents go away. --- js/src/devtools/automation/autospider.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/devtools/automation/autospider.sh b/js/src/devtools/automation/autospider.sh index 73a212d584c..e24ae497e87 100755 --- a/js/src/devtools/automation/autospider.sh +++ b/js/src/devtools/automation/autospider.sh @@ -12,7 +12,7 @@ function usage() { clean=1 platform="" -TIMEOUT=7200 +TIMEOUT=3h while [ $# -gt 1 ]; do case "$1" in --dep) From c3dc3e7a662b239c57d57a5df7b2df77bba341f4 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 24 Apr 2015 17:16:46 -0400 Subject: [PATCH 30/80] Bug 1154703. Avoid using WARP if nvdxgiwrapper.dll is around. It seems to cause trouble and isn't really trustworthy. --- gfx/thebes/gfxWindowsPlatform.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index e26b63c0bc8..72e9800b704 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -1887,7 +1887,8 @@ gfxWindowsPlatform::InitD3D11Devices() if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status))) { if (status != nsIGfxInfo::FEATURE_STATUS_OK) { - if (gfxPrefs::LayersD3D11DisableWARP()) { + // It seems like nvdxgiwrapper makes a mess of WARP. See bug 1154703 for more. + if (gfxPrefs::LayersD3D11DisableWARP() || GetModuleHandleA("nvdxgiwrapper.dll")) { return; } From 9d5f48a9366fe34b70a48284683ad7bb6a957263 Mon Sep 17 00:00:00 2001 From: Philipp Kewisch Date: Mon, 27 Apr 2015 00:46:20 +0200 Subject: [PATCH 31/80] Bug 1153790 - mac unification doesn't work with packaged addons. r=glandium --- python/mozbuild/mozpack/test/test_unify.py | 85 ++++++++++++++++++++-- python/mozbuild/mozpack/unify.py | 41 ++++++++++- 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/python/mozbuild/mozpack/test/test_unify.py b/python/mozbuild/mozpack/test/test_unify.py index 95ae9088f16..a2bbb44702a 100644 --- a/python/mozbuild/mozpack/test/test_unify.py +++ b/python/mozbuild/mozpack/test/test_unify.py @@ -63,9 +63,19 @@ class TestUnifiedFinder(TestUnified): class TestUnifiedBuildFinder(TestUnified): def test_unified_build_finder(self): + finder = UnifiedBuildFinder(FileFinder(self.tmppath('a')), + FileFinder(self.tmppath('b'))) + + # Test chrome.manifest unification self.create_both('chrome.manifest', 'a\nb\nc\n') self.create_one('a', 'chrome/chrome.manifest', 'a\nb\nc\n') self.create_one('b', 'chrome/chrome.manifest', 'b\nc\na\n') + self.assertEqual(sorted([(f, c.open().read()) for f, c in + finder.find('**/chrome.manifest')]), + [('chrome.manifest', 'a\nb\nc\n'), + ('chrome/chrome.manifest', 'a\nb\nc\n')]) + + # Test buildconfig.html unification self.create_one('a', 'chrome/browser/foo/buildconfig.html', '\n'.join([ '', @@ -84,13 +94,6 @@ class TestUnifiedBuildFinder(TestUnified): '', '', ])) - finder = UnifiedBuildFinder(FileFinder(self.tmppath('a')), - FileFinder(self.tmppath('b'))) - self.assertEqual(sorted([(f, c.open().read()) for f, c in - finder.find('**/chrome.manifest')]), - [('chrome.manifest', 'a\nb\nc\n'), - ('chrome/chrome.manifest', 'a\nb\nc\n')]) - self.assertEqual(sorted([(f, c.open().read()) for f, c in finder.find('**/buildconfig.html')]), [('chrome/browser/foo/buildconfig.html', '\n'.join([ @@ -104,6 +107,7 @@ class TestUnifiedBuildFinder(TestUnified): '', ]))]) + # Test xpi file unification xpi = MockDest() with JarWriter(fileobj=xpi, compress=True) as jar: jar.add('foo', 'foo') @@ -123,6 +127,73 @@ class TestUnifiedBuildFinder(TestUnified): [('foo.xpi', foo_xpi)]) errors.out = sys.stderr + # Test install.rdf unification + x86_64 = 'Darwin_x86_64-gcc3' + x86 = 'Darwin_x86-gcc3' + target_tag = '<{em}targetPlatform>{platform}' + target_attr = '{em}targetPlatform="{platform}" ' + + rdf_tag = ''.join([ + '<{RDF}Description {em}bar="bar" {em}qux="qux">', + '<{em}foo>foo', + '{targets}', + '<{em}baz>baz', + '' + ]) + rdf_attr = ''.join([ + '<{RDF}Description {em}bar="bar" {attr}{em}qux="qux">', + '{targets}', + '<{em}foo>foo<{em}baz>baz', + '' + ]) + + for descr_ns, target_ns in (('RDF:', ''), ('', 'em:'), ('RDF:', 'em:')): + # First we need to infuse the above strings with our namespaces and + # platform values. + ns = { 'RDF': descr_ns, 'em': target_ns } + target_tag_x86_64 = target_tag.format(platform=x86_64, **ns) + target_tag_x86 = target_tag.format(platform=x86, **ns) + target_attr_x86_64 = target_attr.format(platform=x86_64, **ns) + target_attr_x86 = target_attr.format(platform=x86, **ns) + + tag_x86_64 = rdf_tag.format(targets=target_tag_x86_64, **ns) + tag_x86 = rdf_tag.format(targets=target_tag_x86, **ns) + tag_merged = rdf_tag.format(targets=target_tag_x86_64 + target_tag_x86, **ns) + tag_empty = rdf_tag.format(targets="", **ns) + + attr_x86_64 = rdf_attr.format(attr=target_attr_x86_64, targets="", **ns) + attr_x86 = rdf_attr.format(attr=target_attr_x86, targets="", **ns) + attr_merged = rdf_attr.format(attr="", targets=target_tag_x86_64 + target_tag_x86, **ns) + + # This table defines the test cases, columns "a" and "b" being the + # contents of the install.rdf of the respective platform and + # "result" the exepected merged content after unification. + testcases = ( + #_____a_____ _____b_____ ___result___# + (tag_x86_64, tag_x86, tag_merged ), + (tag_x86_64, tag_empty, tag_empty ), + (tag_empty, tag_x86, tag_empty ), + (tag_empty, tag_empty, tag_empty ), + + (attr_x86_64, attr_x86, attr_merged ), + (tag_x86_64, attr_x86, tag_merged ), + (attr_x86_64, tag_x86, attr_merged ), + + (attr_x86_64, tag_empty, tag_empty ), + (tag_empty, attr_x86, tag_empty ) + ) + + # Now create the files from the above table and compare + results = [] + for emid, (rdf_a, rdf_b, result) in enumerate(testcases): + filename = 'ext/id{0}/install.rdf'.format(emid) + self.create_one('a', filename, rdf_a) + self.create_one('b', filename, rdf_b) + results.append((filename, result)) + + self.assertEqual(sorted([(f, c.open().read()) for f, c in + finder.find('**/install.rdf')]), results) + if __name__ == '__main__': mozunit.main() diff --git a/python/mozbuild/mozpack/unify.py b/python/mozbuild/mozpack/unify.py index 215ae35434c..c7c8ab11ee8 100644 --- a/python/mozbuild/mozpack/unify.py +++ b/python/mozbuild/mozpack/unify.py @@ -18,9 +18,23 @@ from tempfile import mkstemp import mozpack.path as mozpath import struct import os +import re import subprocess from collections import OrderedDict +# Regular expressions for unifying install.rdf +FIND_TARGET_PLATFORM = re.compile(r""" + <(?P[-._0-9A-Za-z]+:)?targetPlatform> # The targetPlatform tag, with any namespace + (?P[^<]*) # The actual platform value + # The closing tag + """, re.X) +FIND_TARGET_PLATFORM_ATTR = re.compile(r""" + (?P<(?:[-._0-9A-Za-z]+:)?Description) # The opening part of the tag + (?P[^>]*?)\s+ # The initial attributes + (?P[-._0-9A-Za-z]+:)?targetPlatform= # The targetPlatform attribute, with any namespace + [\'"](?P[^\'"]+)[\'"] # The actual platform value + (?P[^>]*?>) # The remaining attributes and closing angle bracket + """, re.X) def may_unify_binary(file): ''' @@ -165,9 +179,11 @@ class UnifiedBuildFinder(UnifiedFinder): def unify_file(self, path, file1, file2): ''' - Unify buildconfig.html contents, or defer to UnifiedFinder.unify_file. + Unify files taking Mozilla application special cases into account. + Otherwise defer to UnifiedFinder.unify_file. ''' - if mozpath.basename(path) == 'buildconfig.html': + basename = mozpath.basename(path) + if basename == 'buildconfig.html': content1 = file1.open().readlines() content2 = file2.open().readlines() # Copy everything from the first file up to the end of its , @@ -178,7 +194,26 @@ class UnifiedBuildFinder(UnifiedFinder): ['
\n'] + content2[content2.index('

about:buildconfig

\n') + 1:] )) - if path.endswith('.xpi'): + elif basename == 'install.rdf': + # install.rdf files often have em:targetPlatform (either as + # attribute or as tag) that will differ between platforms. The + # unified install.rdf should contain both em:targetPlatforms if + # they exist, or strip them if only one file has a target platform. + content1, content2 = ( + FIND_TARGET_PLATFORM_ATTR.sub(lambda m: \ + m.group('tag') + m.group('attrs') + m.group('otherattrs') + + '<%stargetPlatform>%s' % \ + (m.group('ns') or "", m.group('platform'), m.group('ns') or ""), + f.open().read() + ) for f in (file1, file2) + ) + + platform2 = FIND_TARGET_PLATFORM.search(content2) + return GeneratedFile(FIND_TARGET_PLATFORM.sub( + lambda m: m.group(0) + platform2.group(0) if platform2 else '', + content1 + )) + elif path.endswith('.xpi'): finder1 = JarFinder(os.path.join(self._finder1.base, path), JarReader(fileobj=file1.open())) finder2 = JarFinder(os.path.join(self._finder2.base, path), From 3e58c4f5fe636f9909f7fc6e446970bb984e3da0 Mon Sep 17 00:00:00 2001 From: Emanuel Hoogeveen Date: Mon, 27 Apr 2015 07:28:00 -0400 Subject: [PATCH 32/80] Bug 949036 - Make ID3v2 tag detection more careful - not every bit of data containing "ID3" is a tag. r=eflores --- dom/media/MP3FrameParser.cpp | 63 ++++++++++++++++++----- dom/media/MP3FrameParser.h | 2 + dom/media/apple/AppleMP3Reader.cpp | 6 ++- dom/media/directshow/DirectShowReader.cpp | 9 +++- dom/media/gstreamer/GStreamerReader.cpp | 6 ++- dom/media/omx/MediaOmxReader.cpp | 7 ++- 6 files changed, 72 insertions(+), 21 deletions(-) diff --git a/dom/media/MP3FrameParser.cpp b/dom/media/MP3FrameParser.cpp index 9ead1cb3be2..0235ba0295e 100644 --- a/dom/media/MP3FrameParser.cpp +++ b/dom/media/MP3FrameParser.cpp @@ -178,36 +178,67 @@ MP3Parser::GetSamplesPerFrame() const char sID3Head[3] = { 'I', 'D', '3' }; const uint32_t ID3_HEADER_LENGTH = 10; +const uint32_t ID3_FOOTER_LENGTH = 10; +const uint8_t ID3_FOOTER_PRESENT = 0x10; ID3Parser::ID3Parser() : mCurrentChar(0) + , mVersion(0) + , mFlags(0) , mHeaderLength(0) { } void ID3Parser::Reset() { - mCurrentChar = mHeaderLength = 0; + mCurrentChar = mVersion = mFlags = mHeaderLength = 0; } bool ID3Parser::ParseChar(char ch) { - // First three bytes of an ID3v2 header must match the string "ID3". - if (mCurrentChar < sizeof(sID3Head) / sizeof(*sID3Head) - && ch != sID3Head[mCurrentChar]) { - goto fail; - } - - // The last four bytes of the header is a 28-bit unsigned integer with the - // high bit of each byte unset. - if (mCurrentChar >= 6 && mCurrentChar < ID3_HEADER_LENGTH) { - if (ch & 0x80) { - goto fail; - } else { + switch (mCurrentChar) { + // The first three bytes of an ID3v2 header must match the string "ID3". + case 0: case 1: case 2: + if (ch != sID3Head[mCurrentChar]) { + goto fail; + } + break; + // The fourth and fifth bytes give the version, between 2 and 4. + case 3: + if (ch < '\2' || ch > '\4') { + goto fail; + } + mVersion = uint8_t(ch); + break; + case 4: + if (ch != '\0') { + goto fail; + } + break; + // The sixth byte gives the flags; valid flags depend on the version. + case 5: + if ((ch & (0xff >> mVersion)) != '\0') { + goto fail; + } + mFlags = uint8_t(ch); + break; + // Bytes seven through ten give the sum of the byte length of the extended + // header, the padding and the frames after unsynchronisation. + // These bytes form a 28-bit integer, with the high bit of each byte unset. + case 6: case 7: case 8: case 9: + if (ch & 0x80) { + goto fail; + } mHeaderLength <<= 7; mHeaderLength |= ch; - } + if (mCurrentChar == 9) { + mHeaderLength += ID3_HEADER_LENGTH; + mHeaderLength += (mFlags & ID3_FOOTER_PRESENT) ? ID3_FOOTER_LENGTH : 0; + } + break; + default: + MOZ_CRASH("Header already fully parsed!"); } mCurrentChar++; @@ -215,6 +246,10 @@ ID3Parser::ParseChar(char ch) return IsParsed(); fail: + if (mCurrentChar) { + Reset(); + return ParseChar(ch); + } Reset(); return false; } diff --git a/dom/media/MP3FrameParser.h b/dom/media/MP3FrameParser.h index 9113e53b420..6e8c2fcf12d 100644 --- a/dom/media/MP3FrameParser.h +++ b/dom/media/MP3FrameParser.h @@ -29,6 +29,8 @@ public: private: uint32_t mCurrentChar; + uint8_t mVersion; + uint8_t mFlags; uint32_t mHeaderLength; }; diff --git a/dom/media/apple/AppleMP3Reader.cpp b/dom/media/apple/AppleMP3Reader.cpp index aaa980fb229..a6392ce5992 100644 --- a/dom/media/apple/AppleMP3Reader.cpp +++ b/dom/media/apple/AppleMP3Reader.cpp @@ -539,12 +539,16 @@ AppleMP3Reader::NotifyDataArrived(const char* aBuffer, } mMP3FrameParser.Parse(aBuffer, aLength, aOffset); + if (!mMP3FrameParser.IsMP3()) { + return; + } uint64_t duration = mMP3FrameParser.GetDuration(); if (duration != mDuration) { LOGD("Updating media duration to %lluus\n", duration); - mDuration = duration; + MOZ_ASSERT(mDecoder); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + mDuration = duration; mDecoder->UpdateEstimatedMediaDuration(duration); } } diff --git a/dom/media/directshow/DirectShowReader.cpp b/dom/media/directshow/DirectShowReader.cpp index b4e3c48ecd6..740b2dab2e8 100644 --- a/dom/media/directshow/DirectShowReader.cpp +++ b/dom/media/directshow/DirectShowReader.cpp @@ -409,15 +409,20 @@ void DirectShowReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) { MOZ_ASSERT(NS_IsMainThread()); + if (!mMP3FrameParser.NeedsData()) { + return; + } + + mMP3FrameParser.Parse(aBuffer, aLength, aOffset); if (!mMP3FrameParser.IsMP3()) { return; } - mMP3FrameParser.Parse(aBuffer, aLength, aOffset); + int64_t duration = mMP3FrameParser.GetDuration(); if (duration != mDuration) { - mDuration = duration; MOZ_ASSERT(mDecoder); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); + mDuration = duration; mDecoder->UpdateEstimatedMediaDuration(mDuration); } } diff --git a/dom/media/gstreamer/GStreamerReader.cpp b/dom/media/gstreamer/GStreamerReader.cpp index 8df45a5592e..fbd6d48822b 100644 --- a/dom/media/gstreamer/GStreamerReader.cpp +++ b/dom/media/gstreamer/GStreamerReader.cpp @@ -1278,19 +1278,21 @@ void GStreamerReader::NotifyDataArrived(const char *aBuffer, int64_t aOffset) { MOZ_ASSERT(NS_IsMainThread()); - if (HasVideo()) { return; } - if (!mMP3FrameParser.NeedsData()) { return; } mMP3FrameParser.Parse(aBuffer, aLength, aOffset); + if (!mMP3FrameParser.IsMP3()) { + return; + } int64_t duration = mMP3FrameParser.GetDuration(); if (duration != mLastParserDuration && mUseParserDuration) { + MOZ_ASSERT(mDecoder); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mLastParserDuration = duration; mDecoder->UpdateEstimatedMediaDuration(mLastParserDuration); diff --git a/dom/media/omx/MediaOmxReader.cpp b/dom/media/omx/MediaOmxReader.cpp index 8241074e52e..baf9f79aac8 100644 --- a/dom/media/omx/MediaOmxReader.cpp +++ b/dom/media/omx/MediaOmxReader.cpp @@ -491,15 +491,18 @@ void MediaOmxReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, in if (HasVideo()) { return; } - if (!mMP3FrameParser.NeedsData()) { return; } mMP3FrameParser.Parse(aBuffer, aLength, aOffset); + if (!mMP3FrameParser.IsMP3()) { + return; + } + int64_t duration = mMP3FrameParser.GetDuration(); - ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor()); if (duration != mLastParserDuration && mUseParserDuration) { + ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor()); mLastParserDuration = duration; decoder->UpdateEstimatedMediaDuration(mLastParserDuration); } From 72145bc9c8ca4e8eacdd8eb2df72dc9786d3ba9a Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Fri, 24 Apr 2015 14:53:00 -0400 Subject: [PATCH 33/80] Bug 1154041 - Enable child process memory report logging by default on B2G. r=erahm --- xpcom/base/nsMemoryReporterManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 9c6b9ab2ce6..f9b4092a893 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -1260,11 +1260,13 @@ nsMemoryReporterManager::~nsMemoryReporterManager() NS_ASSERTION(!mSavedWeakReporters, "failed to restore weak reporters"); } -//#define DEBUG_CHILD_PROCESS_MEMORY_REPORTING 1 +#ifdef MOZ_WIDGET_GONK +#define DEBUG_CHILD_PROCESS_MEMORY_REPORTING 1 +#endif #ifdef DEBUG_CHILD_PROCESS_MEMORY_REPORTING #define MEMORY_REPORTING_LOG(format, ...) \ - fprintf(stderr, "++++ MEMORY REPORTING: " format, ##__VA_ARGS__); + printf_stderr("++++ MEMORY REPORTING: " format, ##__VA_ARGS__); #else #define MEMORY_REPORTING_LOG(...) #endif From 945381a8a23dc0a47d6302053b3e57feb81d6bbd Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Fri, 24 Apr 2015 12:33:35 -0700 Subject: [PATCH 34/80] Bug 1158284 - Utility in gfxPlatform to check for safe mode, lazier computation if we should accelerate and random cleanup of prefs usage. r=botond --- gfx/thebes/gfxPlatform.cpp | 16 ++++++++ gfx/thebes/gfxPlatform.h | 3 ++ gfx/thebes/gfxWindowsPlatform.cpp | 15 +------ widget/nsBaseWidget.cpp | 67 +++++++++++++++---------------- widget/nsBaseWidget.h | 1 - widget/windows/nsWindow.cpp | 19 +++------ 6 files changed, 59 insertions(+), 62 deletions(-) diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index d0e3fe8a598..2e7eea6ab6e 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -1759,6 +1759,22 @@ gfxPlatform::GetBackendPref(const char* aBackendPrefName, uint32_t &aBackendBitm return result; } +bool +gfxPlatform::InSafeMode() +{ + static bool sSafeModeInitialized = false; + static bool sInSafeMode = false; + + if (!sSafeModeInitialized) { + sSafeModeInitialized = true; + nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); + if (xr) { + xr->GetInSafeMode(&sInSafeMode); + } + } + return sInSafeMode; +} + bool gfxPlatform::OffMainThreadCompositingEnabled() { diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 17e1753dd4b..bd44897b4e0 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -491,6 +491,9 @@ public: // platform-specific override, by default do nothing } + // Are we in safe mode? + static bool InSafeMode(); + static bool OffMainThreadCompositingEnabled(); static bool CanUseDirect3D9(); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 72e9800b704..caefb86d38b 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -494,11 +494,6 @@ gfxWindowsPlatform::UpdateRenderMode() bool isVistaOrHigher = IsVistaOrLater(); - bool safeMode = false; - nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); - if (xr) - xr->GetInSafeMode(&safeMode); - mUseDirectWrite = Preferences::GetBool("gfx.font_rendering.directwrite.enabled", false); #ifdef CAIRO_HAS_D2D_SURFACE @@ -535,7 +530,7 @@ gfxWindowsPlatform::UpdateRenderMode() } ID3D11Device *device = GetD3D11Device(); - if (isVistaOrHigher && !safeMode && tryD2D && + if (isVistaOrHigher && !InSafeMode() && tryD2D && device && device->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 && DoesD3D11TextureSharingWork(device)) { @@ -1869,13 +1864,7 @@ gfxWindowsPlatform::InitD3D11Devices() MOZ_ASSERT(!mD3D11Device); - bool safeMode = false; - nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); - if (xr) { - xr->GetInSafeMode(&safeMode); - } - - if (safeMode) { + if (InSafeMode()) { return; } diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index ca155f46363..474197d466c 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -129,7 +129,6 @@ nsBaseWidget::nsBaseWidget() , mUpdateCursor(true) , mBorderStyle(eBorderStyle_none) , mUseLayersAcceleration(false) -, mForceLayersAcceleration(false) , mUseAttachedEvents(false) , mBounds(0,0,0,0) , mOriginalBounds(nullptr) @@ -826,35 +825,23 @@ nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup() bool nsBaseWidget::ComputeShouldAccelerate(bool aDefault) { -#if defined(XP_WIN) || defined(ANDROID) || \ - defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT) - bool accelerateByDefault = true; -#else - bool accelerateByDefault = false; -#endif + // Pref to disable acceleration wins: + if (gfxPrefs::LayersAccelerationDisabled()) { + return false; + } -#ifdef XP_MACOSX - // 10.6.2 and lower have a bug involving textures and pixel buffer objects - // that caused bug 629016, so we don't allow OpenGL-accelerated layers on - // those versions of the OS. - // This will still let full-screen video be accelerated on OpenGL, because - // that XUL widget opts in to acceleration, but that's probably OK. - accelerateByDefault = nsCocoaFeatures::AccelerateByDefault(); -#endif + // No acceleration in the safe mode: + if (gfxPlatform::InSafeMode()) { + return false; + } - // we should use AddBoolPrefVarCache - bool disableAcceleration = gfxPrefs::LayersAccelerationDisabled(); - mForceLayersAcceleration = gfxPrefs::LayersAccelerationForceEnabled(); - - const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED"); - accelerateByDefault = accelerateByDefault || - (acceleratedEnv && (*acceleratedEnv != '0')); - - nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); - bool safeMode = false; - if (xr) - xr->GetInSafeMode(&safeMode); + // If the pref forces acceleration, no need to check further: + if (gfxPrefs::LayersAccelerationForceEnabled()) { + return true; + } + // Being whitelisted is not enough to accelerate, but not being whitelisted is + // enough not to: bool whitelisted = false; nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); @@ -873,12 +860,6 @@ nsBaseWidget::ComputeShouldAccelerate(bool aDefault) } } - if (disableAcceleration || safeMode) - return false; - - if (mForceLayersAcceleration) - return true; - if (!whitelisted) { static int tell_me_once = 0; if (!tell_me_once) { @@ -892,8 +873,26 @@ nsBaseWidget::ComputeShouldAccelerate(bool aDefault) return false; } - if (accelerateByDefault) +#if defined (XP_MACOSX) + // 10.6.2 and lower have a bug involving textures and pixel buffer objects + // that caused bug 629016, so we don't allow OpenGL-accelerated layers on + // those versions of the OS. + // This will still let full-screen video be accelerated on OpenGL, because + // that XUL widget opts in to acceleration, but that's probably OK. + bool accelerateByDefault = nsCocoaFeatures::AccelerateByDefault(); +#elif defined(XP_WIN) || defined(ANDROID) || \ + defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_QT) + bool accelerateByDefault = true; +#else + bool accelerateByDefault = false; +#endif + + // If the platform is accelerated by default or the environment + // variable is set, we accelerate: + const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED"); + if (accelerateByDefault || (acceleratedEnv && (*acceleratedEnv != '0'))) { return true; + } /* use the window acceleration flag */ return aDefault; diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index ee34d08e446..2621a0c9d51 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -482,7 +482,6 @@ protected: bool mUpdateCursor; nsBorderStyle mBorderStyle; bool mUseLayersAcceleration; - bool mForceLayersAcceleration; bool mMultiProcessWindow; bool mUseAttachedEvents; nsIntRect mBounds; diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index cdfd9be9e26..f90342e28d4 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -3279,26 +3279,17 @@ struct LayerManagerPrefs { static void GetLayerManagerPrefs(LayerManagerPrefs* aManagerPrefs) { - Preferences::GetBool("layers.acceleration.disabled", - &aManagerPrefs->mDisableAcceleration); - Preferences::GetBool("layers.acceleration.force-enabled", - &aManagerPrefs->mForceAcceleration); - Preferences::GetBool("layers.prefer-opengl", - &aManagerPrefs->mPreferOpenGL); - Preferences::GetBool("layers.prefer-d3d9", - &aManagerPrefs->mPreferD3D9); + aManagerPrefs->mDisableAcceleration = gfxPrefs::LayersAccelerationDisabled(); + aManagerPrefs->mForceAcceleration = gfxPrefs::LayersAccelerationForceEnabled(); + aManagerPrefs->mPreferOpenGL = gfxPrefs::LayersPreferOpenGL(); + aManagerPrefs->mPreferD3D9 = gfxPrefs::LayersPreferD3D9(); const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED"); aManagerPrefs->mAccelerateByDefault = aManagerPrefs->mAccelerateByDefault || (acceleratedEnv && (*acceleratedEnv != '0')); - - bool safeMode = false; - nsCOMPtr xr = do_GetService("@mozilla.org/xre/runtime;1"); - if (xr) - xr->GetInSafeMode(&safeMode); aManagerPrefs->mDisableAcceleration = - aManagerPrefs->mDisableAcceleration || safeMode; + aManagerPrefs->mDisableAcceleration || gfxPlatform::InSafeMode(); } LayerManager* From ddccced1dbd98d35a1c922d806671c74b566ed4d Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Mon, 27 Apr 2015 12:06:11 -0400 Subject: [PATCH 35/80] Bug 1158340 - Refactor RedistributeDisplayPortExcess. r=kats --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 123165ab0df..0aa19e39a53 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2347,19 +2347,14 @@ static void RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize, const CSSRect& aScrollableRect) { - float xSlack = std::max(0.0f, aDisplayPortSize.width - aScrollableRect.width); - float ySlack = std::max(0.0f, aDisplayPortSize.height - aScrollableRect.height); - - if (ySlack > 0) { - // Reassign wasted y-axis displayport to the x-axis - aDisplayPortSize.height -= ySlack; - float xExtra = ySlack * aDisplayPortSize.width / aDisplayPortSize.height; - aDisplayPortSize.width += xExtra; - } else if (xSlack > 0) { - // Reassign wasted x-axis displayport to the y-axis - aDisplayPortSize.width -= xSlack; - float yExtra = xSlack * aDisplayPortSize.height / aDisplayPortSize.width; - aDisplayPortSize.height += yExtra; + // As aDisplayPortSize.height * aDisplayPortSize.width does not change, + // we are just scaling by the ratio and its inverse. + if (aDisplayPortSize.height > aScrollableRect.height) { + aDisplayPortSize.width *= (aDisplayPortSize.height / aScrollableRect.height); + aDisplayPortSize.height = aScrollableRect.height; + } else if (aDisplayPortSize.width > aScrollableRect.width) { + aDisplayPortSize.height *= (aDisplayPortSize.width / aScrollableRect.width); + aDisplayPortSize.width = aScrollableRect.width; } } From 7fa1167ea354e0d2e2c39db4a6480f08effb9cb6 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 28 Apr 2015 11:37:33 +1200 Subject: [PATCH 36/80] Bug 1136360 - Backout 3920b67e97a3 to fix A/V sync regressions (bug 1148299 & bug 1157886). r=backout --- media/libcubeb/src/cubeb_wasapi.cpp | 88 ++++------------------------- 1 file changed, 10 insertions(+), 78 deletions(-) diff --git a/media/libcubeb/src/cubeb_wasapi.cpp b/media/libcubeb/src/cubeb_wasapi.cpp index d70eea59123..540158e30d6 100644 --- a/media/libcubeb/src/cubeb_wasapi.cpp +++ b/media/libcubeb/src/cubeb_wasapi.cpp @@ -216,8 +216,6 @@ struct cubeb_stream /* Main handle on the WASAPI stream. */ IAudioClient * client; - /* Interface pointer to the clock, to estimate latency. */ - IAudioClock * audio_clock; /* Interface pointer to use the event-driven interface. */ IAudioRenderClient * render_client; /* Interface pointer to use the volume facilities. */ @@ -239,16 +237,8 @@ struct cubeb_stream HANDLE refill_event; /* Each cubeb_stream has its own thread. */ HANDLE thread; - /* We synthesize our clock from the callbacks. This in fractional frames, in - * the stream samplerate. */ - double clock; - UINT64 prev_position; - /* This is the clock value last time we reset the stream. This is in - * fractional frames, in the stream samplerate. */ - double base_clock; - /* The latency in frames of the stream */ - UINT32 latency_frames; - UINT64 device_frequency; + /* We synthesize our clock from the callbacks. */ + LONG64 clock; owned_critical_section * stream_reset_lock; /* Maximum number of frames we can be requested in a callback. */ uint32_t buffer_frame_count; @@ -353,28 +343,14 @@ private: }; namespace { -void clock_add(cubeb_stream * stm, double value) +void clock_add(cubeb_stream * stm, LONG64 value) { - auto_lock lock(stm->stream_reset_lock); - stm->clock += value; + InterlockedExchangeAdd64(&stm->clock, value); } -UINT64 clock_get(cubeb_stream * stm) +LONG64 clock_get(cubeb_stream * stm) { - auto_lock lock(stm->stream_reset_lock); - return UINT64(stm->clock); -} - -void latency_set(cubeb_stream * stm, UINT32 value) -{ - auto_lock lock(stm->stream_reset_lock); - stm->latency_frames = value; -} - -UINT32 latency_get(cubeb_stream * stm) -{ - auto_lock lock(stm->stream_reset_lock); - return stm->latency_frames; + return InterlockedExchangeAdd64(&stm->clock, 0); } bool should_upmix(cubeb_stream * stream) @@ -476,6 +452,8 @@ refill(cubeb_stream * stm, float * data, long frames_needed) long out_frames = cubeb_resampler_fill(stm->resampler, dest, frames_needed); + clock_add(stm, roundf(frames_needed * stream_to_mix_samplerate_ratio(stm))); + /* XXX: Handle this error. */ if (out_frames < 0) { XASSERT(false); @@ -547,10 +525,8 @@ wasapi_stream_render_loop(LPVOID stream) /* We don't check if the drain is actually finished here, we just want to * shutdown. */ if (stm->draining) { - LOG("DRAINED"); stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED); } - continue; } case WAIT_OBJECT_0 + 1: { /* reconfigure */ @@ -559,8 +535,6 @@ wasapi_stream_render_loop(LPVOID stream) { auto_lock lock(stm->stream_reset_lock); close_wasapi_stream(stm); - stm->base_clock = stm->clock; - stm->latency_frames = 0; /* Reopen a stream and start it immediately. This will automatically pick the * new default device for this role. */ int r = setup_wasapi_stream(stm); @@ -588,16 +562,6 @@ wasapi_stream_render_loop(LPVOID stream) long available = stm->buffer_frame_count - padding; - clock_add(stm, available * stream_to_mix_samplerate_ratio(stm)); - - UINT64 position = 0; - HRESULT hr = stm->audio_clock->GetPosition(&position, NULL); - if (SUCCEEDED(hr)) { - double playing_frame = stm->mix_params.rate * (double)position / stm->device_frequency; - double last_written_frame = stm->clock - stm->base_clock; - latency_set(stm, std::max(last_written_frame - playing_frame, 0.0)); - } - if (stm->draining) { if (padding == 0) { stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED); @@ -1090,19 +1054,6 @@ int setup_wasapi_stream(cubeb_stream * stm) return CUBEB_ERROR; } - hr = stm->client->GetService(__uuidof(IAudioClock), - (void **)&stm->audio_clock); - if (FAILED(hr)) { - LOG("Could not get IAudioClock: %x.\n", hr); - return CUBEB_ERROR; - } - - hr = stm->audio_clock->GetFrequency(&stm->device_frequency); - if (FAILED(hr)) { - LOG("Could not get the device frequency from IAudioClock: %x.\n", hr); - return CUBEB_ERROR; - } - hr = stm->client->GetService(__uuidof(IAudioRenderClient), (void **)&stm->render_client); if (FAILED(hr)) { @@ -1161,14 +1112,11 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, stm->stream_params = stream_params; stm->draining = false; stm->latency = latency; - stm->clock = 0.0; - stm->base_clock = 0.0; - stm->latency_frames = 0; + stm->clock = 0; /* Null out WASAPI-specific state */ stm->resampler = NULL; stm->client = NULL; - stm->audio_clock = NULL; stm->render_client = NULL; stm->audio_stream_volume = NULL; stm->device_enumerator = NULL; @@ -1226,9 +1174,6 @@ void close_wasapi_stream(cubeb_stream * stm) SafeRelease(stm->render_client); stm->render_client = NULL; - SafeRelease(stm->audio_clock); - stm->audio_clock = NULL; - SafeRelease(stm->audio_stream_volume); stm->audio_stream_volume = NULL; @@ -1338,20 +1283,7 @@ int wasapi_stream_get_position(cubeb_stream * stm, uint64_t * position) { XASSERT(stm && position); - UINT64 clock = clock_get(stm); - UINT32 latency = latency_get(stm); - - *position = clock >= latency ? clock - latency : 0; - - /* This can happen if the clock does not increase, for example, because the - * WASAPI endpoint buffer is full for now, and the latency naturally decreases - * because more samples have been played by the mixer process. - * We return the previous value to keep the clock monotonicaly increasing. */ - if (*position < stm->prev_position) { - *position = stm->prev_position; - } - - stm->prev_position = *position; + *position = clock_get(stm); return CUBEB_OK; } From c2b1f94fa6baba5ef99e6a8d7afab4c8f474798d Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 24 Apr 2015 13:15:00 -0400 Subject: [PATCH 37/80] Bug 1154356 - Escape variable name in Declaration::AppendVariableAndValueToString. r=heycam --- layout/style/Declaration.cpp | 6 ++++-- layout/style/test/test_variables.html | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index e419c5301c8..7f8ec1bfaac 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -1171,8 +1171,10 @@ void Declaration::AppendVariableAndValueToString(const nsAString& aName, nsAString& aResult) const { - aResult.AppendLiteral("--"); - aResult.Append(aName); + nsAutoString localName; + localName.AppendLiteral("--"); + localName.Append(aName); + nsStyleUtil::AppendEscapedCSSIdent(localName, aResult); CSSVariableDeclarations::Type type; nsString value; bool important; diff --git a/layout/style/test/test_variables.html b/layout/style/test/test_variables.html index 962323554f4..a1dd341a76e 100644 --- a/layout/style/test/test_variables.html +++ b/layout/style/test/test_variables.html @@ -26,6 +26,9 @@ + + diff --git a/editor/libeditor/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list index ae8e2a391c7..972e1a3f930 100644 --- a/editor/libeditor/crashtests/crashtests.list +++ b/editor/libeditor/crashtests/crashtests.list @@ -62,3 +62,4 @@ load 1057677.html needs-focus load 1128787.html load 1134545.html load 1158452.html +load 1158651.html diff --git a/editor/libeditor/nsHTMLEditRules.cpp b/editor/libeditor/nsHTMLEditRules.cpp index 51dcdc22cb0..b7f5e17e3cf 100644 --- a/editor/libeditor/nsHTMLEditRules.cpp +++ b/editor/libeditor/nsHTMLEditRules.cpp @@ -6035,6 +6035,7 @@ nsHTMLEditRules::GetParagraphFormatNodes(nsTArray>& outAr // Remove all non-editable nodes. Leave them be. if (!mHTMLEditor->IsEditable(testNode)) { outArrayOfNodes.RemoveElementAt(i); + continue; } // Scan for table elements. If we find table elements other than table, From 54c977f7bae988c60ca242d54a4b2cc893059427 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 21 Apr 2015 16:30:14 -0400 Subject: [PATCH 47/80] bug 1146518 - Only pass hyper links to MaiHyperlink::MaiHyperlink r=surkov --- accessible/atk/nsMaiHyperlink.cpp | 3 --- accessible/atk/nsMaiInterfaceHypertext.cpp | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/accessible/atk/nsMaiHyperlink.cpp b/accessible/atk/nsMaiHyperlink.cpp index 0b086a0963d..3013e6f8b77 100644 --- a/accessible/atk/nsMaiHyperlink.cpp +++ b/accessible/atk/nsMaiHyperlink.cpp @@ -94,9 +94,6 @@ MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) : mHyperlink(aHyperLink), mMaiAtkHyperlink(nullptr) { - if (!mHyperlink->IsLink()) - return; - mMaiAtkHyperlink = reinterpret_cast (g_object_new(mai_atk_hyperlink_get_type(), nullptr)); diff --git a/accessible/atk/nsMaiInterfaceHypertext.cpp b/accessible/atk/nsMaiInterfaceHypertext.cpp index 88b500486fa..4186ef53d8a 100644 --- a/accessible/atk/nsMaiInterfaceHypertext.cpp +++ b/accessible/atk/nsMaiInterfaceHypertext.cpp @@ -27,7 +27,7 @@ getLinkCB(AtkHypertext *aText, gint aLinkIndex) NS_ENSURE_TRUE(hyperText, nullptr); Accessible* hyperLink = hyperText->LinkAt(aLinkIndex); - if (!hyperLink) { + if (!hyperLink || !hyperLink->IsLink()) { return nullptr; } From 30404a39ef62905060731791f29bac1205ae4e98 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 21 Apr 2015 16:31:58 -0400 Subject: [PATCH 48/80] bug 1146518 - allow MaiHyperlink to store references to proxies r=surkov --- accessible/atk/AccessibleWrap.cpp | 6 +----- accessible/atk/nsMai.h | 4 ++++ accessible/atk/nsMaiHyperlink.cpp | 2 +- accessible/atk/nsMaiHyperlink.h | 13 ++++++++++--- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/accessible/atk/AccessibleWrap.cpp b/accessible/atk/AccessibleWrap.cpp index 0f922cf4c1a..6b2956f8359 100644 --- a/accessible/atk/AccessibleWrap.cpp +++ b/accessible/atk/AccessibleWrap.cpp @@ -123,10 +123,6 @@ static const GInterfaceInfo atk_if_infos[] = { (GInterfaceFinalizeFunc) nullptr, nullptr} }; -// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a -// proxy. -static const uintptr_t IS_PROXY = 1; - static GQuark quark_mai_hyperlink = 0; AtkHyperlink* @@ -136,7 +132,7 @@ MaiAtkObject::GetAtkHyperlink() MaiHyperlink* maiHyperlink = (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink); if (!maiHyperlink) { - maiHyperlink = new MaiHyperlink(reinterpret_cast(accWrap)); + maiHyperlink = new MaiHyperlink(accWrap); g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, maiHyperlink); } diff --git a/accessible/atk/nsMai.h b/accessible/atk/nsMai.h index b36bd15958d..127fbf44461 100644 --- a/accessible/atk/nsMai.h +++ b/accessible/atk/nsMai.h @@ -51,6 +51,10 @@ IsAtkVersionAtLeast(int aMajor, int aMinor) (aMajor == atkMajorVersion && aMinor <= atkMinorVersion); } +// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a +// proxy. +static const uintptr_t IS_PROXY = 1; + /** * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject */ diff --git a/accessible/atk/nsMaiHyperlink.cpp b/accessible/atk/nsMaiHyperlink.cpp index 3013e6f8b77..7c364f3a39d 100644 --- a/accessible/atk/nsMaiHyperlink.cpp +++ b/accessible/atk/nsMaiHyperlink.cpp @@ -90,7 +90,7 @@ mai_atk_hyperlink_get_type(void) return type; } -MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) : +MaiHyperlink::MaiHyperlink(uintptr_t aHyperLink) : mHyperlink(aHyperLink), mMaiAtkHyperlink(nullptr) { diff --git a/accessible/atk/nsMaiHyperlink.h b/accessible/atk/nsMaiHyperlink.h index 7fca0275eea..0e5e5dbbba2 100644 --- a/accessible/atk/nsMaiHyperlink.h +++ b/accessible/atk/nsMaiHyperlink.h @@ -23,16 +23,23 @@ namespace a11y { class MaiHyperlink { public: - explicit MaiHyperlink(Accessible* aHyperLink); + explicit MaiHyperlink(uintptr_t aHyperLink); ~MaiHyperlink(); public: AtkHyperlink* GetAtkHyperlink() const { return mMaiAtkHyperlink; } Accessible* GetAccHyperlink() - { return mHyperlink && mHyperlink->IsLink() ? mHyperlink : nullptr; } + { + if (!mHyperlink || mHyperlink & IS_PROXY) + return nullptr; + + Accessible* link = reinterpret_cast(mHyperlink); + NS_ASSERTION(link->IsLink(), "Why isn't it a link!"); + return link; + } protected: - Accessible* mHyperlink; + uintptr_t mHyperlink; AtkHyperlink* mMaiAtkHyperlink; }; From 8572f52559b96eedcad5bafadaee4227fd36fe62 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Tue, 21 Apr 2015 18:30:35 -0400 Subject: [PATCH 49/80] bug 1146518 - create MaiHyperlinks for proxies r=surkov --- .../atk/nsMaiInterfaceHyperlinkImpl.cpp | 5 +++-- accessible/atk/nsMaiInterfaceHypertext.cpp | 22 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp b/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp index ee6d1969243..106648d80d1 100644 --- a/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp +++ b/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp @@ -16,10 +16,11 @@ static AtkHyperlink* getHyperlinkCB(AtkHyperlinkImpl* aImpl) { AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImpl)); - if (!accWrap) + if (!accWrap || !GetProxy(ATK_OBJECT(aImpl))) return nullptr; - NS_ENSURE_TRUE(accWrap->IsLink(), nullptr); + if (accWrap) + NS_ASSERTION(accWrap->IsLink(), "why isn't it a link!"); return MAI_ATK_OBJECT(aImpl)->GetAtkHyperlink(); } diff --git a/accessible/atk/nsMaiInterfaceHypertext.cpp b/accessible/atk/nsMaiInterfaceHypertext.cpp index 4186ef53d8a..d6b3ee8f47e 100644 --- a/accessible/atk/nsMaiInterfaceHypertext.cpp +++ b/accessible/atk/nsMaiInterfaceHypertext.cpp @@ -22,6 +22,7 @@ static AtkHyperlink* getLinkCB(AtkHypertext *aText, gint aLinkIndex) { AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); + AtkObject* atkHyperLink = nullptr; if (accWrap) { HyperTextAccessible* hyperText = accWrap->AsHyperText(); NS_ENSURE_TRUE(hyperText, nullptr); @@ -31,22 +32,17 @@ getLinkCB(AtkHypertext *aText, gint aLinkIndex) return nullptr; } - AtkObject* hyperLinkAtkObj = AccessibleWrap::GetAtkObject(hyperLink); - NS_ENSURE_TRUE(IS_MAI_OBJECT(hyperLinkAtkObj), nullptr); - - return MAI_ATK_OBJECT(hyperLinkAtkObj)->GetAtkHyperlink(); - } - - if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) { + atkHyperLink = AccessibleWrap::GetAtkObject(hyperLink); + } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) { ProxyAccessible* proxyLink = proxy->LinkAt(aLinkIndex); - if (proxyLink) { - NS_WARNING("IMPLEMENT ME! See bug 1146518."); - // We should somehow get from ProxyAccessible* to AtkHyperlink*. - } - return nullptr; + if (!proxyLink) + return nullptr; + + atkHyperLink = GetWrapperFor(proxyLink); } - return nullptr; + NS_ENSURE_TRUE(IS_MAI_OBJECT(atkHyperLink), nullptr); + return MAI_ATK_OBJECT(atkHyperLink)->GetAtkHyperlink(); } static gint From 7a292f5a83e29ed03c8aeedb7c192e98a71e9d5c Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Wed, 22 Apr 2015 18:31:19 -0400 Subject: [PATCH 50/80] bug 1146518 - make atk hyper link impl support proxies r=surkov --- accessible/atk/nsMaiHyperlink.cpp | 99 ++++++++++++++++++++----------- accessible/atk/nsMaiHyperlink.h | 8 +++ 2 files changed, 74 insertions(+), 33 deletions(-) diff --git a/accessible/atk/nsMaiHyperlink.cpp b/accessible/atk/nsMaiHyperlink.cpp index 7c364f3a39d..5aac35a05e8 100644 --- a/accessible/atk/nsMaiHyperlink.cpp +++ b/accessible/atk/nsMaiHyperlink.cpp @@ -6,6 +6,7 @@ #include "nsIURI.h" #include "nsMaiHyperlink.h" +#include "mozilla/a11y/ProxyAccessible.h" using namespace mozilla::a11y; @@ -61,8 +62,17 @@ static gint getAnchorCountCB(AtkHyperlink *aLink); G_END_DECLS static gpointer parent_class = nullptr; -static Accessible* -get_accessible_hyperlink(AtkHyperlink *aHyperlink); + +static MaiHyperlink* +GetMaiHyperlink(AtkHyperlink *aHyperlink) +{ + NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr); + MaiHyperlink * maiHyperlink = + MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink; + NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr); + NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr); + return maiHyperlink; +} GType mai_atk_hyperlink_get_type(void) @@ -150,79 +160,102 @@ finalizeCB(GObject *aObj) gchar * getUriCB(AtkHyperlink *aLink, gint aLinkIndex) { - Accessible* hyperlink = get_accessible_hyperlink(aLink); - NS_ENSURE_TRUE(hyperlink, nullptr); + MaiHyperlink* maiLink = GetMaiHyperlink(aLink); + if (!maiLink) + return nullptr; + nsAutoCString cautoStr; + if (Accessible* hyperlink = maiLink->GetAccHyperlink()) { nsCOMPtr uri = hyperlink->AnchorURIAt(aLinkIndex); if (!uri) - return nullptr; + return nullptr; - nsAutoCString cautoStr; nsresult rv = uri->GetSpec(cautoStr); NS_ENSURE_SUCCESS(rv, nullptr); return g_strdup(cautoStr.get()); + } + + bool valid; + maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid); + if (!valid) + return nullptr; + + return g_strdup(cautoStr.get()); } AtkObject * getObjectCB(AtkHyperlink *aLink, gint aLinkIndex) { - Accessible* hyperlink = get_accessible_hyperlink(aLink); - NS_ENSURE_TRUE(hyperlink, nullptr); + MaiHyperlink* maiLink = GetMaiHyperlink(aLink); + if (!maiLink) + return nullptr; - Accessible* anchor = hyperlink->AnchorAt(aLinkIndex); - NS_ENSURE_TRUE(anchor, nullptr); + if (Accessible* hyperlink = maiLink->GetAccHyperlink()) { + Accessible* anchor = hyperlink->AnchorAt(aLinkIndex); + NS_ENSURE_TRUE(anchor, nullptr); - AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor); - //no need to add ref it, because it is "get" not "ref" - return atkObj; + return AccessibleWrap::GetAtkObject(anchor); + } + + ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex); + return anchor ? GetWrapperFor(anchor) : nullptr; } gint getEndIndexCB(AtkHyperlink *aLink) { - Accessible* hyperlink = get_accessible_hyperlink(aLink); - NS_ENSURE_TRUE(hyperlink, -1); + MaiHyperlink* maiLink = GetMaiHyperlink(aLink); + if (!maiLink) + return false; + if (Accessible* hyperlink = maiLink->GetAccHyperlink()) return static_cast(hyperlink->EndOffset()); + + bool valid = false; + uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid); + return valid ? static_cast(endIdx) : -1; } gint getStartIndexCB(AtkHyperlink *aLink) { - Accessible* hyperlink = get_accessible_hyperlink(aLink); - NS_ENSURE_TRUE(hyperlink, -1); + MaiHyperlink* maiLink = GetMaiHyperlink(aLink); + if (maiLink) + return -1; + if (Accessible* hyperlink = maiLink->GetAccHyperlink()) return static_cast(hyperlink->StartOffset()); + + bool valid = false; + uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid); + return valid ? static_cast(startIdx) : -1; } gboolean isValidCB(AtkHyperlink *aLink) { - Accessible* hyperlink = get_accessible_hyperlink(aLink); - NS_ENSURE_TRUE(hyperlink, FALSE); + MaiHyperlink* maiLink = GetMaiHyperlink(aLink); + if (!maiLink) + return false; + if (Accessible* hyperlink = maiLink->GetAccHyperlink()) return static_cast(hyperlink->IsLinkValid()); + + return static_cast(maiLink->Proxy()->IsLinkValid()); } gint getAnchorCountCB(AtkHyperlink *aLink) { - Accessible* hyperlink = get_accessible_hyperlink(aLink); - NS_ENSURE_TRUE(hyperlink, -1); + MaiHyperlink* maiLink = GetMaiHyperlink(aLink); + if (!maiLink) + return -1; + if (Accessible* hyperlink = maiLink->GetAccHyperlink()) return static_cast(hyperlink->AnchorCount()); -} -// Check if aHyperlink is a valid MaiHyperlink, and return the -// HyperLinkAccessible related. -Accessible* -get_accessible_hyperlink(AtkHyperlink *aHyperlink) -{ - NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr); - MaiHyperlink * maiHyperlink = - MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink; - NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr); - NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr); - return maiHyperlink->GetAccHyperlink(); + bool valid = false; + uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid); + return valid ? static_cast(anchorCount) : -1; } diff --git a/accessible/atk/nsMaiHyperlink.h b/accessible/atk/nsMaiHyperlink.h index 0e5e5dbbba2..44420323cdf 100644 --- a/accessible/atk/nsMaiHyperlink.h +++ b/accessible/atk/nsMaiHyperlink.h @@ -38,6 +38,14 @@ public: return link; } + ProxyAccessible* Proxy() const + { + if (!(mHyperlink & IS_PROXY)) + return nullptr; + + return reinterpret_cast(mHyperlink & ~IS_PROXY); + } + protected: uintptr_t mHyperlink; AtkHyperlink* mMaiAtkHyperlink; From d39e08e603d3ee90a951912c73f14990851309e9 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Mon, 27 Apr 2015 16:51:31 -0700 Subject: [PATCH 51/80] Bug 1154898 - Avoid offline observer crash (r=aklotz) --- dom/plugins/ipc/PluginModuleParent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index 3ce0919acc3..bec540f7f45 100755 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -537,6 +537,8 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded) Preferences::RegisterCallback(TimeoutChanged, kHangUIMinDisplayPref, this); #endif + RegisterSettingsCallbacks(); + #ifdef MOZ_CRASHREPORTER // If this fails, we're having IPC troubles, and we're doomed anyways. if (!CrashReporterParent::CreateCrashReporter(this)) { @@ -693,8 +695,6 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32 sInstantiated = true; mRunID = sNextRunID++; - RegisterSettingsCallbacks(); - #ifdef MOZ_ENABLE_PROFILER_SPS InitPluginProfiling(); #endif From d539ee6adcf70d9125f58dec4a7db3d1d5dc0716 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Mon, 27 Apr 2015 17:05:05 -0700 Subject: [PATCH 52/80] Bug 1155789 - Fail if sending a CPOW in parent when no CPOW manager exists (r=dvander) --- dom/base/nsFrameLoader.cpp | 3 ++- dom/ipc/ContentChild.cpp | 3 +++ dom/ipc/ContentParent.cpp | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index e43f6148791..f7436ae666c 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -2472,7 +2472,8 @@ nsFrameLoader::DoSendAsyncMessage(JSContext* aCx, return false; } InfallibleTArray cpows; - if (aCpows && !cp->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { + jsipc::CPOWManager* mgr = cp->GetCPOWManager(); + if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) { return false; } return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows, diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 3cadcba5806..89bf83538d9 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -814,6 +814,9 @@ ContentChild::InitXPCOM() RecvSetOffline(isOffline); RecvBidiKeyboardNotify(isLangRTL); + // Create the CPOW manager as soon as possible. + SendPJavaScriptConstructor(); + if (domainPolicy.active()) { nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); MOZ_ASSERT(ssm); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index afc1221a569..6c5750ca154 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -4388,7 +4388,8 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx, return false; } InfallibleTArray cpows; - if (aCpows && !GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) { + jsipc::CPOWManager* mgr = GetCPOWManager(); + if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) { return false; } #ifdef MOZ_NUWA_PROCESS From f458612d3a4ecef75ebab066fc4a2c3104f4e6ee Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 28 Apr 2015 15:07:22 +1200 Subject: [PATCH 53/80] Bug 1151611 - Expose DXVA status in about:support. r=cpearce,felipe --- dom/base/nsDOMWindowUtils.cpp | 24 ++++++++++++++ dom/interfaces/base/nsIDOMWindowUtils.idl | 9 +++++- dom/media/fmp4/MP4Reader.cpp | 32 +++++++++++++++++++ dom/media/fmp4/MP4Reader.h | 2 ++ dom/media/fmp4/PlatformDecoderModule.cpp | 3 +- .../fmp4/gonk/GonkVideoDecoderManager.cpp | 2 -- dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp | 8 +++-- dom/media/fmp4/wmf/WMFVideoMFTManager.cpp | 9 ++++-- .../chrome/global/aboutSupport.properties | 2 ++ toolkit/modules/Troubleshoot.jsm | 1 + .../tests/browser/browser_Troubleshoot.js | 3 ++ 11 files changed, 85 insertions(+), 10 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 58fddd6bb89..75255645e34 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -25,6 +25,9 @@ #include "mozilla/layers/ShadowLayers.h" #include "ClientLayerManager.h" #include "nsQueryObject.h" +#ifdef MOZ_FMP4 +#include "MP4Reader.h" +#endif #include "nsIScrollableFrame.h" @@ -2236,6 +2239,27 @@ nsDOMWindowUtils::GetLayerManagerRemote(bool* retval) return NS_OK; } +NS_IMETHODIMP +nsDOMWindowUtils::GetSupportsHardwareH264Decoding(bool* retval) +{ + MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); + +#ifdef MOZ_FMP4 + nsCOMPtr widget = GetWidget(); + if (!widget) + return NS_ERROR_FAILURE; + + LayerManager *mgr = widget->GetLayerManager(); + if (!mgr) + return NS_ERROR_FAILURE; + + *retval = MP4Reader::IsVideoAccelerated(mgr->GetCompositorBackendType()); +#else + *retval = false; +#endif + return NS_OK; +} + NS_IMETHODIMP nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex) { diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index b9cb9d01d54..fb0b7970a44 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -51,7 +51,7 @@ interface nsIJSRAIIHelper; interface nsIContentPermissionRequest; interface nsIObserver; -[scriptable, uuid(7ecfd6e7-120a-4567-85f7-14277f4c6d9f)] +[scriptable, uuid(55d6b97f-0717-449d-ac6c-cdaba0a9b698)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1327,6 +1327,13 @@ interface nsIDOMWindowUtils : nsISupports { */ readonly attribute boolean layerManagerRemote; + /** + * True if we can initialize a hardware-backed h264 decoder for a simple + * test video, does not mean that all h264 video decoding will be done + * in hardware. + */ + readonly attribute boolean supportsHardwareH264Decoding; + /** * Record (and return) frame-intervals for frames which were presented * between calling StartFrameTimeRecording and StopFrameTimeRecording. diff --git a/dom/media/fmp4/MP4Reader.cpp b/dom/media/fmp4/MP4Reader.cpp index b3395a1b8df..fc57a9c651b 100644 --- a/dom/media/fmp4/MP4Reader.cpp +++ b/dom/media/fmp4/MP4Reader.cpp @@ -30,6 +30,7 @@ using mozilla::layers::Image; using mozilla::layers::LayerManager; +using mozilla::layers::ImageContainer; using mozilla::layers::LayersBackend; #ifdef PR_LOGGING @@ -70,6 +71,37 @@ TrackTypeToStr(TrackType aTrack) } #endif +uint8_t sTestExtraData[40] = { 0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96, 0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0 }; + +/* static */ bool +MP4Reader::IsVideoAccelerated(LayersBackend aBackend) +{ + VideoInfo config; + config.mMimeType = "video/avc"; + config.mId = 1; + config.mDuration = 40000; + config.mMediaTime = 0; + config.mDisplay = config.mImage = nsIntSize(64, 64); + config.mExtraData = new MediaByteBuffer(); + config.mExtraData->AppendElements(sTestExtraData, 40); + + PlatformDecoderModule::Init(); + + nsRefPtr platform = PlatformDecoderModule::Create(); + + nsRefPtr decoder = + platform->CreateDecoder(config, nullptr, nullptr, aBackend, nullptr); + nsresult rv = decoder->Init(); + NS_ENSURE_SUCCESS(rv, false); + + bool result = decoder->IsHardwareAccelerated(); + + decoder->Shutdown(); + + return result; +} + bool AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata) { diff --git a/dom/media/fmp4/MP4Reader.h b/dom/media/fmp4/MP4Reader.h index 110c7480540..031f18ebd04 100644 --- a/dom/media/fmp4/MP4Reader.h +++ b/dom/media/fmp4/MP4Reader.h @@ -88,6 +88,8 @@ public: virtual void DisableHardwareAcceleration() override; + static bool IsVideoAccelerated(layers::LayersBackend aBackend); + private: bool InitDemuxer(); diff --git a/dom/media/fmp4/PlatformDecoderModule.cpp b/dom/media/fmp4/PlatformDecoderModule.cpp index b12b6ca8e30..3b2c37af0d2 100644 --- a/dom/media/fmp4/PlatformDecoderModule.cpp +++ b/dom/media/fmp4/PlatformDecoderModule.cpp @@ -118,8 +118,7 @@ PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy, already_AddRefed PlatformDecoderModule::Create() { - // Note: This runs on the decode thread. - MOZ_ASSERT(!NS_IsMainThread()); + // Note: This (usually) runs on the decode thread. nsRefPtr m(CreatePDM()); diff --git a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp index 6a44f33b615..652d5a5dff1 100644 --- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp +++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp @@ -54,8 +54,6 @@ GonkVideoDecoderManager::GonkVideoDecoderManager( , mNativeWindow(nullptr) , mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock") { - NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread."); - MOZ_ASSERT(mImageContainer); MOZ_COUNT_CTOR(GonkVideoDecoderManager); mMimeType = aConfig.mMimeType; mVideoWidth = aConfig.mDisplay.width; diff --git a/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp b/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp index 1396809d8eb..ccc4539d3ad 100644 --- a/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp +++ b/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp @@ -49,8 +49,12 @@ WMFMediaDataDecoder::Init() nsresult WMFMediaDataDecoder::Shutdown() { - mTaskQueue->Dispatch( - NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown)); + if (mTaskQueue) { + mTaskQueue->Dispatch( + NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown)); + } else { + ProcessShutdown(); + } #ifdef DEBUG { MonitorAutoLock mon(mMonitor); diff --git a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp index a55dc160528..95bcd4530bf 100644 --- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp @@ -78,8 +78,6 @@ WMFVideoMFTManager::WMFVideoMFTManager( // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in // Init(). { - NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread."); - MOZ_ASSERT(mImageContainer); MOZ_COUNT_CTOR(WMFVideoMFTManager); // Need additional checks/params to check vp8/vp9 @@ -165,7 +163,12 @@ WMFVideoMFTManager::InitializeDXVA() // The DXVA manager must be created on the main thread. nsRefPtr event(new CreateDXVAManagerEvent(mLayersBackend)); - NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); + + if (NS_IsMainThread()) { + event->Run(); + } else { + NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); + } mDXVA2Manager = event->mDXVA2Manager; return mDXVA2Manager != nullptr; diff --git a/toolkit/locales/en-US/chrome/global/aboutSupport.properties b/toolkit/locales/en-US/chrome/global/aboutSupport.properties index ef59e95666f..546d4f05645 100644 --- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties +++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties @@ -37,6 +37,8 @@ pendingReports=All Crash Reports (including #1 pending crash in the given time r # "GPU Accelerated Windows: 0/2" acceleratedWindows = GPU Accelerated Windows +supportsHardwareH264 = Supports Hardware H264 Decoding + # LOCALIZATION NOTE (rawDataCopied) Text displayed in a mobile "Toast" to user when the # raw data is successfully copied to the clipboard via button press. rawDataCopied=Raw data copied to clipboard diff --git a/toolkit/modules/Troubleshoot.jsm b/toolkit/modules/Troubleshoot.jsm index 86733efbc99..0812e6a71d3 100644 --- a/toolkit/modules/Troubleshoot.jsm +++ b/toolkit/modules/Troubleshoot.jsm @@ -313,6 +313,7 @@ let dataProviders = { try { data.windowLayerManagerType = winUtils.layerManagerType; data.windowLayerManagerRemote = winUtils.layerManagerRemote; + data.supportsHardwareH264 = winUtils.supportsHardwareH264Decoding; } catch (e) { continue; diff --git a/toolkit/modules/tests/browser/browser_Troubleshoot.js b/toolkit/modules/tests/browser/browser_Troubleshoot.js index 28eb0262243..6bb63ab114d 100644 --- a/toolkit/modules/tests/browser/browser_Troubleshoot.js +++ b/toolkit/modules/tests/browser/browser_Troubleshoot.js @@ -199,6 +199,9 @@ const SNAPSHOT_SCHEMA = { windowLayerManagerRemote: { type: "boolean", }, + supportsHardwareH264: { + type: "boolean", + }, numAcceleratedWindowsMessage: { type: "array", }, From 43ec2624bf4d8284ec7cf8a6266113e1b3319bd2 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 28 Apr 2015 15:58:13 +1200 Subject: [PATCH 54/80] Bug 1151611 - Null check PDM::Create to fix bustage. CLOSED TREE --- dom/media/fmp4/MP4Reader.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dom/media/fmp4/MP4Reader.cpp b/dom/media/fmp4/MP4Reader.cpp index fc57a9c651b..95991475164 100644 --- a/dom/media/fmp4/MP4Reader.cpp +++ b/dom/media/fmp4/MP4Reader.cpp @@ -89,9 +89,15 @@ MP4Reader::IsVideoAccelerated(LayersBackend aBackend) PlatformDecoderModule::Init(); nsRefPtr platform = PlatformDecoderModule::Create(); + if (!platform) { + return false; + } nsRefPtr decoder = platform->CreateDecoder(config, nullptr, nullptr, aBackend, nullptr); + if (!decoder) { + return false; + } nsresult rv = decoder->Init(); NS_ENSURE_SUCCESS(rv, false); From 50a1d3fd6662c2de47844bcedcb1655c9c6503be Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Tue, 28 Apr 2015 00:12:29 -0400 Subject: [PATCH 55/80] bug 1142384 - eventtokenbucket thread management r=hurley --- netwerk/protocol/http/nsHttpHandler.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index ca68173506d..64f72731566 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -382,8 +382,7 @@ nsHttpHandler::MakeNewRequestTokenBucket() return; nsRefPtr tokenBucket = - new EventTokenBucket(RequestTokenBucketHz(), - RequestTokenBucketBurst()); + new EventTokenBucket(RequestTokenBucketHz(), RequestTokenBucketBurst()); mConnMgr->UpdateRequestTokenBucket(tokenBucket); } @@ -1452,23 +1451,20 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) } } } - if (requestTokenBucketUpdated) { - MakeNewRequestTokenBucket(); - } if (PREF_CHANGED(HTTP_PREF("pacing.requests.enabled"))) { - rv = prefs->GetBoolPref(HTTP_PREF("pacing.requests.enabled"), - &cVar); - if (NS_SUCCEEDED(rv)){ - requestTokenBucketUpdated = true; + rv = prefs->GetBoolPref(HTTP_PREF("pacing.requests.enabled"), &cVar); + if (NS_SUCCEEDED(rv)) { mRequestTokenBucketEnabled = cVar; + requestTokenBucketUpdated = true; } } - if (PREF_CHANGED(HTTP_PREF("pacing.requests.min-parallelism"))) { rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.min-parallelism"), &val); - if (NS_SUCCEEDED(rv)) + if (NS_SUCCEEDED(rv)) { mRequestTokenBucketMinParallelism = static_cast(clamped(val, 1, 1024)); + requestTokenBucketUpdated = true; + } } if (PREF_CHANGED(HTTP_PREF("pacing.requests.hz"))) { rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.hz"), &val); @@ -1485,9 +1481,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) } } if (requestTokenBucketUpdated) { - mRequestTokenBucket = - new EventTokenBucket(RequestTokenBucketHz(), - RequestTokenBucketBurst()); + MakeNewRequestTokenBucket(); } // Keepalive values for initial and idle connections. From 8cf21d6ee6528f708678870fd20180022e0948a2 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 24 Apr 2015 23:19:25 -0700 Subject: [PATCH 56/80] Bug 1158916 - Stop manually notifying MediaDecoder::mReadyStateWatchTarget. r=jww If we've got our state graph set up properly, the watch target should be notified automatically whenever anything relevant changes. --- dom/media/MediaDecoder.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 2353d0998b3..3e986993179 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -1057,7 +1057,6 @@ void MediaDecoder::PlaybackEnded() ChangeState(PLAY_STATE_ENDED); InvalidateWithFlags(VideoFrameContainer::INVALIDATE_FORCE); - mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary? if (mOwner) { mOwner->PlaybackEnded(); } @@ -1251,7 +1250,6 @@ void MediaDecoder::OnSeekResolved(SeekResolveValue aVal) PlaybackPositionChanged(aVal.mEventVisibility); if (mOwner) { - mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary? if (!seekWasAborted && (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed)) { mOwner->SeekCompleted(); if (fireEnded) { @@ -1268,7 +1266,6 @@ void MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility) return; if (mOwner) { - mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary? if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) { mOwner->SeekStarted(); } @@ -1651,7 +1648,6 @@ void MediaDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int6 if (mDecoderStateMachine) { mDecoderStateMachine->NotifyDataArrived(aBuffer, aLength, aOffset); } - mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary? } // Provide access to the state machine object From 00029872fbd5b7b66cbcee509a5e45560dc48589 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 24 Apr 2015 23:13:20 -0700 Subject: [PATCH 57/80] Bug 1157797 - Be more disciplined about where we call UpdateNextFrameStatus. r=jww This value depends on mState and the audio/video queue states. Given that, we can just stick these calls in a few choke points. --- dom/media/MediaDecoderStateMachine.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 502b8bf6263..d682c35ecee 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -543,7 +543,6 @@ void MediaDecoderStateMachine::SendStreamData() // until all samples are drained. if (finished && AudioQueue().GetSize() == 0) { mAudioCompleted = true; - UpdateNextFrameStatus(); } } @@ -940,9 +939,6 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType, case DECODER_STATE_BUFFERING: case DECODER_STATE_DECODING: { CheckIfDecodeComplete(); - // The ready state can change when we've decoded data, so update the - // ready state, so that DOM events can fire. - UpdateNextFrameStatus(); mDecoder->GetReentrantMonitor().NotifyAll(); // Schedule the state machine to notify track ended as soon as possible. if (mAudioCaptured) { @@ -1325,6 +1321,8 @@ void MediaDecoderStateMachine::SetState(State aState) mState = aState; + UpdateNextFrameStatus(); + // Clear state-scoped state. mSentPlaybackEndedEvent = false; } @@ -1867,11 +1865,6 @@ MediaDecoderStateMachine::InitiateSeek() StopPlayback(); UpdatePlaybackPositionInternal(mCurrentSeek.mTarget.mTime); - - // Make sure the main thread decoder gets notified of the seek only after - // we've updated the mirrored NextFrameStatus, which has special behavior - // when we're in DECODER_STATE_SEEKING. - UpdateNextFrameStatus(); nsCOMPtr startEvent = NS_NewRunnableMethodWithArg( mDecoder, @@ -2677,7 +2670,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine() // Notify to allow blocked decoder thread to continue mDecoder->GetReentrantMonitor().NotifyAll(); - UpdateNextFrameStatus(); MaybeStartPlayback(); NS_ASSERTION(IsStateMachineScheduled(), "Must have timer scheduled"); return NS_OK; @@ -3031,12 +3023,6 @@ void MediaDecoderStateMachine::AdvanceFrame() currentFrame = nullptr; } - // If the number of audio/video frames queued has changed, either by - // this function popping and playing a video frame, or by the audio - // thread popping and playing an audio frame, we may need to update our - // ready state. Post an update to do so. - UpdateNextFrameStatus(); - int64_t delay = remainingTime / mPlaybackRate; if (delay > 0) { ScheduleStateMachineIn(delay); @@ -3256,7 +3242,6 @@ void MediaDecoderStateMachine::StartBuffering() mBufferingStart = TimeStamp::Now(); SetState(DECODER_STATE_BUFFERING); - UpdateNextFrameStatus(); DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs", decodeDuration.ToSeconds()); #ifdef PR_LOGGING From 24a378e7d658c138a6df7d7e81f7191dc49c2b82 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 27 Apr 2015 11:51:46 -0700 Subject: [PATCH 58/80] Bug 1157797 - Use state-watching machinery for UpdateNextFrameStatus. r=jww The ergonomics here aren't ideal. I'm going to file a bug to improve them. --- dom/media/MediaDecoderStateMachine.cpp | 16 ++++++++++------ dom/media/MediaDecoderStateMachine.h | 5 +++-- dom/media/StateWatching.h | 10 ++++++---- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index d682c35ecee..5df1f793b49 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -205,11 +205,12 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mRealTime(aRealTime), mDispatchedStateMachine(false), mDelayedScheduler(this), - mState(DECODER_STATE_DECODING_NONE), + mState(DECODER_STATE_DECODING_NONE, "MediaDecoderStateMachine::mState"), mPlayDuration(0), mStartTime(-1), mEndTime(-1), mDurationSet(false), + mNextFrameStatusUpdater("MediaDecoderStateMachine::mNextFrameStatusUpdater"), mFragmentEndTime(-1), mReader(aReader), mCurrentFrameTime(0), @@ -228,7 +229,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mIsVideoPrerolling(false), mAudioCaptured(false), mPositionChangeQueued(false), - mAudioCompleted(false), + mAudioCompleted(false, "MediaDecoderStateMachine::mAudioCompleted"), mGotDurationFromMetaData(false), mDispatchedEventToDecode(false), mStopAudioThread(true), @@ -257,6 +258,12 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mNextFrameStatus.Init(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED, "MediaDecoderStateMachine::mNextFrameStatus (Canonical)"); + // Skip the initial notification we get when we Watch the value, since we're + // not on the right thread yet. + mNextFrameStatusUpdater->Watch(mState, /* aSkipInitialNotify = */ true); + mNextFrameStatusUpdater->Watch(mAudioCompleted, /* aSkipInitialNotify = */ true); + mNextFrameStatusUpdater->AddWeakCallback(this, &MediaDecoderStateMachine::UpdateNextFrameStatus); + static bool sPrefCacheInit = false; if (!sPrefCacheInit) { sPrefCacheInit = true; @@ -1321,8 +1328,6 @@ void MediaDecoderStateMachine::SetState(State aState) mState = aState; - UpdateNextFrameStatus(); - // Clear state-scoped state. mSentPlaybackEndedEvent = false; } @@ -3182,7 +3187,7 @@ void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs) void MediaDecoderStateMachine::UpdateNextFrameStatus() { MOZ_ASSERT(OnTaskQueue()); - AssertCurrentThreadInMonitor(); + ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); MediaDecoderOwner::NextFrameStatus status; const char* statusString; @@ -3424,7 +3429,6 @@ void MediaDecoderStateMachine::OnAudioSinkComplete() } ResyncAudioClock(); mAudioCompleted = true; - UpdateNextFrameStatus(); // Kick the decode thread; it may be sleeping waiting for this to finish. mDecoder->GetReentrantMonitor().NotifyAll(); } diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 521e09b0c59..40fab5faaa0 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -844,7 +844,7 @@ public: // NotifyAll on the monitor must be called when the state is changed so // that interested threads can wake up and alter behaviour if appropriate // Accessed on state machine, audio, main, and AV thread. - State mState; + Watchable mState; // The task queue in which we run decode tasks. This is referred to as // the "decode thread", though in practise tasks can run on a different @@ -887,6 +887,7 @@ public: // The status of our next frame. Mirrored on the main thread and used to // compute ready state. + WatcherHolder mNextFrameStatusUpdater; Canonical::Holder mNextFrameStatus; public: AbstractCanonical* CanonicalNextFrameStatus() { return &mNextFrameStatus; } @@ -1155,7 +1156,7 @@ protected: // the state machine thread. Synchronised via decoder monitor. // When data is being sent to a MediaStream, this is true when all data has // been written to the MediaStream. - bool mAudioCompleted; + Watchable mAudioCompleted; // True if mDuration has a value obtained from an HTTP header, or from // the media index/metadata. Accessed on the state machine thread. diff --git a/dom/media/StateWatching.h b/dom/media/StateWatching.h index ac8052d1d85..bfef7488a0b 100644 --- a/dom/media/StateWatching.h +++ b/dom/media/StateWatching.h @@ -70,7 +70,7 @@ void EnsureStateWatchingLog(); class AbstractWatcher { public: - NS_INLINE_DECL_REFCOUNTING(AbstractWatcher) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbstractWatcher) AbstractWatcher() : mDestroyed(false) {} bool IsDestroyed() { return mDestroyed; } virtual void Notify() = 0; @@ -104,11 +104,13 @@ class WatchTarget public: explicit WatchTarget(const char* aName) : mName(aName) {} - void AddWatcher(AbstractWatcher* aWatcher) + void AddWatcher(AbstractWatcher* aWatcher, bool aSkipInitialNotify) { MOZ_ASSERT(!mWatchers.Contains(aWatcher)); mWatchers.AppendElement(aWatcher); - aWatcher->Notify(); + if (!aSkipInitialNotify) { + aWatcher->Notify(); + } } void RemoveWatcher(AbstractWatcher* aWatcher) @@ -204,7 +206,7 @@ public: AbstractThread::GetCurrent()->TailDispatcher().AddDirectTask(r.forget()); } - void Watch(WatchTarget& aTarget) { aTarget.AddWatcher(this); } + void Watch(WatchTarget& aTarget, bool aSkipInitialNotify = false) { aTarget.AddWatcher(this, aSkipInitialNotify); } void Unwatch(WatchTarget& aTarget) { aTarget.RemoveWatcher(this); } template From 97082247432ad1ac9f9a291825e9848811b4e6be Mon Sep 17 00:00:00 2001 From: Ethan Hugg Date: Sun, 26 Apr 2015 13:13:46 -0700 Subject: [PATCH 59/80] Bug 1158627 - WebRTC return error if GetEmptyFrame returns null r=jesup --- .../modules/video_coding/main/source/jitter_buffer.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/jitter_buffer.cc b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/jitter_buffer.cc index b69b62b20c7..615744856d6 100644 --- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/jitter_buffer.cc +++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/jitter_buffer.cc @@ -660,8 +660,10 @@ VCMFrameBufferEnum VCMJitterBuffer::GetFrame(const VCMPacket& packet, LOG(LS_WARNING) << "Unable to get empty frame; Recycling."; bool found_key_frame = RecycleFramesUntilKeyFrame(); *frame = GetEmptyFrame(); - assert(*frame); - if (!found_key_frame) { + if (!*frame) { + LOG(LS_ERROR) << "GetEmptyFrame returned NULL."; + return kGeneralError; + } else if (!found_key_frame) { ret = kFlushIndicator; } } From 682040b72bf997b57e9d875aa1d47d341b6cd9b7 Mon Sep 17 00:00:00 2001 From: Mark Goodwin Date: Tue, 28 Apr 2015 05:43:40 +0100 Subject: [PATCH 60/80] Bug 1152388 - modify onSSLErrorReport to use UpdateChannel.jsm to fetch update channel information (r=felipe) --- browser/base/content/browser.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index cd1156107ac..9fcedd0bc74 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -42,6 +42,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Log", "resource://gre/modules/Log.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel", + "resource://gre/modules/UpdateChannel.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "Favicons", "@mozilla.org/browser/favicon-service;1", "mozIAsyncFavicons"); @@ -2758,7 +2760,7 @@ let BrowserOnClick = { version: 1, build: gAppInfo.appBuildID, product: gAppInfo.name, - channel: Services.prefs.getCharPref("app.update.channel") + channel: UpdateChannel.get() } let reportURL = Services.prefs.getCharPref("security.ssl.errorReporting.url"); From 6f25800574aef914b73814abc10fb9f0b9d1bc1d Mon Sep 17 00:00:00 2001 From: "Paul Kerr [:pkerr]" Date: Tue, 21 Apr 2015 15:29:18 -0700 Subject: [PATCH 61/80] Bug 1100502: about:webrtc e10s fix. Content and chrome connections are reported. r=rjesup --- dom/ipc/ContentChild.cpp | 16 + dom/ipc/ContentChild.h | 3 + dom/ipc/ContentParent.cpp | 16 +- dom/ipc/ContentParent.h | 4 + dom/ipc/PContent.ipdl | 4 + media/webrtc/moz.build | 10 + .../src/common/browser_logging/WebRtcLog.cpp | 1 - .../src/peerconnection/PWebrtcGlobal.ipdl | 31 + .../src/peerconnection/PeerConnectionCtx.cpp | 10 + .../src/peerconnection/PeerConnectionCtx.h | 5 + .../src/peerconnection/WebrtcGlobal.h | 495 ++++++++++++ .../src/peerconnection/WebrtcGlobalChild.h | 38 + .../WebrtcGlobalInformation.cpp | 757 +++++++++++++++--- .../peerconnection/WebrtcGlobalInformation.h | 2 +- .../src/peerconnection/WebrtcGlobalParent.h | 52 ++ toolkit/content/aboutwebrtc/aboutWebrtc.js | 6 +- 16 files changed, 1342 insertions(+), 108 deletions(-) create mode 100644 media/webrtc/signaling/src/peerconnection/PWebrtcGlobal.ipdl create mode 100644 media/webrtc/signaling/src/peerconnection/WebrtcGlobal.h create mode 100644 media/webrtc/signaling/src/peerconnection/WebrtcGlobalChild.h create mode 100644 media/webrtc/signaling/src/peerconnection/WebrtcGlobalParent.h diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 89bf83538d9..d03d1b15bfb 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -54,6 +54,7 @@ #include "mozilla/net/NeckoChild.h" #include "mozilla/plugins/PluginInstanceParent.h" #include "mozilla/plugins/PluginModuleParent.h" +#include "mozilla/media/webrtc/WebrtcGlobalChild.h" #include "mozilla/widget/WidgetMessageUtils.h" #if defined(MOZ_CONTENT_SANDBOX) @@ -1829,6 +1830,21 @@ ContentChild::DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor) #endif } +PWebrtcGlobalChild * +ContentChild::AllocPWebrtcGlobalChild() +{ + WebrtcGlobalChild *child = new WebrtcGlobalChild(); + return child; +} + +bool +ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor) +{ + delete static_cast(aActor); + return true; +} + + bool ContentChild::RecvRegisterChrome(InfallibleTArray&& packages, InfallibleTArray&& resources, diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 5e36150b43b..139740418ad 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -457,6 +457,9 @@ public: virtual bool DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate) override; + virtual PWebrtcGlobalChild* AllocPWebrtcGlobalChild() override; + virtual bool DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor) override; + virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const InfallibleTArray& aRequests, const IPC::Principal& aPrincipal, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 6c5750ca154..6f1129d4e7d 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -87,6 +87,7 @@ #include "mozilla/StaticPtr.h" #include "mozilla/Telemetry.h" #include "mozilla/unused.h" +#include "mozilla/media/webrtc/WebrtcGlobalParent.h" #include "nsAnonymousTemporaryFile.h" #include "nsAppRunner.h" #include "nsAutoPtr.h" @@ -2607,7 +2608,7 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer, raw->GuaranteePersistance(); nsRefPtr drawable = new gfxSurfaceDrawable(image, size); - nsCOMPtr imageContainer(image::ImageOps::CreateFromDrawable(drawable)); + nsCOMPtr imageContainer(image::ImageOps::CreateFromDrawable(drawable)); nsCOMPtr imgPtr(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv)); @@ -4907,6 +4908,19 @@ ContentParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActo return true; } +PWebrtcGlobalParent * +ContentParent::AllocPWebrtcGlobalParent() +{ + return WebrtcGlobalParent::Alloc(); +} + +bool +ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) +{ + WebrtcGlobalParent::Dealloc(static_cast(aActor)); + return true; +} + bool ContentParent::RecvSetOfflinePermission(const Principal& aPrincipal) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 5aa8ea952f1..5b250924355 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -843,6 +843,10 @@ private: virtual bool RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, PDocAccessibleParent* aParentDoc, const uint64_t& aParentID) override; + virtual PWebrtcGlobalParent* AllocPWebrtcGlobalParent() override; + virtual bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) override; + + virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction, const uint32_t& aDropEffect) override; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 22d7fe06dcc..4ed145540b8 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -50,6 +50,7 @@ include protocol PTestShell; include protocol PVoicemail; include protocol PJavaScript; include protocol PRemoteSpellcheckEngine; +include protocol PWebrtcGlobal; include DOMTypes; include JavaScriptTypes; include InputStreamParams; @@ -443,6 +444,7 @@ prio(normal upto urgent) sync protocol PContent manages PVoicemail; manages PJavaScript; manages PRemoteSpellcheckEngine; + manages PWebrtcGlobal; both: // Depending on exactly how the new browser is being created, it might be @@ -763,6 +765,8 @@ parent: PAsmJSCacheEntry(OpenMode openMode, WriteParams write, Principal principal); + PWebrtcGlobal(); + // Services remoting async StartVisitedQuery(URIParams uri); diff --git a/media/webrtc/moz.build b/media/webrtc/moz.build index dfb4a1fbbbf..9933bfc33d4 100644 --- a/media/webrtc/moz.build +++ b/media/webrtc/moz.build @@ -36,6 +36,16 @@ webrtc_non_unified_sources = [ 'trunk/webrtc/modules/video_capture/windows/sink_filter_ds.cc', # Because of the MEDIASUBTYPE_HDYC variable and initguid.h ] +IPDL_SOURCES += [ + 'signaling/src/peerconnection/PWebrtcGlobal.ipdl', +] + +EXPORTS.mozilla.media.webrtc += [ + 'signaling/src/peerconnection/WebrtcGlobal.h', + 'signaling/src/peerconnection/WebrtcGlobalChild.h', + 'signaling/src/peerconnection/WebrtcGlobalParent.h' +] + GYP_DIRS += ['trunk'] GYP_DIRS['trunk'].input = 'trunk/peerconnection.gyp' diff --git a/media/webrtc/signaling/src/common/browser_logging/WebRtcLog.cpp b/media/webrtc/signaling/src/common/browser_logging/WebRtcLog.cpp index b5598d9b9d6..f91d5caf957 100644 --- a/media/webrtc/signaling/src/common/browser_logging/WebRtcLog.cpp +++ b/media/webrtc/signaling/src/common/browser_logging/WebRtcLog.cpp @@ -148,7 +148,6 @@ void ConfigWebRtcLog(uint32_t trace_mask, nsCString &aLogFile, nsCString &aAECLo #if !defined(MOZILLA_EXTERNAL_LINKAGE) // Capture the final choices for the trace settings. mozilla::Preferences::SetCString("media.webrtc.debug.log_file", aLogFile); - mozilla::Preferences::SetUint("media.webrtc.debug.trace_mask", trace_mask); mozilla::Preferences::SetCString("media.webrtc.debug.aec_log_dir", aAECLogDir); #endif return; diff --git a/media/webrtc/signaling/src/peerconnection/PWebrtcGlobal.ipdl b/media/webrtc/signaling/src/peerconnection/PWebrtcGlobal.ipdl new file mode 100644 index 00000000000..cda4dff6ee0 --- /dev/null +++ b/media/webrtc/signaling/src/peerconnection/PWebrtcGlobal.ipdl @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PContent; + +include "mozilla/media/webrtc/WebrtcGlobal.h"; + +using struct mozilla::dom::RTCStatsReportInternal from "mozilla/dom/RTCStatsReportBinding.h"; +using WebrtcGlobalLog from "mozilla/media/webrtc/WebrtcGlobal.h"; + +namespace mozilla { +namespace dom { + +async protocol PWebrtcGlobal { + manager PContent; + +child: // parent -> child messages + GetStatsRequest(int aRequestId, nsString aPcIdFilter); + GetLogRequest(int aRequestId, nsCString aPattern); + SetAecLogging(bool aEnable); + SetDebugMode(int aLevel); + +parent: // child -> parent messages + GetStatsResult(int aRequestId, RTCStatsReportInternal[] aStats); + GetLogResult(int aRequestId, WebrtcGlobalLog aLog); + __delete__(); +}; + +} // end namespace net +} // end namespace mozilla diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp index 696c7699cb2..d3dae374f64 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp @@ -100,6 +100,12 @@ PeerConnectionCtx* PeerConnectionCtx::gInstance; nsIThread* PeerConnectionCtx::gMainThread; StaticRefPtr PeerConnectionCtx::gPeerConnectionCtxShutdown; +const std::map& +PeerConnectionCtx::mGetPeerConnections() +{ + return mPeerConnections; +} + nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread, nsIEventTarget* stsThread) { if (!gMainThread) { @@ -319,6 +325,10 @@ nsresult PeerConnectionCtx::Initialize() { NS_ENSURE_SUCCESS(rv, rv); mTelemetryTimer->InitWithFuncCallback(EverySecondTelemetryCallback_m, this, 1000, nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP); + + if (XRE_GetProcessType() == GeckoProcessType_Content) { + WebrtcGlobalChild::Create(); + } #endif // MOZILLA_INTERNAL_API return NS_OK; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h index 4c7f8616697..8e7f3f85d26 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h @@ -7,6 +7,10 @@ #include +#if !defined(MOZILLA_EXTERNAL_LINKAGE) +#include "mozilla/media/webrtc/WebrtcGlobalChild.h" +#endif + #include "mozilla/Attributes.h" #include "StaticPtr.h" #include "PeerConnectionImpl.h" @@ -56,6 +60,7 @@ class PeerConnectionCtx { mStatsForClosedPeerConnections; #endif + const std::map& mGetPeerConnections(); private: // We could make these available only via accessors but it's too much trouble. std::map mPeerConnections; diff --git a/media/webrtc/signaling/src/peerconnection/WebrtcGlobal.h b/media/webrtc/signaling/src/peerconnection/WebrtcGlobal.h new file mode 100644 index 00000000000..dedf63f3d08 --- /dev/null +++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobal.h @@ -0,0 +1,495 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _WEBRTC_GLOBAL_H_ +#define _WEBRTC_GLOBAL_H_ + +#include "ipc/IPCMessageUtils.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/RTCStatsReportBinding.h" + +typedef mozilla::dom::RTCStatsReportInternal StatsReport; +typedef nsTArray< nsAutoPtr> RTCReports; +typedef mozilla::dom::Sequence WebrtcGlobalLog; + +namespace IPC { + +template +struct ParamTraits> +{ + typedef mozilla::dom::Optional paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + if (aParam.WasPassed()) { + WriteParam(aMsg, true); + WriteParam(aMsg, aParam.Value()); + return; + } + + WriteParam(aMsg, false); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + bool was_passed = false; + + if (!ReadParam(aMsg, aIter, &was_passed)) { + return false; + } + + aResult->Reset(); //XXX Optional_base seems to reach this point with isSome true. + + if (was_passed) { + if (!ReadParam(aMsg, aIter, &(aResult->Construct()))) { + return false; + } + } + + return true; + } +}; + +template +struct ParamTraits> +{ + typedef mozilla::dom::Sequence paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, static_cast&>(aParam)); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + return ReadParam(aMsg, aIter, dynamic_cast*>(aResult)); + } +}; + +template<> +struct ParamTraits : + public ContiguousEnumSerializer< + mozilla::dom::RTCStatsType, + mozilla::dom::RTCStatsType::Inboundrtp, + mozilla::dom::RTCStatsType::EndGuard_> +{}; + +template<> +struct ParamTraits : + public ContiguousEnumSerializer< + mozilla::dom::RTCStatsIceCandidatePairState, + mozilla::dom::RTCStatsIceCandidatePairState::Frozen, + mozilla::dom::RTCStatsIceCandidatePairState::EndGuard_> +{}; + +template<> +struct ParamTraits : + public ContiguousEnumSerializer< + mozilla::dom::RTCStatsIceCandidateType, + mozilla::dom::RTCStatsIceCandidateType::Host, + mozilla::dom::RTCStatsIceCandidateType::EndGuard_> +{}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCStatsReportInternal paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mClosed); + WriteParam(aMsg, aParam.mCodecStats); + WriteParam(aMsg, aParam.mIceCandidatePairStats); + WriteParam(aMsg, aParam.mIceCandidateStats); + WriteParam(aMsg, aParam.mIceComponentStats); + WriteParam(aMsg, aParam.mInboundRTPStreamStats); + WriteParam(aMsg, aParam.mLocalSdp); + WriteParam(aMsg, aParam.mMediaStreamStats); + WriteParam(aMsg, aParam.mMediaStreamTrackStats); + WriteParam(aMsg, aParam.mOutboundRTPStreamStats); + WriteParam(aMsg, aParam.mPcid); + WriteParam(aMsg, aParam.mRemoteSdp); + WriteParam(aMsg, aParam.mTimestamp); + WriteParam(aMsg, aParam.mTransportStats); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mClosed)) || + !ReadParam(aMsg, aIter, &(aResult->mCodecStats)) || + !ReadParam(aMsg, aIter, &(aResult->mIceCandidatePairStats)) || + !ReadParam(aMsg, aIter, &(aResult->mIceCandidateStats)) || + !ReadParam(aMsg, aIter, &(aResult->mIceComponentStats)) || + !ReadParam(aMsg, aIter, &(aResult->mInboundRTPStreamStats)) || + !ReadParam(aMsg, aIter, &(aResult->mLocalSdp)) || + !ReadParam(aMsg, aIter, &(aResult->mMediaStreamStats)) || + !ReadParam(aMsg, aIter, &(aResult->mMediaStreamTrackStats)) || + !ReadParam(aMsg, aIter, &(aResult->mOutboundRTPStreamStats)) || + !ReadParam(aMsg, aIter, &(aResult->mPcid)) || + !ReadParam(aMsg, aIter, &(aResult->mRemoteSdp)) || + !ReadParam(aMsg, aIter, &(aResult->mTimestamp)) || + !ReadParam(aMsg, aIter, &(aResult->mTransportStats))) { + return false; + } + + return true; + } +}; + +typedef mozilla::dom::RTCStats RTCStats; + +static void WriteRTCStats(Message* aMsg, const RTCStats& aParam) +{ + // RTCStats base class + WriteParam(aMsg, aParam.mId); + WriteParam(aMsg, aParam.mTimestamp); + WriteParam(aMsg, aParam.mType); +} + +static bool ReadRTCStats(const Message* aMsg, void** aIter, RTCStats* aResult) +{ + // RTCStats base class + if (!ReadParam(aMsg, aIter, &(aResult->mId)) || + !ReadParam(aMsg, aIter, &(aResult->mTimestamp)) || + !ReadParam(aMsg, aIter, &(aResult->mType))) { + return false; + } + + return true; +} + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCCodecStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mChannels); + WriteParam(aMsg, aParam.mClockRate); + WriteParam(aMsg, aParam.mCodec); + WriteParam(aMsg, aParam.mParameters); + WriteParam(aMsg, aParam.mPayloadType); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mChannels)) || + !ReadParam(aMsg, aIter, &(aResult->mClockRate)) || + !ReadParam(aMsg, aIter, &(aResult->mCodec)) || + !ReadParam(aMsg, aIter, &(aResult->mParameters)) || + !ReadParam(aMsg, aIter, &(aResult->mPayloadType)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCIceCandidatePairStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mComponentId); + WriteParam(aMsg, aParam.mLocalCandidateId); + WriteParam(aMsg, aParam.mMozPriority); + WriteParam(aMsg, aParam.mNominated); + WriteParam(aMsg, aParam.mReadable); + WriteParam(aMsg, aParam.mRemoteCandidateId); + WriteParam(aMsg, aParam.mSelected); + WriteParam(aMsg, aParam.mState); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mComponentId)) || + !ReadParam(aMsg, aIter, &(aResult->mLocalCandidateId)) || + !ReadParam(aMsg, aIter, &(aResult->mMozPriority)) || + !ReadParam(aMsg, aIter, &(aResult->mNominated)) || + !ReadParam(aMsg, aIter, &(aResult->mReadable)) || + !ReadParam(aMsg, aIter, &(aResult->mRemoteCandidateId)) || + !ReadParam(aMsg, aIter, &(aResult->mSelected)) || + !ReadParam(aMsg, aIter, &(aResult->mState)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCIceCandidateStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mCandidateId); + WriteParam(aMsg, aParam.mCandidateType); + WriteParam(aMsg, aParam.mComponentId); + WriteParam(aMsg, aParam.mIpAddress); + WriteParam(aMsg, aParam.mMozLocalTransport); + WriteParam(aMsg, aParam.mPortNumber); + WriteParam(aMsg, aParam.mTransport); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mCandidateId)) || + !ReadParam(aMsg, aIter, &(aResult->mCandidateType)) || + !ReadParam(aMsg, aIter, &(aResult->mComponentId)) || + !ReadParam(aMsg, aIter, &(aResult->mIpAddress)) || + !ReadParam(aMsg, aIter, &(aResult->mMozLocalTransport)) || + !ReadParam(aMsg, aIter, &(aResult->mPortNumber)) || + !ReadParam(aMsg, aIter, &(aResult->mTransport)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCIceComponentStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mActiveConnection); + WriteParam(aMsg, aParam.mBytesReceived); + WriteParam(aMsg, aParam.mBytesSent); + WriteParam(aMsg, aParam.mComponent); + WriteParam(aMsg, aParam.mTransportId); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mActiveConnection)) || + !ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) || + !ReadParam(aMsg, aIter, &(aResult->mBytesSent)) || + !ReadParam(aMsg, aIter, &(aResult->mComponent)) || + !ReadParam(aMsg, aIter, &(aResult->mTransportId)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +static void WriteRTCRTPStreamStats( + Message* aMsg, + const mozilla::dom::RTCRTPStreamStats& aParam) +{ + WriteParam(aMsg, aParam.mBitrateMean); + WriteParam(aMsg, aParam.mBitrateStdDev); + WriteParam(aMsg, aParam.mCodecId); + WriteParam(aMsg, aParam.mFramerateMean); + WriteParam(aMsg, aParam.mFramerateStdDev); + WriteParam(aMsg, aParam.mIsRemote); + WriteParam(aMsg, aParam.mMediaTrackId); + WriteParam(aMsg, aParam.mMediaType); + WriteParam(aMsg, aParam.mRemoteId); + WriteParam(aMsg, aParam.mSsrc); + WriteParam(aMsg, aParam.mTransportId); +} + +static bool ReadRTCRTPStreamStats( + const Message* aMsg, void** aIter, + mozilla::dom::RTCRTPStreamStats* aResult) +{ + if (!ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) || + !ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) || + !ReadParam(aMsg, aIter, &(aResult->mCodecId)) || + !ReadParam(aMsg, aIter, &(aResult->mFramerateMean)) || + !ReadParam(aMsg, aIter, &(aResult->mFramerateStdDev)) || + !ReadParam(aMsg, aIter, &(aResult->mIsRemote)) || + !ReadParam(aMsg, aIter, &(aResult->mMediaTrackId)) || + !ReadParam(aMsg, aIter, &(aResult->mMediaType)) || + !ReadParam(aMsg, aIter, &(aResult->mRemoteId)) || + !ReadParam(aMsg, aIter, &(aResult->mSsrc)) || + !ReadParam(aMsg, aIter, &(aResult->mTransportId))) { + return false; + } + + return true; +} + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCInboundRTPStreamStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mBytesReceived); + WriteParam(aMsg, aParam.mDiscardedPackets); + WriteParam(aMsg, aParam.mJitter); + WriteParam(aMsg, aParam.mMozAvSyncDelay); + WriteParam(aMsg, aParam.mMozJitterBufferDelay); + WriteParam(aMsg, aParam.mMozRtt); + WriteParam(aMsg, aParam.mPacketsLost); + WriteParam(aMsg, aParam.mPacketsReceived); + WriteRTCRTPStreamStats(aMsg, aParam); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) || + !ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) || + !ReadParam(aMsg, aIter, &(aResult->mJitter)) || + !ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) || + !ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) || + !ReadParam(aMsg, aIter, &(aResult->mMozRtt)) || + !ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) || + !ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) || + !ReadRTCRTPStreamStats(aMsg, aIter, aResult) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCOutboundRTPStreamStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mBytesSent); + WriteParam(aMsg, aParam.mDroppedFrames); + WriteParam(aMsg, aParam.mPacketsSent); + WriteParam(aMsg, aParam.mTargetBitrate); + WriteRTCRTPStreamStats(aMsg, aParam); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mBytesSent)) || + !ReadParam(aMsg, aIter, &(aResult->mDroppedFrames)) || + !ReadParam(aMsg, aIter, &(aResult->mPacketsSent)) || + !ReadParam(aMsg, aIter, &(aResult->mTargetBitrate)) || + !ReadRTCRTPStreamStats(aMsg, aIter, aResult) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCMediaStreamStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mStreamIdentifier); + WriteParam(aMsg, aParam.mTrackIds); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mStreamIdentifier)) || + !ReadParam(aMsg, aIter, &(aResult->mTrackIds)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCTransportStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mBytesReceived); + WriteParam(aMsg, aParam.mBytesSent); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) || + !ReadParam(aMsg, aIter, &(aResult->mBytesSent)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; + +template<> +struct ParamTraits +{ + typedef mozilla::dom::RTCMediaStreamTrackStats paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mAudioLevel); + WriteParam(aMsg, aParam.mEchoReturnLoss); + WriteParam(aMsg, aParam.mEchoReturnLossEnhancement); + WriteParam(aMsg, aParam.mFrameHeight); + WriteParam(aMsg, aParam.mFrameWidth); + WriteParam(aMsg, aParam.mFramesCorrupted); + WriteParam(aMsg, aParam.mFramesDecoded); + WriteParam(aMsg, aParam.mFramesDropped); + WriteParam(aMsg, aParam.mFramesPerSecond); + WriteParam(aMsg, aParam.mFramesReceived); + WriteParam(aMsg, aParam.mFramesSent); + WriteParam(aMsg, aParam.mRemoteSource); + WriteParam(aMsg, aParam.mSsrcIds); + WriteParam(aMsg, aParam.mTrackIdentifier); + WriteRTCStats(aMsg, aParam); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (!ReadParam(aMsg, aIter, &(aResult->mAudioLevel)) || + !ReadParam(aMsg, aIter, &(aResult->mEchoReturnLoss)) || + !ReadParam(aMsg, aIter, &(aResult->mEchoReturnLossEnhancement)) || + !ReadParam(aMsg, aIter, &(aResult->mFrameHeight)) || + !ReadParam(aMsg, aIter, &(aResult->mFrameWidth)) || + !ReadParam(aMsg, aIter, &(aResult->mFramesCorrupted)) || + !ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) || + !ReadParam(aMsg, aIter, &(aResult->mFramesDropped)) || + !ReadParam(aMsg, aIter, &(aResult->mFramesPerSecond)) || + !ReadParam(aMsg, aIter, &(aResult->mFramesReceived)) || + !ReadParam(aMsg, aIter, &(aResult->mFramesSent)) || + !ReadParam(aMsg, aIter, &(aResult->mRemoteSource)) || + !ReadParam(aMsg, aIter, &(aResult->mSsrcIds)) || + !ReadParam(aMsg, aIter, &(aResult->mTrackIdentifier)) || + !ReadRTCStats(aMsg, aIter, aResult)) { + return false; + } + + return true; + } +}; +} // namespace ipc + +#endif // _WEBRTC_GLOBAL_H_ diff --git a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalChild.h b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalChild.h new file mode 100644 index 00000000000..ed1de43a95d --- /dev/null +++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalChild.h @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _WEBRTC_GLOBAL_CHILD_H_ +#define _WEBRTC_GLOBAL_CHILD_H_ + +#include "mozilla/dom/PWebrtcGlobalChild.h" + +namespace mozilla { +namespace dom { + +class WebrtcGlobalChild : + public PWebrtcGlobalChild +{ + friend class ContentChild; + + bool mShutdown; + + MOZ_IMPLICIT WebrtcGlobalChild(); + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + + virtual bool RecvGetStatsRequest(const int& aRequestId, + const nsString& aPcIdFilter) override; + virtual bool RecvGetLogRequest(const int& aReqestId, + const nsCString& aPattern) override; + virtual bool RecvSetAecLogging(const bool& aEnable) override; + virtual bool RecvSetDebugMode(const int& aLevel) override; + +public: + virtual ~WebrtcGlobalChild(); + static WebrtcGlobalChild* Create(); +}; + +} // namespace dom +} // namespace mozilla + +#endif // _WEBRTC_GLOBAL_CHILD_H_ diff --git a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp index 8d05a262ec5..406ced1800c 100644 --- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp +++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp @@ -3,13 +3,21 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebrtcGlobalInformation.h" +#include "WebrtcGlobalChild.h" +#include "WebrtcGlobalParent.h" #include #include +#include +#include +#include +#include #include "CSFLog.h" #include "WebRtcLog.h" #include "mozilla/dom/WebrtcGlobalInformationBinding.h" +#include "WebrtcGlobal.h" +#include "mozilla/dom/ContentChild.h" #include "nsAutoPtr.h" #include "nsNetCID.h" // NS_SOCKETTRANSPORTSERVICE_CONTRACTID @@ -18,6 +26,9 @@ #include "mozilla/Vector.h" #include "nsProxyRelease.h" #include "mozilla/Telemetry.h" +#include "mozilla/unused.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/RefPtr.h" #include "rlogringbuffer.h" #include "runnable_utils.h" @@ -28,10 +39,190 @@ static const char* logTag = "WebrtcGlobalInformation"; namespace mozilla { - namespace dom { typedef Vector> RTCStatsQueries; +typedef nsTArray Stats; + +template +class RequestManager +{ +public: + + static Request* Create(Callback& aCallback, QueryParam& aParam) + { + mozilla::StaticMutexAutoLock lock(sMutex); + + int id = ++sLastRequestId; + auto result = sRequests.insert( + std::make_pair(id, Request(id, aCallback, aParam))); + + if (!result.second) { + return nullptr; + } + + return &result.first->second; + } + + static void Delete(int aId) + { + mozilla::StaticMutexAutoLock lock(sMutex); + sRequests.erase(aId); + } + + static Request* Get(int aId) + { + mozilla::StaticMutexAutoLock lock(sMutex); + auto r = sRequests.find(aId); + + if (r == sRequests.end()) { + return nullptr; + } + + return &r->second; + } + + Result mResult; + std::queue> mContactList; + const int mRequestId; + + RefPtr GetNextParent() + { + while (!mContactList.empty()) { + RefPtr next = mContactList.front(); + mContactList.pop(); + if (next->IsActive()) { + return next; + } + } + + return nullptr; + } + + void Complete() + { + ErrorResult rv; + mCallback.get()->Call(mResult, rv); + + if (rv.Failed()) { + CSFLogError(logTag, "Error firing stats observer callback"); + } + } + +protected: + // The mutex is used to protect two related operations involving the sRequest map + // and the sLastRequestId. For the map, it prevents more than one thread from + // adding or deleting map entries at the same time. For id generation, + // it creates an atomic allocation and increment. + static mozilla::StaticMutex sMutex; + static std::map sRequests; + static int sLastRequestId; + + Callback mCallback; + + explicit RequestManager(int aId, Callback& aCallback) + : mRequestId(aId) + , mCallback(aCallback) + {} + ~RequestManager() {} +private: + + RequestManager() = delete; + RequestManager& operator=(const RequestManager&) = delete; +}; + +template +mozilla::StaticMutex RequestManager::sMutex; +template +std::map RequestManager::sRequests; +template +int RequestManager::sLastRequestId; + +typedef nsMainThreadPtrHandle StatsRequestCallback; + +class StatsRequest + : public RequestManager +{ +public: + const nsString mPcIdFilter; + explicit StatsRequest(int aId, StatsRequestCallback& aCallback, nsAString& aFilter) + : RequestManager(aId, aCallback) + , mPcIdFilter(aFilter) + { + mResult.mReports.Construct(); + } + +private: + StatsRequest() = delete; + StatsRequest& operator=(const StatsRequest&) = delete; +}; + +typedef nsMainThreadPtrHandle LogRequestCallback; + +class LogRequest + : public RequestManager, + const nsACString> +{ +public: + const nsCString mPattern; + explicit LogRequest(int aId, LogRequestCallback& aCallback, const nsACString& aPattern) + : RequestManager(aId, aCallback) + , mPattern(aPattern) + {} + +private: + LogRequest() = delete; + LogRequest& operator=(const LogRequest&) = delete; +}; + +class WebrtcContentParents +{ +public: + static WebrtcGlobalParent* Alloc(); + static void Dealloc(WebrtcGlobalParent* aParent); + static bool Empty() + { + return sContentParents.empty(); + } + static const std::vector>& GetAll() + { + return sContentParents; + } +private: + static std::vector> sContentParents; + WebrtcContentParents() = delete; + WebrtcContentParents(const WebrtcContentParents&) = delete; + WebrtcContentParents& operator=(const WebrtcContentParents&) = delete; +}; + +std::vector> WebrtcContentParents::sContentParents; + +WebrtcGlobalParent* WebrtcContentParents::Alloc() +{ + RefPtr cp = new WebrtcGlobalParent; + sContentParents.push_back(cp); + return cp.get(); +} + +void WebrtcContentParents::Dealloc(WebrtcGlobalParent* aParent) +{ + if (aParent) { + aParent->mShutdown = true; + auto cp = std::find(sContentParents.begin(), sContentParents.end(), aParent); + if (cp != sContentParents.end()) { + sContentParents.erase(cp); + } + } +} static PeerConnectionCtx* GetPeerConnectionCtx() { @@ -42,89 +233,201 @@ static PeerConnectionCtx* GetPeerConnectionCtx() return nullptr; } -static void OnStatsReport_m( - nsMainThreadPtrHandle aStatsCallback, - nsAutoPtr aQueryList) +static void +OnStatsReport_m(WebrtcGlobalChild* aThisChild, + const int aRequestId, + nsAutoPtr aQueryList) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aQueryList); - WebrtcGlobalStatisticsReport report; - report.mReports.Construct(); + if (aThisChild) { + Stats stats; - // Reports for the currently active PeerConnections - for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) { - MOZ_ASSERT(*q); - report.mReports.Value().AppendElement(*(*q)->report); + // Copy stats generated for the currently active PeerConnections + for (auto&& query : *aQueryList) { + stats.AppendElement(*(query->report)); + } + // Reports saved for closed/destroyed PeerConnections + auto ctx = PeerConnectionCtx::GetInstance(); + if (ctx) { + for (auto&& pc : ctx->mStatsForClosedPeerConnections) { + stats.AppendElement(pc); + } + } + + unused << aThisChild->SendGetStatsResult(aRequestId, stats); + return; } - PeerConnectionCtx* ctx = GetPeerConnectionCtx(); + // This is the last stats report to be collected. (Must be the gecko process). + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + + StatsRequest* request = StatsRequest::Get(aRequestId); + + if (!request) { + CSFLogError(logTag, "Bad RequestId"); + return; + } + + for (auto&& query : *aQueryList) { + request->mResult.mReports.Value().AppendElement(*(query->report)); + } + + // Reports saved for closed/destroyed PeerConnections + auto ctx = PeerConnectionCtx::GetInstance(); if (ctx) { - // Reports for closed/destroyed PeerConnections - report.mReports.Value().AppendElements(ctx->mStatsForClosedPeerConnections); + for (auto&& pc : ctx->mStatsForClosedPeerConnections) { + request->mResult.mReports.Value().AppendElement(pc); + } } - ErrorResult rv; - aStatsCallback.get()->Call(report, rv); - - if (rv.Failed()) { - CSFLogError(logTag, "Error firing stats observer callback"); - } + request->Complete(); + StatsRequest::Delete(aRequestId); } -static void GetAllStats_s( - nsMainThreadPtrHandle aStatsCallback, - nsAutoPtr aQueryList) +static void +GetAllStats_s(WebrtcGlobalChild* aThisChild, + const int aRequestId, + nsAutoPtr aQueryList) { MOZ_ASSERT(aQueryList); + // The call to PeerConnetionImpl must happen on the from a runnable + // dispatched on the STS thread. - for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) { - MOZ_ASSERT(*q); - PeerConnectionImpl::ExecuteStatsQuery_s(*q); + // Get stats from active connections. + for (auto&& query : *aQueryList) { + PeerConnectionImpl::ExecuteStatsQuery_s(query); } + // After the RTCStatsQueries have been filled in, control must return + // to the main thread before their eventual destruction. NS_DispatchToMainThread(WrapRunnableNM(&OnStatsReport_m, - aStatsCallback, + aThisChild, + aRequestId, aQueryList), NS_DISPATCH_NORMAL); } -static void OnGetLogging_m( - nsMainThreadPtrHandle aLoggingCallback, - const std::string& aPattern, - nsAutoPtr> aLogList) +static void OnGetLogging_m(WebrtcGlobalChild* aThisChild, + const int aRequestId, + nsAutoPtr> aLogList) { - ErrorResult rv; - if (!aLogList->empty()) { + MOZ_ASSERT(NS_IsMainThread()); + + if (aThisChild) { + // Add this log to the collection of logs and call into + // the next content process. Sequence nsLogs; - for (auto l = aLogList->begin(); l != aLogList->end(); ++l) { - nsLogs.AppendElement(NS_ConvertUTF8toUTF16(l->c_str())); + + if (!aLogList->empty()) { + for (auto& line : *aLogList) { + nsLogs.AppendElement(NS_ConvertUTF8toUTF16(line.c_str())); + } + nsLogs.AppendElement(NS_LITERAL_STRING("+++++++ END ++++++++")); } - aLoggingCallback.get()->Call(nsLogs, rv); + + unused << aThisChild->SendGetLogResult(aRequestId, nsLogs); + return; } - if (rv.Failed()) { - CSFLogError(logTag, "Error firing logging observer callback"); + // This is the last log to be collected. (Must be the gecko process). + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + + LogRequest* request = LogRequest::Get(aRequestId); + + if (!request) { + CSFLogError(logTag, "Bad RequestId"); + return; } + + if (!aLogList->empty()) { + for (auto& line : *aLogList) { + request->mResult.AppendElement(NS_ConvertUTF8toUTF16(line.c_str())); + } + request->mResult.AppendElement(NS_LITERAL_STRING("+++++++ END ++++++++")); + } + + request->Complete(); + LogRequest::Delete(aRequestId); } -static void GetLogging_s( - nsMainThreadPtrHandle aLoggingCallback, - const std::string& aPattern) +static void GetLogging_s(WebrtcGlobalChild* aThisChild, + const int aRequestId, + const std::string& aPattern) { + // Request log while not on the main thread. RLogRingBuffer* logs = RLogRingBuffer::GetInstance(); nsAutoPtr> result(new std::deque); // Might not exist yet. if (logs) { logs->Filter(aPattern, 0, result); } + // Return to main thread to complete processing. NS_DispatchToMainThread(WrapRunnableNM(&OnGetLogging_m, - aLoggingCallback, - aPattern, + aThisChild, + aRequestId, result), NS_DISPATCH_NORMAL); } +static nsresult +BuildStatsQueryList( + const std::map& aPeerConnections, + const nsAString& aPcIdFilter, + RTCStatsQueries* queries) +{ + nsresult rv; + + for (auto&& pc : aPeerConnections) { + MOZ_ASSERT(pc.second); + if (aPcIdFilter.IsEmpty() || + aPcIdFilter.EqualsASCII(pc.second->GetIdAsAscii().c_str())) { + if (pc.second->HasMedia()) { + queries->append(nsAutoPtr(new RTCStatsQuery(true))); + rv = pc.second->BuildStatsQuery_m(nullptr, queries->back()); // all tracks + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + MOZ_ASSERT(queries->back()->report); + } + } + } + + return NS_OK; +} + +static nsresult +RunStatsQuery( + const std::map& aPeerConnections, + const nsAString& aPcIdFilter, + WebrtcGlobalChild* aThisChild, + const int aRequestId) +{ + auto* queries = new RTCStatsQueries; + nsresult rv = BuildStatsQueryList(aPeerConnections, aPcIdFilter, queries); + + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr stsThread = + do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); + + if (NS_FAILED(rv)) { + return rv; + } else if (!stsThread) { + return NS_ERROR_FAILURE; + } + + rv = RUN_ON_THREAD(stsThread, + WrapRunnableNM(&GetAllStats_s, + aThisChild, + aRequestId, + nsAutoPtr(queries)), + NS_DISPATCH_NORMAL); + return rv; +} void WebrtcGlobalInformation::GetAllStats( @@ -138,55 +441,83 @@ WebrtcGlobalInformation::GetAllStats( return; } + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); + + // CallbackObject does not support threadsafe refcounting, and must be + // destroyed on main. + StatsRequestCallback callbackHandle( + new nsMainThreadPtrHolder(&aStatsCallback)); + + nsString filter; + if (pcIdFilter.WasPassed()) { + filter = pcIdFilter.Value(); + } + + StatsRequest* request = StatsRequest::Create(callbackHandle, filter); + + if (!request) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + if (!WebrtcContentParents::Empty()) { + // Pass on the request to any content based PeerConnections. + for (auto& cp : WebrtcContentParents::GetAll()) { + request->mContactList.push(cp); + } + + auto next = request->GetNextParent(); + if (next) { + aRv = next->SendGetStatsRequest(request->mRequestId, request->mPcIdFilter) ? + NS_OK : NS_ERROR_FAILURE; + return; + } + } + // No content resident PeerConnectionCtx instances. + // Check this process. + PeerConnectionCtx* ctx = GetPeerConnectionCtx(); + nsresult rv; + + if (ctx) { + rv = RunStatsQuery(ctx->mGetPeerConnections(), + filter, nullptr, request->mRequestId); + + if (NS_FAILED(rv)) { + StatsRequest::Delete(request->mRequestId); + } + } else { + // Just send back an empty report. + rv = NS_OK; + request->Complete(); + StatsRequest::Delete(request->mRequestId); + } + + aRv = rv; + return; +} + +static nsresult +RunLogQuery(const nsCString& aPattern, + WebrtcGlobalChild* aThisChild, + const int aRequestId) +{ nsresult rv; nsCOMPtr stsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) { - aRv.Throw(rv); - return; + return rv; + } else if (!stsThread) { + return NS_ERROR_FAILURE; } - if (!stsThread) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return; - } - - nsAutoPtr queries(new RTCStatsQueries); - - // If there is no PeerConnectionCtx, go through the same motions, since - // the API consumer doesn't care why there are no PeerConnectionImpl. - PeerConnectionCtx *ctx = GetPeerConnectionCtx(); - if (ctx) { - for (auto p = ctx->mPeerConnections.begin(); - p != ctx->mPeerConnections.end(); - ++p) { - MOZ_ASSERT(p->second); - - if (!pcIdFilter.WasPassed() || - pcIdFilter.Value().EqualsASCII(p->second->GetIdAsAscii().c_str())) { - if (p->second->HasMedia()) { - queries->append(nsAutoPtr(new RTCStatsQuery(true))); - rv = p->second->BuildStatsQuery_m(nullptr, queries->back()); // all tracks - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(rv); - return; - } - MOZ_ASSERT(queries->back()->report); - } - } - } - } - - // CallbackObject does not support threadsafe refcounting, and must be - // destroyed on main. - nsMainThreadPtrHandle callbackHandle( - new nsMainThreadPtrHolder(&aStatsCallback)); - rv = RUN_ON_THREAD(stsThread, - WrapRunnableNM(&GetAllStats_s, callbackHandle, queries), + WrapRunnableNM(&GetLogging_s, + aThisChild, + aRequestId, + aPattern.get()), NS_DISPATCH_NORMAL); - aRv = rv; + return rv; } void @@ -201,36 +532,45 @@ WebrtcGlobalInformation::GetLogging( return; } - nsresult rv; - nsCOMPtr stsThread = - do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); - - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return; - } - - if (!stsThread) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return; - } - - std::string pattern(NS_ConvertUTF16toUTF8(aPattern).get()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); // CallbackObject does not support threadsafe refcounting, and must be // destroyed on main. - nsMainThreadPtrHandle callbackHandle( + LogRequestCallback callbackHandle( new nsMainThreadPtrHolder(&aLoggingCallback)); - rv = RUN_ON_THREAD(stsThread, - WrapRunnableNM(&GetLogging_s, callbackHandle, pattern), - NS_DISPATCH_NORMAL); + nsAutoCString pattern; + CopyUTF16toUTF8(aPattern, pattern); + + LogRequest* request = LogRequest::Create(callbackHandle, pattern); + + if (!request) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + if (!WebrtcContentParents::Empty()) { + // Pass on the request to any content based PeerConnections. + for (auto& cp : WebrtcContentParents::GetAll()) { + request->mContactList.push(cp); + } + + auto next = request->GetNextParent(); + if (next) { + aRv = next->SendGetLogRequest(request->mRequestId, request->mPattern) ? + NS_OK : NS_ERROR_FAILURE; + return; + } + } + + nsresult rv = RunLogQuery(request->mPattern, nullptr, request->mRequestId); if (NS_FAILED(rv)) { - aLoggingCallback.Release(); + LogRequest::Delete(request->mRequestId); } aRv = rv; + return; } static int32_t sLastSetLevel = 0; @@ -241,6 +581,10 @@ WebrtcGlobalInformation::SetDebugLevel(const GlobalObject& aGlobal, int32_t aLev { StartWebRtcLog(webrtc::TraceLevel(aLevel)); sLastSetLevel = aLevel; + + for (auto& cp : WebrtcContentParents::GetAll()){ + unused << cp->SendSetDebugMode(aLevel); + } } int32_t @@ -255,6 +599,10 @@ WebrtcGlobalInformation::SetAecDebug(const GlobalObject& aGlobal, bool aEnable) StartWebRtcLog(sLastSetLevel); // to make it read the aec path webrtc::Trace::set_aec_debug(aEnable); sLastAECDebug = aEnable; + + for (auto& cp : WebrtcContentParents::GetAll()){ + unused << cp->SendSetAecLogging(aEnable); + } } bool @@ -263,6 +611,209 @@ WebrtcGlobalInformation::AecDebug(const GlobalObject& aGlobal) return sLastAECDebug; } +bool +WebrtcGlobalParent::RecvGetStatsResult(const int& aRequestId, + nsTArray&& Stats) +{ + MOZ_ASSERT(NS_IsMainThread()); + nsresult rv = NS_OK; + + StatsRequest* request = StatsRequest::Get(aRequestId); + + if (!request) { + CSFLogError(logTag, "Bad RequestId"); + return false; + } + + for (auto&& s : Stats) { + request->mResult.mReports.Value().AppendElement(s); + } + + auto next = request->GetNextParent(); + if (next) { + // There are more content instances to query. + return next->SendGetStatsRequest(request->mRequestId, request->mPcIdFilter); + } + + // Content queries complete, run chrome instance query if applicable + PeerConnectionCtx* ctx = GetPeerConnectionCtx(); + + if (ctx) { + rv = RunStatsQuery(ctx->mGetPeerConnections(), + request->mPcIdFilter, nullptr, aRequestId); + } else { + // No instance in the process, return the collections as is + request->Complete(); + StatsRequest::Delete(aRequestId); + } + + return NS_SUCCEEDED(rv); +} + +bool +WebrtcGlobalParent::RecvGetLogResult(const int& aRequestId, + const WebrtcGlobalLog& aLog) +{ + MOZ_ASSERT(NS_IsMainThread()); + + LogRequest* request = LogRequest::Get(aRequestId); + + if (!request) { + CSFLogError(logTag, "Bad RequestId"); + return false; + } + request->mResult.AppendElements(aLog); + + auto next = request->GetNextParent(); + if (next) { + // There are more content instances to query. + return next->SendGetLogRequest(request->mRequestId, request->mPattern); + } + + // Content queries complete, run chrome instance query if applicable + nsresult rv = RunLogQuery(request->mPattern, nullptr, aRequestId); + + if (NS_FAILED(rv)) { + //Unable to get gecko process log. Return what has been collected. + CSFLogError(logTag, "Unable to extract chrome process log"); + request->Complete(); + LogRequest::Delete(aRequestId); + } + + return true; +} + +WebrtcGlobalParent* +WebrtcGlobalParent::Alloc() +{ + return WebrtcContentParents::Alloc(); +} + +bool +WebrtcGlobalParent::Dealloc(WebrtcGlobalParent * aActor) +{ + WebrtcContentParents::Dealloc(aActor); + return true; +} + +void +WebrtcGlobalParent::ActorDestroy(ActorDestroyReason aWhy) +{ + mShutdown = true; + return; +} + +bool +WebrtcGlobalParent::Recv__delete__() +{ + return true; +} + +MOZ_IMPLICIT WebrtcGlobalParent::WebrtcGlobalParent() + : mShutdown(false) +{ + MOZ_COUNT_CTOR(WebrtcGlobalParent); +} + +MOZ_IMPLICIT WebrtcGlobalParent::~WebrtcGlobalParent() +{ + MOZ_COUNT_DTOR(WebrtcGlobalParent); +} + +bool +WebrtcGlobalChild::RecvGetStatsRequest(const int& aRequestId, + const nsString& aPcIdFilter) +{ + if (mShutdown) { + return true; + } + + PeerConnectionCtx* ctx = GetPeerConnectionCtx(); + + if (ctx) { + nsresult rv = RunStatsQuery(ctx->mGetPeerConnections(), + aPcIdFilter, this, aRequestId); + return NS_SUCCEEDED(rv); + } + + nsTArray empty_stats; + SendGetStatsResult(aRequestId, empty_stats); + + return true; +} + +bool +WebrtcGlobalChild::RecvGetLogRequest(const int& aRequestId, + const nsCString& aPattern) +{ + if (mShutdown) { + return true; + } + + nsresult rv; + nsCOMPtr stsThread = + do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); + + if (NS_SUCCEEDED(rv) && stsThread) { + rv = RUN_ON_THREAD(stsThread, + WrapRunnableNM(&GetLogging_s, this, aRequestId, aPattern.get()), + NS_DISPATCH_NORMAL); + + if (NS_SUCCEEDED(rv)) { + return true; + } + } + + Sequence empty_log; + SendGetLogResult(aRequestId, empty_log); + + return true; +} + +bool +WebrtcGlobalChild::RecvSetAecLogging(const bool& aEnable) +{ + if (!mShutdown) { + StartWebRtcLog(sLastSetLevel); // to make it read the aec path + webrtc::Trace::set_aec_debug(aEnable); + } + return true; +} + +bool +WebrtcGlobalChild::RecvSetDebugMode(const int& aLevel) +{ + if (!mShutdown) { + StartWebRtcLog(webrtc::TraceLevel(aLevel)); + } + return true; +} + +WebrtcGlobalChild* +WebrtcGlobalChild::Create() +{ + WebrtcGlobalChild* child = + static_cast( + ContentChild::GetSingleton()->SendPWebrtcGlobalConstructor()); + return child; +} + +void +WebrtcGlobalChild::ActorDestroy(ActorDestroyReason aWhy) +{ + mShutdown = true; +} + +MOZ_IMPLICIT WebrtcGlobalChild::WebrtcGlobalChild() + : mShutdown(false) +{ + MOZ_COUNT_CTOR(WebrtcGlobalChild); +} + +MOZ_IMPLICIT WebrtcGlobalChild::~WebrtcGlobalChild() +{ + MOZ_COUNT_DTOR(WebrtcGlobalChild); +} struct StreamResult { StreamResult() : candidateTypeBitpattern(0), streamSucceeded(false) {} @@ -522,7 +1073,5 @@ void WebrtcGlobalInformation::StoreLongTermICEStatistics( NS_DISPATCH_NORMAL); } - } // namespace dom } // namespace mozilla - diff --git a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h index b7a19dd38a8..2725a29a664 100644 --- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h +++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h @@ -13,6 +13,7 @@ class PeerConnectionImpl; class ErrorResult; namespace dom { + class GlobalObject; class WebrtcGlobalStatisticsCallback; class WebrtcGlobalLoggingCallback; @@ -49,4 +50,3 @@ private: } // namespace mozilla #endif // _WEBRTC_GLOBAL_INFORMATION_H_ - diff --git a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalParent.h b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalParent.h new file mode 100644 index 00000000000..4a4916d5aac --- /dev/null +++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalParent.h @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _WEBRTC_GLOBAL_PARENT_H_ +#define _WEBRTC_GLOBAL_PARENT_H_ + +#include "mozilla/dom/PWebrtcGlobalParent.h" +#include "mozilla/dom/RTCStatsReportBinding.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/RefPtr.h" + +namespace mozilla { +namespace dom { + +class WebrtcParents; + +class WebrtcGlobalParent + : public PWebrtcGlobalParent + , public RefCounted +{ + friend class ContentParent; + friend class WebrtcGlobalInformation; + friend class WebrtcContentParents; + + bool mShutdown; + + MOZ_IMPLICIT WebrtcGlobalParent(); + + static WebrtcGlobalParent* Alloc(); + static bool Dealloc(WebrtcGlobalParent* aActor); + + virtual bool RecvGetStatsResult(const int& aRequestId, + nsTArray&& aStats) override; + virtual bool RecvGetLogResult(const int& aRequestId, + const WebrtcGlobalLog& aLog) override; + + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + virtual bool Recv__delete__() override; +public: + virtual ~WebrtcGlobalParent(); + MOZ_DECLARE_REFCOUNTED_TYPENAME(WebrtcGlobalParent) + bool IsActive() + { + return !mShutdown; + } +}; + +} // namespace dom +} // namespace mozilla + +#endif // _WEBRTC_GLOBAL_PARENT_H_ diff --git a/toolkit/content/aboutwebrtc/aboutWebrtc.js b/toolkit/content/aboutwebrtc/aboutWebrtc.js index 1c357ad0ec9..e71b400ecee 100644 --- a/toolkit/content/aboutwebrtc/aboutWebrtc.js +++ b/toolkit/content/aboutwebrtc/aboutWebrtc.js @@ -293,7 +293,7 @@ let AboutWebRTC = { let connections = document.createDocumentFragment(); let reports = [...this._reports]; - reports.sort((a, b) => a.timestamp - b.timestamp); + reports.sort((a, b) => b.timestamp - a.timestamp); for (let report of reports) { let peerConnection = new PeerConnection(report); connections.appendChild(peerConnection.render()); @@ -306,6 +306,10 @@ let AboutWebRTC = { let content = document.createElement("div"); content.className = "log"; + if (!this._log.length) { + return content; + } + let elem = document.createElement("h3"); elem.textContent = getString("log_heading"); content.appendChild(elem); From 2a9ecc75e446848107bc790a2716d8d1a4503e4a Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 10:35:18 -0700 Subject: [PATCH 62/80] Bumping gaia.json for 6 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/3b9160c9f39b Author: Gareth Aye Desc: Merge pull request #29304 from millermedeiros/1029322-month-view-full-wid Bug 1029322 - [Calendar] Month view does not fill the full screen width on larger screens r=gaye ======== https://hg.mozilla.org/integration/gaia-central/rev/b523764d3918 Author: Miller Medeiros Desc: Bug 1029322 - [Calendar] Month view does not fill the full screen width on larger screens ======== https://hg.mozilla.org/integration/gaia-central/rev/e51941510d75 Author: Gareth Aye Desc: Merge pull request #29376 from millermedeiros/1150831-multi_day_sidebar_timeformatchange Bug 1150831 - [Calendar] On Week view, it displays some codes in the time fields when changing back to "12-hour" from "24-hour" format. ======== https://hg.mozilla.org/integration/gaia-central/rev/edd3b32dfb7a Author: Miller Medeiros Desc: Bug 1150831 - [Calendar] On Week view, it displays some codes in the time fields when changing back to "12-hour" from "24-hour" format. ======== https://hg.mozilla.org/integration/gaia-central/rev/5a1f9c1ca6c2 Author: Gareth Aye Desc: Merge pull request #29535 from millermedeiros/1153071-view-factory Bug 1153071 - [Calendar] remove view factory logic from app.js r=gaye ======== https://hg.mozilla.org/integration/gaia-central/rev/e8c305996701 Author: Miller Medeiros Desc: Bug 1153071 - [Calendar] remove view factory logic from app.js --- 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 08647c93126..5352af2fa0d 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "0636405f0844bf32451a375b2d61a2b16fe33348", + "git_revision": "e8f4231141210db01f43405e0c0336f480083ae7", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "d4ec6c8c9cfc10a495e5c6cfddeb71871be73106", + "revision": "3b9160c9f39b5e13ada99d0297b0fdf3971f581b", "repo_path": "integration/gaia-central" } From 5f3271bec64bf158ab269731edcf752d6003194d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 10:37:30 -0700 Subject: [PATCH 63/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 1a008c09d12..f1339e57ee3 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 d136f25b55e..4a37531c9db 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 117afd3e40f..ffd9b3128c0 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 51ea2141328..a61f95fc76b 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index c3c23e21709..e303b7e68f9 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index d136f25b55e..4a37531c9db 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 be2dbdcb29a..3a63f94de4e 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 3d814de1611..21c103da273 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 aa29a1b27d0..beac3f6c74e 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 d4faed745d7..969aa3f0dec 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 366452a683bb2cb735c659549d464b9f44033cb3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 11:02:38 -0700 Subject: [PATCH 64/80] Bumping gaia.json for 6 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/12dab22031b2 Author: autolander Desc: Bug 1152969 - merge pull request #29743 from Cwiiis:bug1152969-can-save-empty-bookmark-name to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/9f2fb74821f8 Author: Chris Lord Desc: Bug 1152969 - Fix being able to save empty bookmark names. r=kgrandon ======== https://hg.mozilla.org/integration/gaia-central/rev/0e5903a60efa Author: autolander Desc: Bug 1142526 - merge pull request #29742 from stasm:1142526-innerHTML-value-relanding to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/ece1cfd1ce27 Author: Staś Małolepszy Desc: Bug 1142526 - Treat the innerHTML attribute as the string's value. r=gandalf ======== https://hg.mozilla.org/integration/gaia-central/rev/a5163837d153 Author: autolander Desc: Bug 1157610 - merge pull request #29726 from sfoster:entrysheet-headers-bug-1157610 to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/328bd171e1a7 Author: Sam Foster Desc: Bug 1157610 - Bidi entry sheet titles --- 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 5352af2fa0d..fb883ad85b5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "e8f4231141210db01f43405e0c0336f480083ae7", + "git_revision": "5fd082cb265885248974fbb4ff70239901a6427e", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "3b9160c9f39b5e13ada99d0297b0fdf3971f581b", + "revision": "12dab22031b25bdf7f4d70a53f5449dd7ac835b4", "repo_path": "integration/gaia-central" } From b195dd1211e180a3a5f3eefc2a5b6e004f26f121 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 11:04:51 -0700 Subject: [PATCH 65/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index f1339e57ee3..7418e87f31c 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 4a37531c9db..25b276d8c4f 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 ffd9b3128c0..19675c59210 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 a61f95fc76b..a888ef04098 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index e303b7e68f9..067bec658a3 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 4a37531c9db..25b276d8c4f 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 3a63f94de4e..9bdb0725849 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 21c103da273..ea3e0e0fb59 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 beac3f6c74e..09391436e3e 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 969aa3f0dec..d849670cfe6 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 11789c5459b9d097a638a87c170424cbcc8bcc98 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 11:25:21 -0700 Subject: [PATCH 66/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/395d10bf55ad Author: Eli Perelman Desc: Merge pull request #29746 from eliperelman/bug-1155814 Bug 1155814 - Bumping gaia-raptor to v1.4.1 ======== https://hg.mozilla.org/integration/gaia-central/rev/2b8cc9644017 Author: Eli Perelman Desc: Bug 1155814 - Bumping gaia-raptor to v1.4.1 --- 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 fb883ad85b5..a1634407a14 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "5fd082cb265885248974fbb4ff70239901a6427e", + "git_revision": "a9f6218d6b79e93072677515a5fc15f226233f5c", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "12dab22031b25bdf7f4d70a53f5449dd7ac835b4", + "revision": "395d10bf55adfe192e168f3fe75a9ecb2eceb72f", "repo_path": "integration/gaia-central" } From 9953a3a0fa5eaa54a1c31254c43221145477627d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 11:27:33 -0700 Subject: [PATCH 67/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 7418e87f31c..dcfa7c8a539 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 25b276d8c4f..9c262d13a92 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 19675c59210..405367e087d 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 a888ef04098..62393f146e0 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index 067bec658a3..81b4ccfd294 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 25b276d8c4f..9c262d13a92 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 9bdb0725849..20631bffdae 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 ea3e0e0fb59..d28cee53969 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 09391436e3e..bcd6a292697 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 d849670cfe6..1d6d27d139f 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 54f709bee77cd2f121be0d72732c7f963bc41f35 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 13:05:18 -0700 Subject: [PATCH 68/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/54c3c717ca6d Author: autolander Desc: Bug 1157895 - merge pull request #29748 from Cwiiis:bug1157895-fix-gaia-grid-height to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/51a225a1e081 Author: Chris Lord Desc: Bug 1157895 - Fix gaia-grid being too tall sometimes. r=kgrandon If the last item in the grid was in the last column position, it would incorrectly add to the height of the grid. --- 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 a1634407a14..24c6eea9f53 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "a9f6218d6b79e93072677515a5fc15f226233f5c", + "git_revision": "649d6ea599bbcba11d11032d85267c99837831e8", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "395d10bf55adfe192e168f3fe75a9ecb2eceb72f", + "revision": "54c3c717ca6d11f75838376eb80f4393935cc2da", "repo_path": "integration/gaia-central" } From 616f862421a2f52f6882eac148056341f76855d3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 13:07:30 -0700 Subject: [PATCH 69/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index dcfa7c8a539..b94f557e63c 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 9c262d13a92..099063fb347 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 405367e087d..6e4f96bd1d5 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 62393f146e0..bf62e8f035e 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index 81b4ccfd294..3b0a860b0ed 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 9c262d13a92..099063fb347 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 20631bffdae..9b0bb0a4669 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 d28cee53969..c0536548884 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 bcd6a292697..3ce6a6ba33f 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 1d6d27d139f..1024b2bffb4 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 9d2e1d0bb8df2259df8b650a4c72b33222f5c5af Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 13:22:38 -0700 Subject: [PATCH 70/80] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/e4a713e18ae0 Author: autolander Desc: Bug 1138718 - merge pull request #28908 from zbraniecki:1138718-update-notifications-l10n-api to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/41db9008fbc5 Author: Zibi Braniecki Desc: Bug 1138718 - Update Camera's Notification API to use L10n API ======== https://hg.mozilla.org/integration/gaia-central/rev/0882381cc764 Author: autolander Desc: Bug 1158238 - merge pull request #29718 from KevinGrandon:bug_1158238_app_import_activity to mozilla-b2g:master ======== https://hg.mozilla.org/integration/gaia-central/rev/3c66c0cdf2a0 Author: Kevin Grandon Desc: Bug 1158238 - [System] Add import activity r=kgrandon r=justindarc --- 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 24c6eea9f53..52351051f7a 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "649d6ea599bbcba11d11032d85267c99837831e8", + "git_revision": "5d7cd877353dd3bd43f4719ae6a076a92edda717", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "54c3c717ca6d11f75838376eb80f4393935cc2da", + "revision": "e4a713e18ae03cb6c25761b4a4223d6a0e7dc98f", "repo_path": "integration/gaia-central" } From d48ab47bc516bb5f74a44cd4a742665ec031a745 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 13:24:50 -0700 Subject: [PATCH 71/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index b94f557e63c..e3fc763f9ef 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 099063fb347..511a8331c4a 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 6e4f96bd1d5..18f0d69874d 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 bf62e8f035e..84b36b11fbe 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index 3b0a860b0ed..e7691b1a635 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 099063fb347..511a8331c4a 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 9b0bb0a4669..a47ea1c18c0 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 c0536548884..ea4cc469626 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 3ce6a6ba33f..59c98fae704 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 1024b2bffb4..cf9df735893 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From b7e4988cb25070191ff69326ed82e601a0593369 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 14:10:14 -0700 Subject: [PATCH 72/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/1e59eca7f12b Author: Michael Henretty Desc: Merge pull request #29533 from mikehenrty/bug-1154989-remove-old-test Bug 1154989 - Remove obsolete notification test ======== https://hg.mozilla.org/integration/gaia-central/rev/fdae86b89d11 Author: Michael Henretty Desc: Bug 1154989 - Remove obsolete notification test --- 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 52351051f7a..4acc63ed6f4 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "5d7cd877353dd3bd43f4719ae6a076a92edda717", + "git_revision": "f6c8e2ba974d5bb81f2e23f8df264b23fc7bcc4b", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "e4a713e18ae03cb6c25761b4a4223d6a0e7dc98f", + "revision": "1e59eca7f12b824cb9abab992fb967fe71698987", "repo_path": "integration/gaia-central" } From cadfcf738f321ab808991f7a2b2cd65fbf3dce03 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 14:12:45 -0700 Subject: [PATCH 73/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index e3fc763f9ef..13d5dc7e1e5 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 511a8331c4a..0975ecd28cc 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 18f0d69874d..ed638b2fb99 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 84b36b11fbe..2402041cc22 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index e7691b1a635..adb6cfe55a7 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 511a8331c4a..0975ecd28cc 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 a47ea1c18c0..e2e986c0fbd 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 ea4cc469626..e4deaa6d118 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 59c98fae704..85807e733c2 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 cf9df735893..3d323805278 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 3b23189baa5f6a2449376f7d3991b23b4515ae23 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 15:00:04 -0700 Subject: [PATCH 74/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 13d5dc7e1e5..b1a81ab5f61 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -134,7 +134,7 @@ - + From 784d5f66659f1466dde2a058da1f57cfc02304aa Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 15:30:15 -0700 Subject: [PATCH 75/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/ada78e075685 Author: Russ Nicoletti Desc: Merge pull request #29700 from russnicoletti/bug-1151775 Bug 1151775 - [Flame][Video]Share a video to mail/Messages and then back to Video, the video can't be played r=djf ======== https://hg.mozilla.org/integration/gaia-central/rev/f15fccd33137 Author: Russ Nicoletti Desc: Bug 1151775 - [Flame][Video]Share a video to mail/Messages and then back to Video, the video can't be played --- 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 4acc63ed6f4..9bd6a68766d 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "f6c8e2ba974d5bb81f2e23f8df264b23fc7bcc4b", + "git_revision": "5d0d1049a520625c5ad214bdfacb850ef423b5f5", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "1e59eca7f12b824cb9abab992fb967fe71698987", + "revision": "ada78e075685c3289bfb1521e1a5b50eaee8a9d3", "repo_path": "integration/gaia-central" } From a54802da5a68677c0ad1421d0f7bd733a9d25598 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 15:32:29 -0700 Subject: [PATCH 76/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index b1a81ab5f61..be635f927ee 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 0975ecd28cc..838e0a25605 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 ed638b2fb99..9df974c2688 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 2402041cc22..2c1df15127c 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index adb6cfe55a7..f1a0ef32c86 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 0975ecd28cc..838e0a25605 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 e2e986c0fbd..7784c527bef 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 e4deaa6d118..bedaee8a90f 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 85807e733c2..6bb34a271c6 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 3d323805278..26b28d59384 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 903c0467d1a549d26e8333955a345da65ec1230a Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 21:35:33 -0700 Subject: [PATCH 77/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8ad36bed6b86 Author: Russ Nicoletti Desc: Merge pull request #29753 from russnicoletti/bug-1156612 Bug 1156612 - Fix remaining video jshint issues r=kgrandon ======== https://hg.mozilla.org/integration/gaia-central/rev/16a629e0d50a Author: Russ Nicoletti Desc: Bug 1156612 - Fix remaining video jshint issues --- 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 9bd6a68766d..0200ca96226 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "5d0d1049a520625c5ad214bdfacb850ef423b5f5", + "git_revision": "70f69dd51991ab98c34269919e1adc7aeabc8320", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "ada78e075685c3289bfb1521e1a5b50eaee8a9d3", + "revision": "8ad36bed6b86d25dfad34fd1377b15b36a868a67", "repo_path": "integration/gaia-central" } From a983003a36ec4b9a10f6c8a264f5957c9228ba75 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 21:37:53 -0700 Subject: [PATCH 78/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index be635f927ee..7bb6cd6ef9f 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 838e0a25605..56afd3553bd 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 9df974c2688..6f9fbb7fd10 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 2c1df15127c..9472df17345 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index f1a0ef32c86..d2dbee95cb5 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 838e0a25605..56afd3553bd 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 7784c527bef..ff351734fa0 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 bedaee8a90f..f187a05bcc2 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 6bb34a271c6..d1019063c72 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 26b28d59384..9d3d6328b00 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From baa9a1fea2d5d7b8169369d8871599b241af2b5a Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 23:45:15 -0700 Subject: [PATCH 79/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/97f067180960 Author: Ghislain 'Aus' Lacroix Desc: Merge pull request #29760 from nullaus/master Bug 1141792 - Use npm-cache task. r=jlal ======== https://hg.mozilla.org/integration/gaia-central/rev/6f9438c1b8d9 Author: Ghislain 'Aus' Lacroix Desc: Bug 1141792 - Use npm-cache task. r=jlal --- 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 0200ca96226..c359f1b3207 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "70f69dd51991ab98c34269919e1adc7aeabc8320", + "git_revision": "e5c1905b0144a855537fd857d62ec7a3393bb334", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "8ad36bed6b86d25dfad34fd1377b15b36a868a67", + "revision": "97f0671809608b83775857fce9a7f7eba056d5d3", "repo_path": "integration/gaia-central" } From 63f944542fe15dc3124a7d8b0d9d0ef2e4ba591f Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Mon, 27 Apr 2015 23:47:28 -0700 Subject: [PATCH 80/80] 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-l/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 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 7bb6cd6ef9f..de1719961dd 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 56afd3553bd..0a72839c0a7 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 6f9fbb7fd10..17deed36a4f 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 9472df17345..2613cb9ff26 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-l/sources.xml b/b2g/config/emulator-l/sources.xml index d2dbee95cb5..839c694a667 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 56afd3553bd..0a72839c0a7 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 ff351734fa0..6ec29f9e95c 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 f187a05bcc2..45a49988952 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 d1019063c72..9ed13c39e6d 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 9d3d6328b00..9efdd46854f 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - +