Commit ecb779cb authored by Yuzu Saijo's avatar Yuzu Saijo Committed by Commit Bot

[bfcache] Fire pageshow/pagehide for non-main frames as well

This CL makes BackForwardCache navigation fire pageshow/pagehide events
to not only main frames, but also subframes.

Bug: 1021536
Change-Id: If021b240d288deff4acf20c4cbf333a7b79128f7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1900799
Commit-Queue: Yuzu Saijo <yuzus@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712981}
parent 7f3bd0e6
...@@ -187,6 +187,33 @@ class BackForwardCacheBrowserTest : public ContentBrowserTest { ...@@ -187,6 +187,33 @@ class BackForwardCacheBrowserTest : public ContentBrowserTest {
EXPECT_FALSE(ExecJs(rfh, "console.log('hi');")); EXPECT_FALSE(ExecJs(rfh, "console.log('hi');"));
} }
void StartRecordingEvents(RenderFrameHostImpl* rfh) {
EXPECT_TRUE(ExecJs(rfh, R"(
window.testObservedEvents = [];
let event_list = [
'visibilitychange',
'pagehide',
'pageshow',
'freeze',
'resume',
];
for (event_name of event_list) {
let result = event_name;
window.addEventListener(event_name, event => {
if (event.persisted)
result +='.persisted';
window.testObservedEvents.push(result);
});
document.addEventListener(event_name,
() => window.testObservedEvents.push(result));
}
)"));
}
void MatchEventList(RenderFrameHostImpl* rfh, base::ListValue list) {
EXPECT_EQ(list, EvalJs(rfh, "window.testObservedEvents"));
}
private: private:
void AddSampleToBuckets(std::vector<base::Bucket>* buckets, void AddSampleToBuckets(std::vector<base::Bucket>* buckets,
base::HistogramBase::Sample sample) { base::HistogramBase::Sample sample) {
...@@ -1865,26 +1892,7 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, Events) { ...@@ -1865,26 +1892,7 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, Events) {
EXPECT_TRUE(NavigateToURL(shell(), url_a)); EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImpl* rfh_a = current_frame_host(); RenderFrameHostImpl* rfh_a = current_frame_host();
RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a); RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
EXPECT_TRUE(ExecJs(shell(), R"( StartRecordingEvents(rfh_a);
window.testObservedEvents = [];
let event_list = [
'visibilitychange',
'pagehide',
'pageshow',
'freeze',
'resume',
];
for (event_name of event_list) {
let result = event_name;
window.addEventListener(event_name, event => {
if (event.persisted)
result +='.persisted';
window.testObservedEvents.push(result);
});
document.addEventListener(event_name,
() => window.testObservedEvents.push(result));
}
)"));
// 2) Navigate to B. // 2) Navigate to B.
EXPECT_TRUE(NavigateToURL(shell(), url_b)); EXPECT_TRUE(NavigateToURL(shell(), url_b));
...@@ -1906,11 +1914,61 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, Events) { ...@@ -1906,11 +1914,61 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, Events) {
EXPECT_EQ(rfh_a, current_frame_host()); EXPECT_EQ(rfh_a, current_frame_host());
// visibilitychange events are added twice per each because it is fired for // visibilitychange events are added twice per each because it is fired for
// both window and document. // both window and document.
EXPECT_EQ( MatchEventList(rfh_a, ListValueOf("visibilitychange", "visibilitychange",
ListValueOf("visibilitychange", "visibilitychange", "pagehide.persisted", "pagehide.persisted", "freeze", "resume",
"freeze", "resume", "pageshow.persisted", "visibilitychange", "pageshow.persisted", "visibilitychange",
"visibilitychange"), "visibilitychange"));
EvalJs(shell(), "window.testObservedEvents")); }
// Tests the events are fired for subframes when going back from the cache.
// Test case: a(b) -> c -> a(b)
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, EventsForSubframes) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
GURL url_c(embedded_test_server()->GetURL("c.com", "/title1.html"));
// 1) Navigate to A(B).
EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImpl* rfh_a = current_frame_host();
RenderFrameHostImpl* rfh_b = rfh_a->child_at(0)->current_frame_host();
RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
RenderFrameDeletedObserver delete_observer_rfh_b(rfh_b);
StartRecordingEvents(rfh_a);
StartRecordingEvents(rfh_b);
// 2) Navigate to C.
EXPECT_TRUE(NavigateToURL(shell(), url_c));
RenderFrameHostImpl* rfh_c = current_frame_host();
RenderFrameDeletedObserver delete_observer_rfh_c(rfh_c);
EXPECT_FALSE(delete_observer_rfh_a.deleted());
EXPECT_FALSE(delete_observer_rfh_b.deleted());
EXPECT_TRUE(rfh_a->is_in_back_forward_cache());
EXPECT_TRUE(rfh_b->is_in_back_forward_cache());
EXPECT_FALSE(rfh_c->is_in_back_forward_cache());
// TODO(yuzus): Post message to the frozen page, and make sure that the
// messages arrive after the page visibility events, not before them.
// 3) Go back to A(B). Confirm that expected events are fired on the subframe.
web_contents()->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_FALSE(delete_observer_rfh_a.deleted());
EXPECT_FALSE(delete_observer_rfh_b.deleted());
EXPECT_FALSE(delete_observer_rfh_c.deleted());
EXPECT_EQ(rfh_a, current_frame_host());
EXPECT_FALSE(rfh_a->is_in_back_forward_cache());
EXPECT_FALSE(rfh_b->is_in_back_forward_cache());
EXPECT_TRUE(rfh_c->is_in_back_forward_cache());
// visibilitychange events are added twice per each because it is fired for
// both window and document.
MatchEventList(rfh_a, ListValueOf("visibilitychange", "visibilitychange",
"pagehide.persisted", "freeze", "resume",
"pageshow.persisted", "visibilitychange",
"visibilitychange"));
MatchEventList(rfh_b, ListValueOf("visibilitychange", "visibilitychange",
"pagehide.persisted", "freeze", "resume",
"pageshow.persisted", "visibilitychange",
"visibilitychange"));
} }
// Tests the events are fired when going back from the cache. // Tests the events are fired when going back from the cache.
...@@ -1926,26 +1984,7 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, ...@@ -1926,26 +1984,7 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_a)); EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImpl* rfh_a = current_frame_host(); RenderFrameHostImpl* rfh_a = current_frame_host();
RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a); RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
EXPECT_TRUE(ExecJs(shell(), R"( StartRecordingEvents(rfh_a);
window.testObservedEvents = [];
let event_list = [
'visibilitychange',
'pagehide',
'pageshow',
'freeze',
'resume',
];
for (event_name of event_list) {
let result = event_name;
window.addEventListener(event_name, event => {
if (event.persisted)
result +='.persisted';
window.testObservedEvents.push(result);
});
document.addEventListener(event_name,
() => window.testObservedEvents.push(result));
}
)"));
// 2) Navigate to B. // 2) Navigate to B.
EXPECT_TRUE(ExecJs(shell(), JsReplace("location = $1;", url_b.spec()))); EXPECT_TRUE(ExecJs(shell(), JsReplace("location = $1;", url_b.spec())));
...@@ -1968,11 +2007,10 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, ...@@ -1968,11 +2007,10 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
EXPECT_EQ(rfh_a, current_frame_host()); EXPECT_EQ(rfh_a, current_frame_host());
// visibilitychange events are added twice per each because it is fired for // visibilitychange events are added twice per each because it is fired for
// both window and document. // both window and document.
EXPECT_EQ( MatchEventList(rfh_a, ListValueOf("visibilitychange", "visibilitychange",
ListValueOf("visibilitychange", "visibilitychange", "pagehide.persisted", "pagehide.persisted", "freeze", "resume",
"freeze", "resume", "pageshow.persisted", "visibilitychange", "pageshow.persisted", "visibilitychange",
"visibilitychange"), "visibilitychange"));
EvalJs(shell(), "window.testObservedEvents"));
} }
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
......
...@@ -3424,10 +3424,16 @@ void WebViewImpl::PutPageIntoBackForwardCache() { ...@@ -3424,10 +3424,16 @@ void WebViewImpl::PutPageIntoBackForwardCache() {
SetIsHidden(/*is_hidden=*/true, /*is_initial_state=*/false); SetIsHidden(/*is_hidden=*/true, /*is_initial_state=*/false);
Page* page = AsView().page; Page* page = AsView().page;
if (page && page->MainFrame() && page->MainFrame()->DomWindow() && if (page) {
page->MainFrame()->DomWindow()->IsLocalDOMWindow()) for (Frame* frame = page->MainFrame(); frame;
page->MainFrame()->DomWindow()->ToLocalDOMWindow()->DispatchPagehideEvent( frame = frame->Tree().TraverseNext()) {
PageTransitionEventPersistence::kPageTransitionEventPersisted); if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
frame->DomWindow()->ToLocalDOMWindow()->DispatchPagehideEvent(
PageTransitionEventPersistence::kPageTransitionEventPersisted);
}
}
}
// Freeze the page. // Freeze the page.
Scheduler()->SetPageFrozen(/*frozen =*/true); Scheduler()->SetPageFrozen(/*frozen =*/true);
// Hook eviction. // Hook eviction.
...@@ -3457,10 +3463,15 @@ void WebViewImpl::RestorePageFromBackForwardCache() { ...@@ -3457,10 +3463,15 @@ void WebViewImpl::RestorePageFromBackForwardCache() {
// Resume the page. // Resume the page.
Scheduler()->SetPageFrozen(/*frozen =*/false); Scheduler()->SetPageFrozen(/*frozen =*/false);
if (page && page->MainFrame() && page->MainFrame()->DomWindow() && if (page) {
page->MainFrame()->DomWindow()->IsLocalDOMWindow()) for (Frame* frame = page->MainFrame(); frame;
page->MainFrame()->DomWindow()->ToLocalDOMWindow()->DispatchPageshowEvent( frame = frame->Tree().TraverseNext()) {
PageTransitionEventPersistence::kPageTransitionEventPersisted); if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
frame->DomWindow()->ToLocalDOMWindow()->DispatchPageshowEvent(
PageTransitionEventPersistence::kPageTransitionEventPersisted);
}
}
}
SetIsHidden(/*is_hidden=*/false, /*is_initial_state=*/false); SetIsHidden(/*is_hidden=*/false, /*is_initial_state=*/false);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment