From afb59c871d731c7d4b57d4f56c7be90f0291f57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 12 Sep 2017 08:41:17 +0200 Subject: [PATCH 01/17] Bug 1387942: Relax backdrop frame parenthood assertion, and re-enable test. r=xidorn MozReview-Commit-ID: 99I3apwe52l --HG-- extra : rebase_source : a9900b925cb58e095572fca75e211cc0e16c942f --- dom/html/test/test_fullscreen-api.html | 9 --------- layout/base/ServoRestyleManager.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/dom/html/test/test_fullscreen-api.html b/dom/html/test/test_fullscreen-api.html index e21f91def704..2564ea8f8c1b 100644 --- a/dom/html/test/test_fullscreen-api.html +++ b/dom/html/test/test_fullscreen-api.html @@ -77,15 +77,6 @@ function shouldSkipTest(test) { } } } - if (SpecialPowers.DOMWindowUtils.isStyledByServo && - SpecialPowers.isDebugBuild && - navigator.platform.indexOf('Mac') >= 0) { - if (test == "file_fullscreen-backdrop.html") { - todo(false, `${test} skipped due to bug 1387942`); - return true; - } - } - return false; } diff --git a/layout/base/ServoRestyleManager.cpp b/layout/base/ServoRestyleManager.cpp index 90037333f08e..7fe7641e3925 100644 --- a/layout/base/ServoRestyleManager.cpp +++ b/layout/base/ServoRestyleManager.cpp @@ -556,8 +556,10 @@ UpdateBackdropIfNeeded(nsIFrame* aFrame, /* aPseudoElement = */ nullptr); // NOTE(emilio): We can't use the changes handled for the owner of the - // backdrop frame, since it's out of flow, and parented to the viewport frame. - MOZ_ASSERT(backdropFrame->GetParent()->IsViewportFrame()); + // backdrop frame, since it's out of flow, and parented to the viewport or + // canvas frame (depending on the `position` value). + MOZ_ASSERT(backdropFrame->GetParent()->IsViewportFrame() || + backdropFrame->GetParent()->IsCanvasFrame()); nsTArray wrappersToRestyle; ServoRestyleState state(aStyleSet, aChangeList, wrappersToRestyle); aFrame->UpdateStyleOfOwnedChildFrame(backdropFrame, newContext, state); From e629f92818eb0c2b8ff7da000297f781a47fb098 Mon Sep 17 00:00:00 2001 From: KuoE0 Date: Wed, 6 Sep 2017 14:31:36 +0800 Subject: [PATCH 02/17] Bug 1229979 - (Part 1) Make the color of decoration line shadow be as same as the color of the text shadow. r=jfkthame Multi-color shadow is not allowed in spec. We could use the same color of the text as the color of the decoration line when we paint the shadow. MozReview-Commit-ID: AK9NoseSE0h --HG-- extra : rebase_source : 48a84e73a7ee76b615c255a440cbe119fa8f56f0 --- layout/generic/nsTextFrame.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index fdd2fa33128f..c136b667fe73 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -6494,15 +6494,8 @@ nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams, if (!shadowContext) return; - nscolor shadowColor; - const nscolor* decorationOverrideColor; - if (aShadowDetails->mHasColor) { - shadowColor = aShadowDetails->mColor; - decorationOverrideColor = &shadowColor; - } else { - shadowColor = aParams.foregroundColor; - decorationOverrideColor = nullptr; - } + nscolor shadowColor = aShadowDetails->mHasColor ? aShadowDetails->mColor + : aParams.foregroundColor; if (aParams.textDrawer) { wr::TextShadow wrShadow; @@ -6538,7 +6531,8 @@ nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams, aParams.context == shadowContext ? shadowColor : NS_RGB(0, 0, 0); params.clipEdges = aParams.clipEdges; params.drawSoftHyphen = (GetStateBits() & TEXT_HYPHEN_BREAK) != 0; - params.decorationOverrideColor = decorationOverrideColor; + // Multi-color shadow is not allowed, so we use the same color of the text color. + params.decorationOverrideColor = ¶ms.textColor; DrawText(aParams.range, aParams.textBaselinePt + shadowOffset, params); contextBoxBlur.DoPaint(); From 650dd7945ac31c27d5403cd36ef69b45e71a9d7e Mon Sep 17 00:00:00 2001 From: KuoE0 Date: Thu, 7 Sep 2017 11:00:11 +0800 Subject: [PATCH 03/17] Bug 1229979 - (Part 2) Update reference of test case. r=jfkthame MozReview-Commit-ID: CFChebe4JLP --HG-- extra : rebase_source : 676f80747e1f437aa2fe845adf9344ef172f9bf5 --- .../decorations-multiple-zorder-ref.html | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/layout/reftests/text-shadow/decorations-multiple-zorder-ref.html b/layout/reftests/text-shadow/decorations-multiple-zorder-ref.html index f071413f714d..5268c57ae0c2 100644 --- a/layout/reftests/text-shadow/decorations-multiple-zorder-ref.html +++ b/layout/reftests/text-shadow/decorations-multiple-zorder-ref.html @@ -2,14 +2,23 @@ -
testforquirks
-
test
+
test
-
testforquirks
-
testfor
+ +
testfor
+
testfor
-
testforquirks
-
testforquirks
+ +
testforquirks
+
testforquirks
From ae3bc947afd85e309ae8d79eacf98657e8e3f5b3 Mon Sep 17 00:00:00 2001 From: James Cheng Date: Mon, 11 Sep 2017 17:17:55 +0800 Subject: [PATCH 04/17] Bug 1398102 - canPlayType should return 'maybe' if the codec parameter is empty. r=gerald MozReview-Commit-ID: BmzIUOuaTj9 --HG-- extra : rebase_source : 530b713cf259920b65181d9459323f5f14bae39e --- dom/html/HTMLMediaElement.cpp | 15 ++++++++++++++- .../mime-types/canPlayType.html.ini | 10 ---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 6c1b0ee0a7ab..b87d3437be47 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -4647,6 +4647,17 @@ HTMLMediaElement::GetCanPlay(const nsAString& aType, // demuxer can handle VP9 in fragmented MP4. return CANPLAY_NO; } + if (status == CANPLAY_YES && + (*containerType).ExtendedType().Codecs().IsEmpty()) { + // Per spec: 'Generally, a user agent should never return "probably" for a + // type that allows the `codecs` parameter if that parameter is not present.' + // As all our currently-supported types allow for `codecs`, we can do this + // check here. + // TODO: Instead, missing `codecs` should be checked in each decoder's + // `IsSupportedType` call from `CanHandleCodecsType()`. + // See bug 1399023. + return CANPLAY_MAYBE; + } return status; } @@ -4664,10 +4675,12 @@ HTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult) case CANPLAY_YES: aResult.AssignLiteral("probably"); break; - default: case CANPLAY_MAYBE: aResult.AssignLiteral("maybe"); break; + default: + MOZ_ASSERT_UNREACHABLE("Unexpected case."); + break; } LOG(LogLevel::Debug, ("%p CanPlayType(%s) = \"%s\"", this, diff --git a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini index 477a04e54ce2..653f4c51a4ee 100644 --- a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini +++ b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini @@ -1,10 +1,5 @@ [canPlayType.html] type: testharness - [audio/mp4 (optional)] - expected: - if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL - if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL - [audio/mp4; codecs="mp4a.40.2" (optional)] expected: if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL @@ -19,11 +14,6 @@ [video/3gpp; codecs="mp4v.20.8" (optional)] expected: FAIL - [video/mp4 (optional)] - expected: - if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL - if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL - [video/mp4; codecs="mp4a.40.2" (optional)] expected: if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL From e0cb8d320b9f618f6182de230ed17a6277dd1b74 Mon Sep 17 00:00:00 2001 From: Andi-Bogdan Postelnicu Date: Tue, 12 Sep 2017 10:30:17 +0300 Subject: [PATCH 05/17] Bug 1398785 - Kill structurally dead code in NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN generated by Coverity. r=sylvestre MozReview-Commit-ID: AB3DLFft5aw --HG-- extra : rebase_source : 6d51c98df43e750d8b21aa8d5de62ab1632afaba --- tools/coverity/model.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/coverity/model.cpp b/tools/coverity/model.cpp index fce193761e85..a150df90125b 100644 --- a/tools/coverity/model.cpp +++ b/tools/coverity/model.cpp @@ -54,6 +54,14 @@ MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine) #define NS_RUNTIMEABORT(msg) __coverity_panic__() +// Kills Structurally dead code (UNREACHABLE) +#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \ + NS_IMETHODIMP_(bool) \ + NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void* p) \ + { \ + __coverity_panic__(); \ + _class* tmp = DowncastCCParticipant<_class>(p); + int GET_JUMP_OFFSET(jsbytecode* pc) { From 3033199142da20505541cd795018631c1fc88e12 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 12 Sep 2017 02:09:25 -0500 Subject: [PATCH 06/17] servo: Merge #18454 - Update WR (handle text runs requiring batch splits, clip optimizations) (from glennw:update-wr-text-runs); r=jdm Source-Repo: https://github.com/servo/servo Source-Revision: efd2d5e4ccd9d63442ecf11196bb8b909e7399d2 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 3611d4fe5eaec5cf6efdaeae1b19bc039b7d011b --- servo/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servo/Cargo.lock b/servo/Cargo.lock index 12afd44640d4..6a5c4cf19fcc 100644 --- a/servo/Cargo.lock +++ b/servo/Cargo.lock @@ -3587,7 +3587,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.50.0" -source = "git+https://github.com/servo/webrender#3d58efaecdc5897de057beab57adc031bc2e187e" +source = "git+https://github.com/servo/webrender#cd1855550857b910f752359b48c5cc053419c358" dependencies = [ "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3615,7 +3615,7 @@ dependencies = [ [[package]] name = "webrender_api" version = "0.50.0" -source = "git+https://github.com/servo/webrender#3d58efaecdc5897de057beab57adc031bc2e187e" +source = "git+https://github.com/servo/webrender#cd1855550857b910f752359b48c5cc053419c358" dependencies = [ "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", From 66769e7d7e1360ba1169393a197330fdda419cc4 Mon Sep 17 00:00:00 2001 From: Ethan Lin Date: Wed, 6 Sep 2017 16:44:12 +0800 Subject: [PATCH 07/17] Bug 1392523 - Enable layers-free mode for some reftests. r=kats MozReview-Commit-ID: 2alMRSD5PmL --HG-- extra : rebase_source : f5454e41fa656ac0f5fa28ddf1d5bee827346aed --- layout/reftests/bugs/reftest.list | 2 ++ layout/reftests/css-animations/reftest.list | 1 + layout/reftests/image/reftest.list | 1 + layout/reftests/invalidation/reftest.list | 1 + layout/reftests/transform/reftest.list | 2 ++ 5 files changed, 7 insertions(+) diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index df0593b2fe09..6d8aa2931463 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1651,11 +1651,13 @@ fuzzy-if(Android,8,300) fuzzy-if(skiaContent,1,40000) == 625409-1.html 625409-1- fuzzy-if(skiaContent,1,500) == 630835-1.html about:blank == 631352-1.html 631352-1-ref.html skip-if(!haveTestPlugin) fails-if(Android) fuzzy-if(winWidget&&!layersGPUAccelerated,102,535) fuzzy-if(skiaContent&&!Android,102,11000) HTTP == 632423-1.html 632423-1-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == 632423-1.html 632423-1-ref.html skip-if(Android) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-ref.html == 632781-normalsize.html 632781-ref.html fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,559) fuzzy-if(!isDebugBuild&>kWidget&&/^Linux\x20i686/.test(http.oscpu),102,140) == 633344-1.html 633344-1-ref.html # bug 1103623, Linux32 from GCC update fuzzy-if(skiaContent,1,500) == 634232-1.html 634232-1-ref.html fuzzy-if(skiaContent,3,120000) == 635302-1.html 635302-1-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == 635302-1.html 635302-1-ref.html fuzzy(1,68) fuzzy-if(gtkWidget,1,70) fails-if(Android) fuzzy-if(skiaContent&&!Android,1,300) == 635373-1.html 635373-1-ref.html random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,20,118) fuzzy-if(skiaContent&&!Android,2,550) == 635373-2.html 635373-2-ref.html random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,20,116) fuzzy-if(skiaContent&&!Android,2,650) == 635373-3.html 635373-3-ref.html diff --git a/layout/reftests/css-animations/reftest.list b/layout/reftests/css-animations/reftest.list index 70b00591e638..61e3e9ea6101 100644 --- a/layout/reftests/css-animations/reftest.list +++ b/layout/reftests/css-animations/reftest.list @@ -43,6 +43,7 @@ fails == background-position-running.html background-position-ref.html # This te fails == background-position-important.html background-position-ref.html # This test fails the reftest-opaque-layer check since animating background-position overridden by a non-animated !important style also creates an active layer, and reftest-opaque-layer only handles items that are assigned to PaintedLayers. == mask-position-after-finish-1a.html mask-anim-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == mask-position-after-finish-1a.html mask-anim-ref.html == mask-position-after-finish-1b.html mask-anim-ref.html == mask-position-in-delay-1a.html mask-anim-ref.html == mask-position-in-delay-1b.html mask-anim-ref.html diff --git a/layout/reftests/image/reftest.list b/layout/reftests/image/reftest.list index 337c84ded40c..8b1e92f2ae3f 100644 --- a/layout/reftests/image/reftest.list +++ b/layout/reftests/image/reftest.list @@ -1,4 +1,5 @@ fuzzy-if(Android,8,30) == background-image-zoom-1.html background-image-zoom-1-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == background-image-zoom-1.html background-image-zoom-1-ref.html fails-if(usesRepeatResampling) == background-image-zoom-2.html about:blank == image-seam-1a.html image-seam-1-ref.html == image-seam-1b.html image-seam-1-ref.html diff --git a/layout/reftests/invalidation/reftest.list b/layout/reftests/invalidation/reftest.list index 40a86ac30ad4..65cef55b9309 100644 --- a/layout/reftests/invalidation/reftest.list +++ b/layout/reftests/invalidation/reftest.list @@ -86,6 +86,7 @@ pref(layers.single-tile.enabled,false) != fast-scrolling.html about:blank == negative-w-component.html negative-w-component-ref.html == mask-invalidation-1a.html mask-invalidation-1-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == mask-invalidation-1a.html mask-invalidation-1-ref.html == mask-invalidation-1b.html mask-invalidation-1-ref.html == mask-invalidation-2a.html mask-invalidation-2-ref.html diff --git a/layout/reftests/transform/reftest.list b/layout/reftests/transform/reftest.list index f05f1c9755e5..a4a22b7a4e33 100644 --- a/layout/reftests/transform/reftest.list +++ b/layout/reftests/transform/reftest.list @@ -31,6 +31,7 @@ fuzzy-if(webrender,1,27) == compound-1a.html compound-1-ref.html == translate-1b.html translate-1-ref.html == translate-1c.html translate-1-ref.html == translate-1d.html translate-1-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == translate-1d.html translate-1-ref.html == translate-1e.html translate-1-ref.html == translate-2a.html translate-2-ref.html == translate-3.html translate-3-ref.html @@ -46,6 +47,7 @@ random == rotate-1f.html rotate-1-ref.html # rotate: 90deg rotations should be indistinguishable from objects constructed # to look the same. == rotate-2a.html rotate-2-ref.html +pref(gfx.webrender.layers-free,true) skip-if(!webrender) == rotate-2a.html rotate-2-ref.html == rotate-2b.html rotate-2-ref.html # -transform-origin: We should NOT get the same images when using different # -transform-origins. From 797770f328eea55c5928f68b7a27783d94092af3 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Tue, 12 Sep 2017 11:03:50 +0200 Subject: [PATCH 08/17] Backed out changeset 939ecf1b80cb (bug 1398102) for failing mda's dom/media/test/test_can_play_type_wave.html. r=backout --- dom/html/HTMLMediaElement.cpp | 15 +-------------- .../mime-types/canPlayType.html.ini | 10 ++++++++++ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index b87d3437be47..6c1b0ee0a7ab 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -4647,17 +4647,6 @@ HTMLMediaElement::GetCanPlay(const nsAString& aType, // demuxer can handle VP9 in fragmented MP4. return CANPLAY_NO; } - if (status == CANPLAY_YES && - (*containerType).ExtendedType().Codecs().IsEmpty()) { - // Per spec: 'Generally, a user agent should never return "probably" for a - // type that allows the `codecs` parameter if that parameter is not present.' - // As all our currently-supported types allow for `codecs`, we can do this - // check here. - // TODO: Instead, missing `codecs` should be checked in each decoder's - // `IsSupportedType` call from `CanHandleCodecsType()`. - // See bug 1399023. - return CANPLAY_MAYBE; - } return status; } @@ -4675,12 +4664,10 @@ HTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult) case CANPLAY_YES: aResult.AssignLiteral("probably"); break; + default: case CANPLAY_MAYBE: aResult.AssignLiteral("maybe"); break; - default: - MOZ_ASSERT_UNREACHABLE("Unexpected case."); - break; } LOG(LogLevel::Debug, ("%p CanPlayType(%s) = \"%s\"", this, diff --git a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini index 653f4c51a4ee..477a04e54ce2 100644 --- a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini +++ b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html.ini @@ -1,5 +1,10 @@ [canPlayType.html] type: testharness + [audio/mp4 (optional)] + expected: + if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL + if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL + [audio/mp4; codecs="mp4a.40.2" (optional)] expected: if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL @@ -14,6 +19,11 @@ [video/3gpp; codecs="mp4v.20.8" (optional)] expected: FAIL + [video/mp4 (optional)] + expected: + if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL + if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL + [video/mp4; codecs="mp4a.40.2" (optional)] expected: if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL From 7a2d2e198cd340100c59b605bc70ffa7ab3782aa Mon Sep 17 00:00:00 2001 From: JW Wang Date: Fri, 8 Sep 2017 15:09:37 +0800 Subject: [PATCH 09/17] Bug 1395855. P1 - remove ChannelMediaResource::mOffset so we have less data race to worry about. r=cpearce We have MediaCacheStream::mChannelOffset to keep the download positon. We don't need 2 variables for the same purpose. MozReview-Commit-ID: IpnEJWuA9A9 --HG-- extra : rebase_source : 8e720d878c12555d0a5528167c183ddb881b249e extra : source : 623cf4cc3ab5ad0d9d263bac05a58699b3577277 --- dom/media/MediaCache.cpp | 7 +++++ dom/media/MediaCache.h | 2 ++ dom/media/MediaResource.cpp | 53 +++++++++++++++---------------------- dom/media/MediaResource.h | 9 ++++--- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/dom/media/MediaCache.cpp b/dom/media/MediaCache.cpp index 40e8a433869b..24dca251f9e1 100644 --- a/dom/media/MediaCache.cpp +++ b/dom/media/MediaCache.cpp @@ -2156,6 +2156,13 @@ MediaCacheStream::GetLength() return mStreamLength; } +int64_t +MediaCacheStream::GetOffset() const +{ + MOZ_ASSERT(NS_IsMainThread()); + return mChannelOffset; +} + int64_t MediaCacheStream::GetNextCachedData(int64_t aOffset) { diff --git a/dom/media/MediaCache.h b/dom/media/MediaCache.h index 1e9037701339..32ed2efecfba 100644 --- a/dom/media/MediaCache.h +++ b/dom/media/MediaCache.h @@ -285,6 +285,8 @@ public: // If we've successfully read data beyond the originally reported length, // we return the end of the data we've read. int64_t GetLength(); + // Return the offset where next channel data will write to. Main thread only. + int64_t GetOffset() const; // Returns the unique resource ID. Call only on the main thread or while // holding the media cache lock. int64_t GetResourceID() { return mResourceID; } diff --git a/dom/media/MediaResource.cpp b/dom/media/MediaResource.cpp index 5daf42209a57..201201a3e2c2 100644 --- a/dom/media/MediaResource.cpp +++ b/dom/media/MediaResource.cpp @@ -80,7 +80,6 @@ ChannelMediaResource::ChannelMediaResource(MediaResourceCallback* aCallback, nsIURI* aURI, bool aIsPrivateBrowsing) : BaseMediaResource(aCallback, aChannel, aURI) - , mOffset(0) , mReopenOnError(false) , mCacheStream(this, aIsPrivateBrowsing) , mSuspendAgent(mChannel) @@ -93,7 +92,6 @@ ChannelMediaResource::ChannelMediaResource( nsIURI* aURI, const MediaChannelStatistics& aStatistics) : BaseMediaResource(aCallback, aChannel, aURI) - , mOffset(0) , mReopenOnError(false) , mCacheStream(this, /* aIsPrivateBrowsing = */ false) , mChannelStatistics(aStatistics) @@ -284,26 +282,19 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest) if (rangeTotal != -1) { contentLength = std::max(contentLength, rangeTotal); } - // Give some warnings if the ranges are unexpected. - // XXX These could be error conditions. - NS_WARNING_ASSERTION( - mOffset == rangeStart, - "response range start does not match current offset"); - mOffset = rangeStart; mCacheStream.NotifyDataStarted(rangeStart); } acceptsRanges = gotRangeHeader; - } else if (mOffset > 0 && responseStatus == HTTP_OK_CODE) { + } else if (GetOffset() > 0 && responseStatus == HTTP_OK_CODE) { // If we get an OK response but we were seeking, or requesting a byte // range, then we have to assume that seeking doesn't work. We also need // to tell the cache that it's getting data for the start of the stream. mCacheStream.NotifyDataStarted(0); - mOffset = 0; // The server claimed it supported range requests. It lied. acceptsRanges = false; } - if (mOffset == 0 && contentLength >= 0 && + if (GetOffset() == 0 && contentLength >= 0 && (responseStatus == HTTP_OK_CODE || responseStatus == HTTP_PARTIAL_RESPONSE_CODE)) { mCacheStream.NotifyDataLength(contentLength); @@ -398,14 +389,14 @@ ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) // cause us to just re-read the stream, which would be really bad. if (mReopenOnError && aStatus != NS_ERROR_PARSED_DATA_CACHED && aStatus != NS_BINDING_ABORTED && - (mOffset == 0 || (GetLength() > 0 && mOffset != GetLength() && - mCacheStream.IsTransportSeekable()))) { + (GetOffset() == 0 || (GetLength() > 0 && GetOffset() != GetLength() && + mCacheStream.IsTransportSeekable()))) { // If the stream did close normally, restart the channel if we're either // at the start of the resource, or if the server is seekable and we're // not at the end of stream. We don't restart the stream if we're at the // end because not all web servers handle this case consistently; see: // https://bugzilla.mozilla.org/show_bug.cgi?id=1373618#c36 - nsresult rv = CacheClientSeek(mOffset, false); + nsresult rv = CacheClientSeek(GetOffset(), false); if (NS_SUCCEEDED(rv)) { return rv; } @@ -435,7 +426,7 @@ ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, { mChannel = aNew; mSuspendAgent.NotifyChannelOpened(mChannel); - return SetupChannelHeaders(); + return SetupChannelHeaders(GetOffset()); } nsresult @@ -444,11 +435,6 @@ ChannelMediaResource::CopySegmentToCache(nsIPrincipal* aPrincipal, uint32_t aCount, uint32_t* aWriteCount) { - // Keep track of where we're up to. - LOG("CopySegmentToCache at mOffset [%" PRId64 "] add " - "[%d] bytes for decoder[%p]", - mOffset, aCount, mCallback.get()); - mOffset += aCount; mCacheStream.NotifyDataReceived(aCount, aFromSegment, aPrincipal); *aWriteCount = aCount; return NS_OK; @@ -528,7 +514,7 @@ ChannelMediaResource::Open(nsIStreamListener** aStreamListener) return rv; } - MOZ_ASSERT(mOffset == 0, "Who set mOffset already?"); + MOZ_ASSERT(GetOffset() == 0, "Who set offset already?"); mListener = new Listener(this); *aStreamListener = mListener; NS_ADDREF(*aStreamListener); @@ -536,7 +522,7 @@ ChannelMediaResource::Open(nsIStreamListener** aStreamListener) } nsresult -ChannelMediaResource::OpenChannel() +ChannelMediaResource::OpenChannel(int64_t aOffset) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mChannel); @@ -546,7 +532,7 @@ ChannelMediaResource::OpenChannel() nsresult rv = mChannel->SetNotificationCallbacks(mListener.get()); NS_ENSURE_SUCCESS(rv, rv); - rv = SetupChannelHeaders(); + rv = SetupChannelHeaders(aOffset); NS_ENSURE_SUCCESS(rv, rv); rv = mChannel->AsyncOpen2(mListener); @@ -561,7 +547,8 @@ ChannelMediaResource::OpenChannel() return NS_OK; } -nsresult ChannelMediaResource::SetupChannelHeaders() +nsresult +ChannelMediaResource::SetupChannelHeaders(int64_t aOffset) { // Always use a byte range request even if we're reading from the start // of the resource. @@ -571,7 +558,7 @@ nsresult ChannelMediaResource::SetupChannelHeaders() if (hc) { // Use |mOffset| if seeking in a complete file download. nsAutoCString rangeString("bytes="); - rangeString.AppendInt(mOffset); + rangeString.AppendInt(aOffset); rangeString.Append('-'); nsresult rv = hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false); NS_ENSURE_SUCCESS(rv, rv); @@ -584,7 +571,7 @@ nsresult ChannelMediaResource::SetupChannelHeaders() NS_ENSURE_TRUE(element, NS_ERROR_FAILURE); element->SetRequestHeaders(hc); } else { - NS_ASSERTION(mOffset == 0, "Don't know how to seek on this channel type"); + NS_ASSERTION(aOffset == 0, "Don't know how to seek on this channel type"); return NS_ERROR_FAILURE; } return NS_OK; @@ -754,10 +741,10 @@ void ChannelMediaResource::Resume() // the channel dead; if the media cache wants to read some other data // in the future, it will call CacheClientSeek itself which will reopen the // channel. - if (totalLength < 0 || mOffset < totalLength) { + if (totalLength < 0 || GetOffset() < totalLength) { // There is (or may be) data to read at mOffset, so start reading it. // Need to recreate the channel. - CacheClientSeek(mOffset, false); + CacheClientSeek(GetOffset(), false); element->DownloadResumed(); } else { // The channel remains dead. Do not notify DownloadResumed() which @@ -863,8 +850,6 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume) CloseChannel(); - mOffset = aOffset; - if (aResume) { mSuspendAgent.Resume(); } @@ -878,7 +863,7 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume) nsresult rv = RecreateChannel(); NS_ENSURE_SUCCESS(rv, rv); - return OpenChannel(); + return OpenChannel(aOffset); } nsresult @@ -962,6 +947,12 @@ ChannelMediaResource::GetLength() return mCacheStream.GetLength(); } +int64_t +ChannelMediaResource::GetOffset() const +{ + return mCacheStream.GetOffset(); +} + // ChannelSuspendAgent bool diff --git a/dom/media/MediaResource.h b/dom/media/MediaResource.h index b66d9594a85d..a60d2f07c474 100644 --- a/dom/media/MediaResource.h +++ b/dom/media/MediaResource.h @@ -538,15 +538,17 @@ protected: uint32_t aCount); nsresult OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, uint32_t aFlags); - // Opens the channel, using an HTTP byte range request to start at mOffset + // Opens the channel, using an HTTP byte range request to start at aOffset // if possible. Main thread only. - nsresult OpenChannel(); + nsresult OpenChannel(int64_t aOffset); nsresult RecreateChannel(); // Add headers to HTTP request. Main thread only. - nsresult SetupChannelHeaders(); + nsresult SetupChannelHeaders(int64_t aOffset); // Closes the channel. Main thread only. void CloseChannel(); + int64_t GetOffset() const; + // Parses 'Content-Range' header and returns results via parameters. // Returns error if header is not available, values are not parse-able or // values are out of range. @@ -568,7 +570,6 @@ protected: uint32_t* aWriteCount); // Main thread access only - int64_t mOffset; RefPtr mListener; // When this flag is set, if we get a network error we should silently // reopen the stream. From 8fb5559c5f80808b585f2d9d29308da194503c05 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Sat, 9 Sep 2017 00:37:40 +0800 Subject: [PATCH 10/17] Bug 1395855. P2 - store the offset of range request. r=cpearce So we know what to pass to SetupChannelHeaders() when the channel is redirected. MozReview-Commit-ID: DbCPGA3qIyn --HG-- extra : rebase_source : 4b8a5b620344fa261b243c0935ce49ebb7a9b4aa extra : source : dfe1a9fe59a623f4d1972f3184a5861cfef62ffd --- dom/media/MediaResource.cpp | 29 +++++++++++++++++------------ dom/media/MediaResource.h | 11 +++++++++-- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/dom/media/MediaResource.cpp b/dom/media/MediaResource.cpp index 201201a3e2c2..56fb41f7ee13 100644 --- a/dom/media/MediaResource.cpp +++ b/dom/media/MediaResource.cpp @@ -150,17 +150,20 @@ ChannelMediaResource::Listener::OnDataAvailable(nsIRequest* aRequest, } nsresult -ChannelMediaResource::Listener::AsyncOnChannelRedirect(nsIChannel* aOldChannel, - nsIChannel* aNewChannel, - uint32_t aFlags, - nsIAsyncVerifyRedirectCallback* cb) +ChannelMediaResource::Listener::AsyncOnChannelRedirect( + nsIChannel* aOld, + nsIChannel* aNew, + uint32_t aFlags, + nsIAsyncVerifyRedirectCallback* cb) { nsresult rv = NS_OK; - if (mResource) - rv = mResource->OnChannelRedirect(aOldChannel, aNewChannel, aFlags); + if (mResource) { + rv = mResource->OnChannelRedirect(aOld, aNew, aFlags, mOffset); + } - if (NS_FAILED(rv)) + if (NS_FAILED(rv)) { return rv; + } cb->OnRedirectVerifyCallback(NS_OK); return NS_OK; @@ -421,12 +424,14 @@ ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) } nsresult -ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, - uint32_t aFlags) +ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld, + nsIChannel* aNew, + uint32_t aFlags, + int64_t aOffset) { mChannel = aNew; mSuspendAgent.NotifyChannelOpened(mChannel); - return SetupChannelHeaders(GetOffset()); + return SetupChannelHeaders(aOffset); } nsresult @@ -515,7 +520,7 @@ ChannelMediaResource::Open(nsIStreamListener** aStreamListener) } MOZ_ASSERT(GetOffset() == 0, "Who set offset already?"); - mListener = new Listener(this); + mListener = new Listener(this, 0); *aStreamListener = mListener; NS_ADDREF(*aStreamListener); return NS_OK; @@ -528,7 +533,7 @@ ChannelMediaResource::OpenChannel(int64_t aOffset) MOZ_ASSERT(mChannel); MOZ_ASSERT(!mListener, "Listener should have been removed by now"); - mListener = new Listener(this); + mListener = new Listener(this, aOffset); nsresult rv = mChannel->SetNotificationCallbacks(mListener.get()); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/media/MediaResource.h b/dom/media/MediaResource.h index a60d2f07c474..a162bf342445 100644 --- a/dom/media/MediaResource.h +++ b/dom/media/MediaResource.h @@ -510,7 +510,10 @@ public: { ~Listener() {} public: - explicit Listener(ChannelMediaResource* aResource) : mResource(aResource) {} + Listener(ChannelMediaResource* aResource, int64_t aOffset) + : mResource(aResource) + , mOffset(aOffset) + {} NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER @@ -523,6 +526,7 @@ public: private: RefPtr mResource; + const int64_t mOffset; }; friend class Listener; @@ -536,7 +540,10 @@ protected: nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aStream, uint32_t aCount); - nsresult OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, uint32_t aFlags); + nsresult OnChannelRedirect(nsIChannel* aOld, + nsIChannel* aNew, + uint32_t aFlags, + int64_t aOffset); // Opens the channel, using an HTTP byte range request to start at aOffset // if possible. Main thread only. From 0acbea23acddb0e15f8685f7e44f9d5de23f07e1 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Wed, 6 Sep 2017 09:43:37 +0100 Subject: [PATCH 11/17] Bug 1397182 - stop expiring reader mode telemetry probes, r=rweiss+418169 MozReview-Commit-ID: 3Gjdfd3Byru --HG-- extra : rebase_source : 0d9cfe916210e977bf6dd75fa22b55ebe803862a --- toolkit/components/telemetry/Histograms.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index c51fd104c2a6..b1a554ae58d3 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -11767,7 +11767,7 @@ }, "READER_MODE_PARSE_RESULT" : { "record_in_processes": ["main", "content"], - "expires_in_version": "58", + "expires_in_version": "never", "alert_emails": ["firefox-dev@mozilla.org", "gijs@mozilla.com"], "kind": "enumerated", "n_values": 5, @@ -11775,7 +11775,7 @@ }, "READER_MODE_DOWNLOAD_RESULT" : { "record_in_processes": ["main", "content"], - "expires_in_version": "58", + "expires_in_version": "never", "alert_emails": ["firefox-dev@mozilla.org", "gijs@mozilla.com"], "kind": "enumerated", "n_values": 5, From bcda16e11408049b97f8f772ad1e271967d16af9 Mon Sep 17 00:00:00 2001 From: Nihanth Subramanya Date: Tue, 29 Aug 2017 16:40:56 +0530 Subject: [PATCH 12/17] Bug 1392219 - Always use native titlebar appearance on MacOS when it is enabled. r=dao MozReview-Commit-ID: 9ZUpci2iB4I --HG-- extra : rebase_source : 3b82f853f695cc519d05edb168704d994f0191bc --- browser/themes/osx/browser.css | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/themes/osx/browser.css b/browser/themes/osx/browser.css index dfd0edf0b633..7f473957f879 100644 --- a/browser/themes/osx/browser.css +++ b/browser/themes/osx/browser.css @@ -82,6 +82,7 @@ } #main-window:not([tabsintitlebar]) > #titlebar { + -moz-appearance: -moz-window-titlebar; height: 22px; /* The native titlebar on OS X is 22px tall. */ } From 7780b1e8465d054d9bd346967c036be6496a24a8 Mon Sep 17 00:00:00 2001 From: peter chang Date: Wed, 6 Sep 2017 16:29:52 +0800 Subject: [PATCH 13/17] Bug 1394308 - Apply inherited scale for OMTA to support layers-free, r=kats Expose the API to get/set inherited scale from stacking context and we can use these APIs to calculate correct scale for OMTA MozReview-Commit-ID: DZEkodHTy8v --HG-- extra : rebase_source : be3c978c8f48c9b1bfcd01cff6bb8200092b5e60 --- gfx/layers/wr/StackingContextHelper.cpp | 3 ++- gfx/layers/wr/StackingContextHelper.h | 12 +++++++++ layout/painting/nsDisplayList.cpp | 35 ++++++++++++++++++------- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/gfx/layers/wr/StackingContextHelper.cpp b/gfx/layers/wr/StackingContextHelper.cpp index 78c663dea082..e20a0714336b 100644 --- a/gfx/layers/wr/StackingContextHelper.cpp +++ b/gfx/layers/wr/StackingContextHelper.cpp @@ -102,6 +102,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen mTransform.PostScale(aParentSC.mXScale, aParentSC.mYScale, 1.0); mTransform.NudgeToIntegersFixedEpsilon(); + // Calculate the correct scale for current stacking context gfx::Size scale = mTransform.As2D().ScaleFactors(true); // Restore the scale to default if the scale is too small @@ -112,7 +113,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen mTransform.PreScale(1.0f/scale.width, 1.0f/scale.height, 1.0); - // Store the inherited scale if has + // Store the inherited scale for child this->mXScale = scale.width; this->mYScale = scale.height; } else { diff --git a/gfx/layers/wr/StackingContextHelper.h b/gfx/layers/wr/StackingContextHelper.h index f9b93e9bf776..ce1d3dba5a12 100644 --- a/gfx/layers/wr/StackingContextHelper.h +++ b/gfx/layers/wr/StackingContextHelper.h @@ -83,6 +83,18 @@ public: // Same but rounds the rectangle to ints after transforming. wr::LayoutRect ToRelativeLayoutRectRounded(const LayoutDeviceRect& aRect) const; + // Export the inherited scale + gfx::Size GetInheritedScale() const { + return gfx::Size(mXScale, mYScale); + } + + // Provide interface to setup the inherited scale to support + // special cases, like OMTA + void SetInheritedScale(const gfx::Size& aScale) { + mXScale = aScale.width; + mYScale = aScale.height; + } + bool IsBackfaceVisible() const { return mTransform.IsBackfaceVisible(); } private: diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index edb72c943467..8a517ec40cb4 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -7812,15 +7812,6 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu // transform animation, the transform value will be resolved // after animation sampling on the compositor transformForSC = nullptr; - - // Pass default transform to compositor in case gecko fails to - // get animated value after animation sampling. - OptionalTransform transformForCompositor = newTransformMatrix; - - OpAddCompositorAnimations - anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId), - transformForCompositor, void_t()); - aManager->WrBridge()->AddWebRenderParentCommand(anim); } gfx::Matrix4x4Typed boundTransform = ViewAs< gfx::Matrix4x4Typed >(newTransformMatrix); @@ -7841,6 +7832,32 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu nullptr, filters); + if (animationsId) { + // Get the inheritedScale from parent and pass the scale to compositor + // to get correct sampling result + gfx::Size scale = aSc.GetInheritedScale(); + for (layers::Animation& animation : animationInfo.GetAnimations()) { + if (animation.property() == eCSSProperty_transform) { + TransformData& transformData = animation.data().get_TransformData(); + transformData.inheritedXScale() = scale.width; + transformData.inheritedYScale() = scale.height; + } + } + + // Pass default transform to compositor in case gecko fails to + // get animated value after animation sampling. + OptionalTransform transformForCompositor = newTransformMatrix; + OpAddCompositorAnimations + anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId), + transformForCompositor, void_t()); + aManager->WrBridge()->AddWebRenderParentCommand(anim); + + // Since we passed a nullptr transformForSC to the StackingContextHelper, + // we now set up the correct inherited scale for the stacking context. + newTransformMatrix.PostScale(scale.width, scale.height, 1.0f); + sc.SetInheritedScale(newTransformMatrix.As2D().ScaleFactors(true)); + + } return mStoredList.CreateWebRenderCommands(aBuilder, sc, aParentCommands, aManager, aDisplayListBuilder); } From 75200fdf13ff4ffddae3123a252ad9698442a1e2 Mon Sep 17 00:00:00 2001 From: peter chang Date: Thu, 7 Sep 2017 11:50:41 +0800 Subject: [PATCH 14/17] Bug 1394308 - Pass perspective transform attribute to compositor for OMTA, r=kats MozReview-Commit-ID: EjyuCfnswqu --HG-- extra : rebase_source : 556db00f7c58b8b49bdafe9ca77785bce819a000 --- gfx/layers/wr/StackingContextHelper.cpp | 8 ++++++++ gfx/layers/wr/StackingContextHelper.h | 3 ++- layout/painting/nsDisplayList.cpp | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gfx/layers/wr/StackingContextHelper.cpp b/gfx/layers/wr/StackingContextHelper.cpp index e20a0714336b..8e8c4a24b90c 100644 --- a/gfx/layers/wr/StackingContextHelper.cpp +++ b/gfx/layers/wr/StackingContextHelper.cpp @@ -14,6 +14,7 @@ namespace layers { StackingContextHelper::StackingContextHelper() : mBuilder(nullptr) + , mHasPerspectiveTransform(false) , mXScale(1.0f) , mYScale(1.0f) { @@ -26,6 +27,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen const Maybe& aTransform, const nsTArray& aFilters) : mBuilder(&aBuilder) + , mHasPerspectiveTransform(false) , mXScale(1.0f) , mYScale(1.0f) { @@ -51,6 +53,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen gfx::Matrix4x4* aTransformPtr, const nsTArray& aFilters) : mBuilder(&aBuilder) + , mHasPerspectiveTransform(false) , mXScale(1.0f) , mYScale(1.0f) { @@ -83,6 +86,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen const nsTArray& aFilters, const gfx::CompositionOp& aMixBlendMode) : mBuilder(&aBuilder) + , mHasPerspectiveTransform(false) , mXScale(1.0f) , mYScale(1.0f) { @@ -92,6 +96,10 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen mTransform = *aTransformPtr; } + if (aPerspectivePtr) { + mHasPerspectiveTransform = true; + } + bool is2d = !aTransformPtr || (aTransformPtr->Is2D() && !aPerspectivePtr); if (is2d) { nsRect itemBounds = aDisplayList->GetClippedBoundsWithRespectToASR(aDisplayListBuilder, aItem->GetActiveScrolledRoot()); diff --git a/gfx/layers/wr/StackingContextHelper.h b/gfx/layers/wr/StackingContextHelper.h index ce1d3dba5a12..df2a543580e0 100644 --- a/gfx/layers/wr/StackingContextHelper.h +++ b/gfx/layers/wr/StackingContextHelper.h @@ -96,12 +96,13 @@ public: } bool IsBackfaceVisible() const { return mTransform.IsBackfaceVisible(); } + bool HasPerspectiveTransform() const { return mHasPerspectiveTransform; } private: wr::DisplayListBuilder* mBuilder; LayerPoint mOrigin; gfx::Matrix4x4 mTransform; - + bool mHasPerspectiveTransform; float mXScale; float mYScale; }; diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 8a517ec40cb4..cb49374ccf17 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -7841,6 +7841,7 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu TransformData& transformData = animation.data().get_TransformData(); transformData.inheritedXScale() = scale.width; transformData.inheritedYScale() = scale.height; + transformData.hasPerspectiveParent() = aSc.HasPerspectiveTransform(); } } From 3eb748d91ed3478ab1bc81c9123151039afb2eb1 Mon Sep 17 00:00:00 2001 From: Jing-wei Wu Date: Tue, 12 Sep 2017 14:54:53 +0800 Subject: [PATCH 15/17] Bug 1394720 - Refactor AnimatedProgressBar for performance tuning. r=walkingice MozReview-Commit-ID: LKekOvdMS6u --HG-- extra : rebase_source : c7e955e8ed44fc30d608f3482a7f33bd057cf0d3 --- .../org/mozilla/gecko/widget/AnimatedProgressBar.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/widget/AnimatedProgressBar.java b/mobile/android/base/java/org/mozilla/gecko/widget/AnimatedProgressBar.java index 48a14e3f779e..24cd9d924527 100644 --- a/mobile/android/base/java/org/mozilla/gecko/widget/AnimatedProgressBar.java +++ b/mobile/android/base/java/org/mozilla/gecko/widget/AnimatedProgressBar.java @@ -162,14 +162,14 @@ public class AnimatedProgressBar extends ThemedProgressBar { } else { canvas.getClipBounds(mRect); final float clipWidth = mRect.width() * mClipRatio; - canvas.save(); + final int saveCount = canvas.save(); if (mIsRtl) { canvas.clipRect(mRect.left, mRect.top, mRect.right - clipWidth, mRect.bottom); } else { canvas.clipRect(mRect.left + clipWidth, mRect.top, mRect.right, mRect.bottom); } super.onDraw(canvas); - canvas.restore(); + canvas.restoreToCount(saveCount); } } @@ -266,8 +266,11 @@ public class AnimatedProgressBar extends ThemedProgressBar { mClosingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { - mClipRatio = (float) valueAnimator.getAnimatedValue(); - invalidate(); + final float ratio = (float) valueAnimator.getAnimatedValue(); + if (mClipRatio != ratio) { + mClipRatio = ratio; + invalidate(); + } } }); mClosingAnimator.addListener(new Animator.AnimatorListener() { From 00681c0e8840a3d8ef437d3065d3337778107827 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 12 Sep 2017 03:25:36 -0500 Subject: [PATCH 16/17] servo: Merge #18453 - Refactor the style cache (from bholley:style_cache_refactor); r=emilio This is the first set of patches from https://bugzilla.mozilla.org/show_bug.cgi?id=1398658 Source-Repo: https://github.com/servo/servo Source-Revision: def983c29566133ab02ed40b9ab8c5e99da8e53e --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 1f176a42fb43f1e36a3d8ac0c8a8fd07db4b878e --- servo/components/style/cache.rs | 13 +- servo/components/style/context.rs | 8 +- servo/components/style/sharing/mod.rs | 231 +++++++++++++------------- servo/components/style/traversal.rs | 10 +- servo/tests/unit/stylo/size_of.rs | 3 + 5 files changed, 133 insertions(+), 132 deletions(-) diff --git a/servo/components/style/cache.rs b/servo/components/style/cache.rs index 8e4c7371938d..843f614f0873 100644 --- a/servo/components/style/cache.rs +++ b/servo/components/style/cache.rs @@ -39,13 +39,22 @@ impl LRUCache { #[inline] /// Touch a given entry, putting it first in the list. pub fn touch(&mut self, pos: usize) { - let last_index = self.entries.len() - 1; - if pos != last_index { + if pos != 0 { let entry = self.entries.remove(pos).unwrap(); self.entries.push_front(entry); } } + /// Returns the front entry in the list (most recently used). + pub fn front(&self) -> Option<&K::Item> { + self.entries.get(0) + } + + /// Returns a mutable reference to the front entry in the list (most recently used). + pub fn front_mut(&mut self) -> Option<&mut K::Item> { + self.entries.get_mut(0) + } + /// Iterate over the contents of this cache, from more to less recently /// used. pub fn iter(&self) -> arraydeque::Iter { diff --git a/servo/components/style/context.rs b/servo/components/style/context.rs index d7db7a5ab61c..de8c95bb430c 100644 --- a/servo/components/style/context.rs +++ b/servo/components/style/context.rs @@ -26,7 +26,7 @@ use selectors::matching::ElementSelectorFlags; use servo_arc::Arc; #[cfg(feature = "servo")] use servo_atoms::Atom; use shared_lock::StylesheetGuards; -use sharing::StyleSharingCandidateCache; +use sharing::StyleSharingCache; use std::fmt; use std::ops; #[cfg(feature = "servo")] use std::sync::Mutex; @@ -679,7 +679,7 @@ impl StackLimitChecker { /// thread in order to be able to mutate it without locking. pub struct ThreadLocalStyleContext { /// A cache to share style among siblings. - pub style_sharing_candidate_cache: StyleSharingCandidateCache, + pub sharing_cache: StyleSharingCache, /// The bloom filter used to fast-reject selector-matching. pub bloom_filter: StyleBloom, /// A channel on which new animations that have been triggered by style @@ -716,7 +716,7 @@ impl ThreadLocalStyleContext { #[cfg(feature = "servo")] pub fn new(shared: &SharedStyleContext) -> Self { ThreadLocalStyleContext { - style_sharing_candidate_cache: StyleSharingCandidateCache::new(), + sharing_cache: StyleSharingCache::new(), bloom_filter: StyleBloom::new(), new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(), tasks: SequentialTaskList(Vec::new()), @@ -733,7 +733,7 @@ impl ThreadLocalStyleContext { /// Creates a new `ThreadLocalStyleContext` from a shared one. pub fn new(shared: &SharedStyleContext) -> Self { ThreadLocalStyleContext { - style_sharing_candidate_cache: StyleSharingCandidateCache::new(), + sharing_cache: StyleSharingCache::new(), bloom_filter: StyleBloom::new(), tasks: SequentialTaskList(Vec::new()), selector_flags: SelectorFlagsMap::new(), diff --git a/servo/components/style/sharing/mod.rs b/servo/components/style/sharing/mod.rs index bf81915ce477..e42a4a8b19ee 100644 --- a/servo/components/style/sharing/mod.rs +++ b/servo/components/style/sharing/mod.rs @@ -68,7 +68,7 @@ use Atom; use applicable_declarations::ApplicableDeclarationBlock; use atomic_refcell::{AtomicRefCell, AtomicRefMut}; use bloom::StyleBloom; -use cache::{LRUCache, LRUCacheMutIterator}; +use cache::LRUCache; use context::{SelectorFlagsMap, SharedStyleContext, StyleContext}; use data::ElementStyles; use dom::{TElement, SendElement}; @@ -342,8 +342,8 @@ impl StyleSharingTarget { pub fn share_style_if_possible( &mut self, context: &mut StyleContext, - ) -> StyleSharingResult { - let cache = &mut context.thread_local.style_sharing_candidate_cache; + ) -> Option { + let cache = &mut context.thread_local.sharing_cache; let shared_context = &context.shared; let selector_flags_map = &mut context.thread_local.selector_flags; let bloom_filter = &context.thread_local.bloom_filter; @@ -351,7 +351,7 @@ impl StyleSharingTarget { if cache.dom_depth != bloom_filter.matching_depth() { debug!("Can't share style, because DOM depth changed from {:?} to {:?}, element: {:?}", cache.dom_depth, bloom_filter.matching_depth(), self.element); - return StyleSharingResult::CannotShare; + return None; } debug_assert_eq!(bloom_filter.current_parent(), self.element.traversal_parent()); @@ -370,45 +370,58 @@ impl StyleSharingTarget { } } -/// A cache miss result. -#[derive(Clone, Debug)] -pub enum CacheMiss { - /// The parents don't match. - Parent, - /// One element was NAC, while the other wasn't. - NativeAnonymousContent, - /// The local name of the element and the candidate don't match. - LocalName, - /// The namespace of the element and the candidate don't match. - Namespace, - /// One of the element or the candidate was a link, but the other one - /// wasn't. - Link, - /// The element and the candidate match different kind of rules. This can - /// only happen in Gecko. - UserAndAuthorRules, - /// The element and the candidate are in a different state. - State, - /// The element had an id attribute, which qualifies for a unique style. - IdAttr, - /// The element had a style attribute, which qualifies for a unique style. - StyleAttr, - /// The element and the candidate class names didn't match. - Class, - /// The presentation hints didn't match. - PresHints, - /// The element and the candidate didn't match the same set of revalidation - /// selectors. - Revalidation, +struct SharingCacheBase { + entries: LRUCache<[Candidate; SHARING_CACHE_BACKING_STORE_SIZE]>, } -/// The results of attempting to share a style. -pub enum StyleSharingResult { - /// We didn't find anybody to share the style with. - CannotShare, - /// The node's style can be shared. The integer specifies the index in the - /// LRU cache that was hit and the damage that was done. - StyleWasShared(usize, ElementStyles), +impl Default for SharingCacheBase { + fn default() -> Self { + Self { + entries: LRUCache::new(), + } + } +} + +impl SharingCacheBase { + fn clear(&mut self) { + self.entries.evict_all(); + } + + fn is_empty(&self) -> bool { + self.entries.num_entries() == 0 + } +} + +impl SharingCache { + fn insert(&mut self, el: E, validation_data_holder: &mut StyleSharingTarget) { + self.entries.insert(StyleSharingCandidate { + element: el, + validation_data: validation_data_holder.take_validation_data(), + }); + } + + fn lookup(&mut self, mut is_match: F) -> Option + where + F: FnMut(&mut StyleSharingCandidate) -> bool + { + let mut index = None; + for (i, candidate) in self.entries.iter_mut().enumerate() { + if is_match(candidate) { + index = Some(i); + break; + } + }; + + match index { + None => None, + Some(i) => { + self.entries.touch(i); + let front = self.entries.front_mut().unwrap(); + debug_assert!(is_match(front)); + Some(front.element.borrow_data().unwrap().styles.clone()) + } + } + } } /// Style sharing caches are are large allocations, so we store them in thread-local @@ -423,20 +436,19 @@ pub enum StyleSharingResult { /// /// [1] https://github.com/rust-lang/rust/issues/42763 /// [2] https://github.com/rust-lang/rust/issues/13707 -type SharingCacheBase = LRUCache<[Candidate; SHARING_CACHE_BACKING_STORE_SIZE]>; type SharingCache = SharingCacheBase>; type TypelessSharingCache = SharingCacheBase; type StoredSharingCache = Arc>; thread_local!(static SHARING_CACHE_KEY: StoredSharingCache = - Arc::new(AtomicRefCell::new(LRUCache::new()))); + Arc::new(AtomicRefCell::new(TypelessSharingCache::default()))); /// An LRU cache of the last few nodes seen, so that we can aggressively try to /// reuse their styles. /// /// Note that this cache is flushed every time we steal work from the queue, so /// storing nodes here temporarily is safe. -pub struct StyleSharingCandidateCache { +pub struct StyleSharingCache { /// The LRU cache, with the type cast away to allow persisting the allocation. cache_typeless: OwningHandle>, /// Bind this structure to the lifetime of E, since that's what we effectively store. @@ -447,13 +459,14 @@ pub struct StyleSharingCandidateCache { dom_depth: usize, } -impl Drop for StyleSharingCandidateCache { +impl Drop for StyleSharingCache { fn drop(&mut self) { self.clear(); } } -impl StyleSharingCandidateCache { +impl StyleSharingCache { + #[allow(dead_code)] fn cache(&self) -> &SharingCache { let base: &TypelessSharingCache = &*self.cache_typeless; unsafe { mem::transmute(base) } @@ -470,31 +483,25 @@ impl StyleSharingCandidateCache { assert_eq!(mem::align_of::>(), mem::align_of::()); let cache_arc = SHARING_CACHE_KEY.with(|c| c.clone()); let cache = OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - debug_assert_eq!(cache.num_entries(), 0); + debug_assert!(cache.is_empty()); - StyleSharingCandidateCache { + StyleSharingCache { cache_typeless: cache, marker: PhantomData, dom_depth: 0, } } - /// Returns the number of entries in the cache. - pub fn num_entries(&self) -> usize { - self.cache().num_entries() - } - - fn iter_mut(&mut self) -> LRUCacheMutIterator> { - self.cache_mut().iter_mut() - } - /// Tries to insert an element in the style sharing cache. /// /// Fails if we know it should never be in the cache. + /// + /// NB: We pass a source for the validation data, rather than the data itself, + /// to avoid memmoving at each function call. See rust issue #42763. pub fn insert_if_possible(&mut self, element: &E, style: &ComputedValues, - validation_data: ValidationData, + validation_data_holder: &mut StyleSharingTarget, dom_depth: usize) { let parent = match element.traversal_parent() { Some(element) => element, @@ -547,20 +554,12 @@ impl StyleSharingCandidateCache { self.clear(); self.dom_depth = dom_depth; } - self.cache_mut().insert(StyleSharingCandidate { - element: *element, - validation_data: validation_data, - }); - } - - /// Touch a given index in the style sharing candidate cache. - pub fn touch(&mut self, index: usize) { - self.cache_mut().touch(index); + self.cache_mut().insert(*element, validation_data_holder); } /// Clear the style sharing candidate cache. pub fn clear(&mut self) { - self.cache_mut().evict_all() + self.cache_mut().clear(); } /// Attempts to share a style with another node. @@ -570,48 +569,33 @@ impl StyleSharingCandidateCache { selector_flags_map: &mut SelectorFlagsMap, bloom_filter: &StyleBloom, target: &mut StyleSharingTarget, - ) -> StyleSharingResult { + ) -> Option { if shared_context.options.disable_style_sharing_cache { debug!("{:?} Cannot share style: style sharing cache disabled", target.element); - return StyleSharingResult::CannotShare + return None; } if target.traversal_parent().is_none() { debug!("{:?} Cannot share style: element has no parent", target.element); - return StyleSharingResult::CannotShare + return None; } if target.is_native_anonymous() { debug!("{:?} Cannot share style: NAC", target.element); - return StyleSharingResult::CannotShare; + return None; } - for (i, candidate) in self.iter_mut().enumerate() { - let sharing_result = - Self::test_candidate( - target, - candidate, - &shared_context, - bloom_filter, - selector_flags_map - ); - - match sharing_result { - Ok(shared_styles) => { - return StyleSharingResult::StyleWasShared(i, shared_styles) - } - Err(miss) => { - debug!("Cache miss: {:?}", miss); - } - } - } - - debug!("{:?} Cannot share style: {} cache entries", target.element, - self.cache().num_entries()); - - StyleSharingResult::CannotShare + self.cache_mut().lookup(|candidate| { + Self::test_candidate( + target, + candidate, + &shared_context, + bloom_filter, + selector_flags_map + ) + }) } fn test_candidate( @@ -620,13 +604,7 @@ impl StyleSharingCandidateCache { shared: &SharedStyleContext, bloom: &StyleBloom, selector_flags_map: &mut SelectorFlagsMap - ) -> Result { - macro_rules! miss { - ($miss: ident) => { - return Err(CacheMiss::$miss); - } - } - + ) -> bool { // Check that we have the same parent, or at least that the parents // share styles and permit sharing across their children. The latter // check allows us to share style between cousins if the parents @@ -635,37 +613,44 @@ impl StyleSharingCandidateCache { let candidate_parent = candidate.element.traversal_parent(); if parent != candidate_parent && !checks::can_share_style_across_parents(parent, candidate_parent) { - miss!(Parent) + trace!("Miss: Parent"); + return false; } if target.is_native_anonymous() { debug_assert!(!candidate.element.is_native_anonymous(), "Why inserting NAC into the cache?"); - miss!(NativeAnonymousContent) + trace!("Miss: Native Anonymous Content"); + return false; } if *target.get_local_name() != *candidate.element.get_local_name() { - miss!(LocalName) + trace!("Miss: Local Name"); + return false; } if *target.get_namespace() != *candidate.element.get_namespace() { - miss!(Namespace) + trace!("Miss: Namespace"); + return false; } if target.is_link() != candidate.element.is_link() { - miss!(Link) + trace!("Miss: Link"); + return false; } if target.matches_user_and_author_rules() != candidate.element.matches_user_and_author_rules() { - miss!(UserAndAuthorRules) + trace!("Miss: User and Author Rules"); + return false; } // We do not ignore visited state here, because Gecko // needs to store extra bits on visited style contexts, // so these contexts cannot be shared if target.element.get_state() != candidate.get_state() { - miss!(State) + trace!("Miss: User and Author State"); + return false; } let element_id = target.element.get_id(); @@ -674,32 +659,38 @@ impl StyleSharingCandidateCache { // It's possible that there are no styles for either id. if checks::may_have_rules_for_ids(shared, element_id.as_ref(), candidate_id.as_ref()) { - miss!(IdAttr) + trace!("Miss: ID Attr"); + return false; } } if !checks::have_same_style_attribute(target, candidate) { - miss!(StyleAttr) + trace!("Miss: Style Attr"); + return false; } if !checks::have_same_class(target, candidate) { - miss!(Class) + trace!("Miss: Class"); + return false; } if !checks::have_same_presentational_hints(target, candidate) { - miss!(PresHints) + trace!("Miss: Pres Hints"); + return false; } if !checks::revalidate(target, candidate, shared, bloom, selector_flags_map) { - miss!(Revalidation) + trace!("Miss: Revalidation"); + return false; } - let data = candidate.element.borrow_data().unwrap(); - debug_assert!(target.has_current_styles_for_traversal(&data, shared.traversal_flags)); + debug_assert!(target.has_current_styles_for_traversal( + &candidate.element.borrow_data().unwrap(), + shared.traversal_flags) + ); + debug!("Sharing allowed between {:?} and {:?}", target.element, candidate.element); - debug!("Sharing style between {:?} and {:?}", - target.element, candidate.element); - Ok(data.styles.clone()) + true } } diff --git a/servo/components/style/traversal.rs b/servo/components/style/traversal.rs index 4c066f876844..efe7d8f68b36 100644 --- a/servo/components/style/traversal.rs +++ b/servo/components/style/traversal.rs @@ -624,7 +624,6 @@ where E: TElement, { use data::RestyleKind::*; - use sharing::StyleSharingResult::*; context.thread_local.statistics.elements_styled += 1; let kind = data.restyle_kind(context.shared); @@ -656,12 +655,11 @@ where // Now that our bloom filter is set up, try the style sharing // cache. match target.share_style_if_possible(context) { - StyleWasShared(index, styles) => { + Some(styles) => { context.thread_local.statistics.styles_shared += 1; - context.thread_local.style_sharing_candidate_cache.touch(index); styles } - CannotShare => { + None => { context.thread_local.statistics.elements_matched += 1; // Perform the matching and cascading. let new_styles = { @@ -677,11 +675,11 @@ where }; context.thread_local - .style_sharing_candidate_cache + .sharing_cache .insert_if_possible( &element, new_styles.primary(), - target.take_validation_data(), + &mut target, context.thread_local.bloom_filter.matching_depth(), ); diff --git a/servo/tests/unit/stylo/size_of.rs b/servo/tests/unit/stylo/size_of.rs index 8ec8e8c0fd1e..df415cfca11e 100644 --- a/servo/tests/unit/stylo/size_of.rs +++ b/servo/tests/unit/stylo/size_of.rs @@ -31,6 +31,9 @@ fn size_of_selectors_dummy_types() { // selectors (with the inline hashes) with as few cache misses as possible. size_of_test!(test_size_of_rule, style::stylist::Rule, 32); +// Large pages generate tens of thousands of ComputedValues. +size_of_test!(test_size_of_cv, ComputedValues, 272); + size_of_test!(test_size_of_option_arc_cv, Option>, 8); size_of_test!(test_size_of_option_rule_node, Option, 8); From 86c4053dd277d1b9e702234d46dc56f5455a4f82 Mon Sep 17 00:00:00 2001 From: Luca Greco Date: Sat, 9 Sep 2017 18:23:52 +0200 Subject: [PATCH 17/17] Bug 1398727 - Fix missing tab title on devtools.panels.elements.createSidebarPane tabs. r=gl MozReview-Commit-ID: G5F9uEC6izs --HG-- extra : rebase_source : 1e34ddf1d2ee4fe5db7886d824c4279ffcbc7674 --- .../browser_ext_devtools_panels_elements_sidebar.js | 11 +++++++++++ .../client/inspector/extensions/extension-sidebar.js | 1 + .../test/browser_inspector_extension_sidebar.js | 2 ++ 3 files changed, 14 insertions(+) diff --git a/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js b/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js index 9878a866731f..4652a1adee7f 100644 --- a/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js +++ b/browser/components/extensions/test/browser/browser_ext_devtools_panels_elements_sidebar.js @@ -7,6 +7,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", XPCOMUtils.defineLazyModuleGetter(this, "devtools", "resource://devtools/shared/Loader.jsm"); +function isActiveSidebarTabTitle(inspector, expectedTabTitle, message) { + const actualTabTitle = inspector.panelDoc.querySelector(".tabs-menu-item.is-active").innerText; + is(actualTabTitle, expectedTabTitle, message); +} + add_task(async function test_devtools_panels_elements_sidebar() { let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/"); @@ -70,6 +75,9 @@ add_task(async function test_devtools_panels_elements_sidebar() { is(shownSidebarInstance, "sidebar1", "Got the shown event on the first extension sidebar"); + isActiveSidebarTabTitle(inspector, "Test Sidebar 1", + "Got the expected title on the active sidebar tab"); + const sidebarPanel1 = inspector.sidebar.getTabPanel(sidebarIds[0]); ok(sidebarPanel1, "Got a rendered sidebar panel for the first registered extension sidebar"); @@ -94,6 +102,9 @@ add_task(async function test_devtools_panels_elements_sidebar() { is(shownSidebarInstance2, "sidebar2", "Got the shown event on the second extension sidebar"); is(hiddenSidebarInstance1, "sidebar1", "Got the hidden event on the first extension sidebar"); + isActiveSidebarTabTitle(inspector, "Test Sidebar 2", + "Got the expected title on the active sidebar tab"); + const sidebarPanel2 = inspector.sidebar.getTabPanel(sidebarIds[1]); ok(sidebarPanel2, "Got a rendered sidebar panel for the second registered extension sidebar"); diff --git a/devtools/client/inspector/extensions/extension-sidebar.js b/devtools/client/inspector/extensions/extension-sidebar.js index 1b9c1b33088a..c2cd755be8d0 100644 --- a/devtools/client/inspector/extensions/extension-sidebar.js +++ b/devtools/client/inspector/extensions/extension-sidebar.js @@ -52,6 +52,7 @@ class ExtensionSidebar { this._provider = createElement(Provider, { store: this.store, key: this.id, + title: this.title, }, ExtensionSidebarComponent({ id: this.id, })); diff --git a/devtools/client/inspector/extensions/test/browser_inspector_extension_sidebar.js b/devtools/client/inspector/extensions/test/browser_inspector_extension_sidebar.js index 63c11046022c..d262c2a7fffa 100644 --- a/devtools/client/inspector/extensions/test/browser_inspector_extension_sidebar.js +++ b/devtools/client/inspector/extensions/test/browser_inspector_extension_sidebar.js @@ -22,6 +22,8 @@ add_task(async function () { is(sidebar.title, sidebarTitle, "Got the expected title in the extension sidebar instance"); + is(sidebar.provider.props.title, sidebarTitle, + "Got the expeted title in the provider props"); let inspectorStoreState = inspector.store.getState();