TEST_F(BaseAudioContextTest, AutoplayMetrics_CreateNoGesture) { HistogramTester histogramTester; createChildFrame(); childDocument().settings()->setMediaPlaybackRequiresUserGesture(true); BaseAudioContext* audioContext = BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION); recordAutoplayStatus(audioContext); histogramTester.expectBucketCount(kCrossOriginMetric, AutoplayStatus::AutoplayStatusFailed, 1); histogramTester.expectTotalCount(kCrossOriginMetric, 1); }
TEST_F(VisualRectMappingTest, LayoutViewSubpixelRounding) { document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); setBodyInnerHTML( "<style>body { margin: 0; }</style>" "<div id=frameContainer style='position: relative; left: 0.5px'>" " <iframe style='position: relative; left: 0.5px' " "src='http://test.com' width='200' height='200' frameBorder='0'></iframe>" "</div>"); setChildFrameHTML( "<style>body { margin: 0; }</style><div id='target' style='position: " "relative; width: 100px; height: 100px; left: 0.5px'>"); document().view()->updateAllLifecyclePhases(); LayoutBlock* frameContainer = toLayoutBlock(getLayoutObjectByElementId("frameContainer")); LayoutObject* target = childDocument().getElementById("target")->layoutObject(); LayoutRect rect(0, 0, 100, 100); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(frameContainer, rect)); // When passing from the iframe to the parent frame, the rect of (0.5, 0, 100, // 100) is expanded to (0, 0, 100, 100), and then offset by the 0.5 offset of // frameContainer. EXPECT_EQ(LayoutRect(LayoutPoint(DoublePoint(0.5, 0)), LayoutSize(101, 100)), rect); }
TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartGesture) { HistogramTester histogramTester; createChildFrame(); childDocument().settings()->setMediaPlaybackRequiresUserGesture(true); BaseAudioContext* audioContext = BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION); UserGestureIndicator userGestureScope(DocumentUserGestureToken::create( &childDocument(), UserGestureToken::NewGesture)); audioContext->maybeRecordStartAttempt(); recordAutoplayStatus(audioContext); histogramTester.expectBucketCount( kCrossOriginMetric, AutoplayStatus::AutoplayStatusFailedWithStart, 1); histogramTester.expectTotalCount(kCrossOriginMetric, 1); }
TEST_F(BaseAudioContextTest, AutoplayMetrics_CallResumeNoGesture) { HistogramTester histogramTester; createChildFrame(); childDocument().settings()->setMediaPlaybackRequiresUserGesture(true); ScriptState::Scope scope(getScriptStateFrom(childDocument())); BaseAudioContext* audioContext = BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION); audioContext->resumeContext(getScriptStateFrom(childDocument())); rejectPendingResolvers(audioContext); recordAutoplayStatus(audioContext); histogramTester.expectBucketCount(kCrossOriginMetric, AutoplayStatus::AutoplayStatusFailed, 1); histogramTester.expectTotalCount(kCrossOriginMetric, 1); }
TEST_F(BaseAudioContextTest, AutoplayMetrics_NodeStartGestureThenSucces) { HistogramTester histogramTester; createChildFrame(); childDocument().settings()->setMediaPlaybackRequiresUserGesture(true); ScriptState::Scope scope(getScriptStateFrom(childDocument())); BaseAudioContext* audioContext = BaseAudioContext::create(childDocument(), ASSERT_NO_EXCEPTION); UserGestureIndicator userGestureScope(DocumentUserGestureToken::create( &childDocument(), UserGestureToken::NewGesture)); audioContext->maybeRecordStartAttempt(); audioContext->resumeContext(getScriptStateFrom(childDocument())); rejectPendingResolvers(audioContext); recordAutoplayStatus(audioContext); histogramTester.expectBucketCount(kCrossOriginMetric, AutoplayStatus::AutoplayStatusSucceeded, 1); histogramTester.expectTotalCount(kCrossOriginMetric, 1); }
TEST_F(VisualRectMappingTest, LayoutView) { document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); setBodyInnerHTML( "<style>body { margin: 0; }</style>" "<div id=frameContainer>" " <iframe src='http://test.com' width='50' height='50' " "frameBorder='0'></iframe>" "</div>"); setChildFrameHTML( "<style>body { margin: 0; }</style><span><img style='width: 20px; " "height: 100px'></span>text text text"); document().view()->updateAllLifecyclePhases(); LayoutBlock* frameContainer = toLayoutBlock(getLayoutObjectByElementId("frameContainer")); LayoutBlock* frameBody = toLayoutBlock(childDocument().body()->layoutObject()); LayoutText* frameText = toLayoutText(frameBody->lastChild()); // This case involves clipping: frame height is 50, y-coordinate of result // rect is 13, so height should be clipped to (50 - 13) == 37. childDocument().view()->setScrollOffset(ScrollOffset(0, 47), ProgrammaticScroll); LayoutRect originalRect(4, 60, 20, 80); LayoutRect rect = originalRect; EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(frameContainer, rect)); EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); rect = originalRect; EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); checkPaintInvalidationStateRectMapping(rect, originalRect, *frameText, layoutView(), layoutView()); rect = LayoutRect(4, 60, 0, 80); EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(frameContainer, rect, EdgeInclusive)); EXPECT_EQ(rect, LayoutRect(4, 13, 0, 37)); }
TEST_P(BoxPaintInvalidatorTest, NonCompositedLayoutViewResize) { setBodyInnerHTML( "<style>" " body { margin: 0 }" " iframe { display: block; width: 100px; height: 100px; border: none; }" "</style>" "<iframe id='iframe'></iframe>"); setChildFrameHTML( "<style>" " ::-webkit-scrollbar { display: none }" " body { margin: 0; background: green; height: 0 }" "</style>" "<div id='content' style='width: 200px; height: 200px'></div>"); document().view()->updateAllLifecyclePhases(); Element* iframe = document().getElementById("iframe"); Element* content = childDocument().getElementById("content"); EXPECT_EQ(layoutView(), content->layoutObject()->containerForPaintInvalidation()); // Resize the content. document().view()->setTracksPaintInvalidations(true); content->setAttribute(HTMLNames::styleAttr, "height: 500px"); document().view()->updateAllLifecyclePhases(); // No invalidation because the changed part of layout overflow is clipped. EXPECT_FALSE(getRasterInvalidationTracking()); document().view()->setTracksPaintInvalidations(false); // Resize the iframe. document().view()->setTracksPaintInvalidations(true); iframe->setAttribute(HTMLNames::styleAttr, "height: 200px"); document().view()->updateAllLifecyclePhases(); const auto& rasterInvalidations = getRasterInvalidationTracking()->trackedRasterInvalidations; ASSERT_EQ(2u, rasterInvalidations.size()); EXPECT_EQ(IntRect(0, 100, 100, 100), rasterInvalidations[0].rect); EXPECT_EQ(static_cast<const DisplayItemClient*>(iframe->layoutObject()), rasterInvalidations[0].client); EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); EXPECT_EQ( static_cast<const DisplayItemClient*>(content->layoutObject()->view()), rasterInvalidations[1].client); if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { // TODO(skobes): Treat LayoutView in the same way as normal objects having // background-attachment: local. crbug.com/568847. EXPECT_EQ(IntRect(0, 0, 100, 200), rasterInvalidations[1].rect); EXPECT_EQ(PaintInvalidationFull, rasterInvalidations[1].reason); } else { EXPECT_EQ(IntRect(0, 100, 100, 100), rasterInvalidations[1].rect); EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[1].reason); } document().view()->setTracksPaintInvalidations(false); }
void createChildFrame() { m_childFrame = LocalFrame::create( MockCrossOriginFrameLoaderClient::create(document().frame()), document().frame()->host(), m_dummyFrameOwner.get()); m_childFrame->setView(FrameView::create(*m_childFrame, IntSize(500, 500))); m_childFrame->init(); m_childDocumentLoader = DocumentLoader::create( m_childFrame.get(), ResourceRequest("https://www.example.com"), SubstituteData(), ClientRedirectPolicy::NotClientRedirect); childDocument().updateSecurityOrigin( SecurityOrigin::create("https", "cross-origin.com", 80)); }
TEST_F(VisualRectMappingTest, LayoutViewDisplayNone) { document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); setBodyInnerHTML( "<style>body { margin: 0; }</style>" "<div id=frameContainer>" " <iframe id='frame' src='http://test.com' width='50' height='50' " "frameBorder='0'></iframe>" "</div>"); setChildFrameHTML( "<style>body { margin: 0; }</style><div " "style='width:100px;height:100px;'></div>"); document().view()->updateAllLifecyclePhases(); LayoutBlock* frameContainer = toLayoutBlock(getLayoutObjectByElementId("frameContainer")); LayoutBlock* frameBody = toLayoutBlock(childDocument().body()->layoutObject()); LayoutBlock* frameDiv = toLayoutBlock(frameBody->lastChild()); // This part is copied from the LayoutView test, just to ensure that the // mapped rect is valid before display:none is set on the iframe. childDocument().view()->setScrollOffset(ScrollOffset(0, 47), ProgrammaticScroll); LayoutRect originalRect(4, 60, 20, 80); LayoutRect rect = originalRect; EXPECT_TRUE(frameDiv->mapToVisualRectInAncestorSpace(frameContainer, rect)); EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); Element* frameElement = document().getElementById("frame"); frameElement->setInlineStyleProperty(CSSPropertyDisplay, "none"); document().view()->updateAllLifecyclePhases(); rect = originalRect; EXPECT_FALSE(frameDiv->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(rect, LayoutRect()); }