From 1aa71351fabef6ca946cac5fe70bb678feb73be3 Mon Sep 17 00:00:00 2001 From: RedYetiDev <38299977+RedYetiDev@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:56:18 -0400 Subject: [PATCH] test: update `performance-timeline` wpt PR-URL: https://github.com/nodejs/node/pull/55197 Reviewed-By: Filip Skokan --- test/fixtures/wpt/README.md | 2 +- ...k-forward-cache-restoration.tentative.html | 95 ++++++++++++ .../droppedentriescount.any.js | 81 ++++++++++ .../idlharness-shadowrealm.window.js | 2 + ...avigation-id-detached-frame.tentative.html | 30 ++++ ...avigation-id-element-timing.tentative.html | 14 ++ .../navigation-id-initial-load.tentative.html | 49 ++++++ ...-long-task-task-attribution.tentative.html | 14 ++ .../navigation-id-mark-measure.tentative.html | 14 ++ .../navigation-id-reset.tentative.html | 53 +++++++ ...vigation-id-resource-timing.tentative.html | 14 ++ .../navigation-id-worker-created-entries.html | 27 ++++ .../navigation-id.helper.js | 144 ++++++++++++++++++ .../abort-block-bfcache.window.js | 21 +++ ...tion-timing-attributes.tentative.window.js | 55 +++++++ ...g-bfcache-reasons-stay.tentative.window.js | 47 ++++++ ...igation-timing-bfcache.tentative.window.js | 28 ++++ ...g-cross-origin-bfcache.tentative.window.js | 60 ++++++++ ...avigation-timing-fetch.tentative.window.js | 40 +++++ ...mes-without-attributes.tentative.window.js | 103 +++++++++++++ ...tion-timing-lock.https.tentative.window.js | 32 ++++ ...ing-navigation-failure.tentative.window.js | 26 ++++ ...on-timing-not-bfcached.tentative.window.js | 36 +++++ ...ng-redirect-on-history.tentative.window.js | 53 +++++++ ...vigation-timing-reload.tentative.window.js | 50 ++++++ ...ng-same-origin-bfcache.tentative.window.js | 61 ++++++++ ...ng-same-origin-replace.tentative.window.js | 43 ++++++ .../not-restored-reasons/test-helper.js | 57 +++++++ .../resources/child-frame.html | 7 + .../performance-timeline/resources/empty.html | 0 .../resources/going-back.html | 9 ++ .../resources/include-frames-helper.js | 60 ++++++++ .../resources/include-frames-subframe.html | 43 ++++++ .../resources/json_resource.json | 4 + .../resources/make_long_task.js | 4 + .../navigation-id-detached-frame-page.html | 21 +++ .../resources/worker-navigation-id.js | 6 + ...upportedEntryTypes-cross-realm-access.html | 18 +++ .../tentative/detached-frame.html | 27 ++++ .../tentative/include-frames-originA-A-A.html | 93 +++++++++++ .../tentative/include-frames-originA-A.html | 76 +++++++++ .../tentative/include-frames-originA-AA.html | 51 +++++++ .../tentative/include-frames-originA-AB.html | 53 +++++++ .../tentative/include-frames-originA-B-A.html | 91 +++++++++++ .../tentative/include-frames-originA-B-B.html | 57 +++++++ .../tentative/include-frames-originA-B.html | 50 ++++++ .../tentative/performance-entry-source.html | 37 +++++ .../with-filter-options-originA.html | 26 ++++ .../timing-removed-iframe.html | 16 ++ test/fixtures/wpt/versions.json | 2 +- test/wpt/status/performance-timeline.json | 53 +++++++ 51 files changed, 2053 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/wpt/performance-timeline/back-forward-cache-restoration.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/droppedentriescount.any.js create mode 100644 test/fixtures/wpt/performance-timeline/idlharness-shadowrealm.window.js create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-detached-frame.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-element-timing.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-initial-load.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-long-task-task-attribution.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-mark-measure.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-reset.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-resource-timing.tentative.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id-worker-created-entries.html create mode 100644 test/fixtures/wpt/performance-timeline/navigation-id.helper.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-iframes-without-attributes.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js create mode 100644 test/fixtures/wpt/performance-timeline/not-restored-reasons/test-helper.js create mode 100644 test/fixtures/wpt/performance-timeline/resources/child-frame.html create mode 100644 test/fixtures/wpt/performance-timeline/resources/empty.html create mode 100644 test/fixtures/wpt/performance-timeline/resources/going-back.html create mode 100644 test/fixtures/wpt/performance-timeline/resources/include-frames-helper.js create mode 100644 test/fixtures/wpt/performance-timeline/resources/include-frames-subframe.html create mode 100644 test/fixtures/wpt/performance-timeline/resources/json_resource.json create mode 100644 test/fixtures/wpt/performance-timeline/resources/make_long_task.js create mode 100644 test/fixtures/wpt/performance-timeline/resources/navigation-id-detached-frame-page.html create mode 100644 test/fixtures/wpt/performance-timeline/resources/worker-navigation-id.js create mode 100644 test/fixtures/wpt/performance-timeline/supportedEntryTypes-cross-realm-access.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/detached-frame.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A-A.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AA.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AB.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-A.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-B.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/performance-entry-source.html create mode 100644 test/fixtures/wpt/performance-timeline/tentative/with-filter-options-originA.html create mode 100644 test/fixtures/wpt/performance-timeline/timing-removed-iframe.html diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 048ce7e49a6..3c7b7fb845d 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -24,7 +24,7 @@ Last update: - html/webappapis/structured-clone: https://github.com/web-platform-tests/wpt/tree/47d3fb280c/html/webappapis/structured-clone - html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/5873f2d8f1/html/webappapis/timers - interfaces: https://github.com/web-platform-tests/wpt/tree/e90ece61d6/interfaces -- performance-timeline: https://github.com/web-platform-tests/wpt/tree/17ebc3aea0/performance-timeline +- performance-timeline: https://github.com/web-platform-tests/wpt/tree/94caab7038/performance-timeline - resource-timing: https://github.com/web-platform-tests/wpt/tree/22d38586d0/resource-timing - resources: https://github.com/web-platform-tests/wpt/tree/1e140d63ec/resources - streams: https://github.com/web-platform-tests/wpt/tree/2bd26e124c/streams diff --git a/test/fixtures/wpt/performance-timeline/back-forward-cache-restoration.tentative.html b/test/fixtures/wpt/performance-timeline/back-forward-cache-restoration.tentative.html new file mode 100644 index 00000000000..c673e09cb46 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/back-forward-cache-restoration.tentative.html @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/droppedentriescount.any.js b/test/fixtures/wpt/performance-timeline/droppedentriescount.any.js new file mode 100644 index 00000000000..4de816bdc42 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/droppedentriescount.any.js @@ -0,0 +1,81 @@ +promise_test(t => { + // This setup is required for later tests as well. + // Await for a dropped entry. + return new Promise(res => { + // Set a buffer size of 0 so that new resource entries count as dropped. + performance.setResourceTimingBufferSize(0); + // Use an observer to make sure the promise is resolved only when the + // new entry has been created. + new PerformanceObserver(res).observe({type: 'resource'}); + fetch('resources/square.png?id=1'); + }).then(() => { + return new Promise(resolve => { + new PerformanceObserver(t.step_func((entries, obs, options) => { + assert_equals(options['droppedEntriesCount'], 0); + resolve(); + })).observe({type: 'mark'}); + performance.mark('test'); + })}); +}, 'Dropped entries count is 0 when there are no dropped entries of relevant type.'); + +promise_test(async t => { + return new Promise(resolve => { + new PerformanceObserver(t.step_func((entries, obs, options) => { + assert_equals(options['droppedEntriesCount'], 1); + resolve(); + })).observe({entryTypes: ['mark', 'resource']}); + performance.mark('meow'); + }); +}, 'Dropped entries correctly counted with multiple types.'); + +promise_test(t => { + return new Promise(resolve => { + new PerformanceObserver(t.step_func((entries, obs, options) => { + assert_equals(options['droppedEntriesCount'], 1, + 'There should have been some dropped resource timing entries at this point'); + resolve(); + })).observe({type: 'resource', buffered: true}); + }); +}, 'Dropped entries counted even if observer was not registered at the time.'); + +promise_test(t => { + return new Promise(resolve => { + let callback_ran = false; + new PerformanceObserver(t.step_func((entries, obs, options) => { + if (!callback_ran) { + assert_equals(options['droppedEntriesCount'], 2, + 'There should be two dropped entries right now.'); + fetch('resources/square.png?id=3'); + callback_ran = true; + } else { + assert_equals(options['droppedEntriesCount'], undefined, + 'droppedEntriesCount should be unset after the first callback!'); + resolve(); + } + })).observe({type: 'resource'}); + fetch('resources/square.png?id=2'); + }); +}, 'Dropped entries only surfaced on the first callback.'); + + +promise_test(t => { + return new Promise(resolve => { + let callback_ran = false; + let droppedEntriesCount = -1; + new PerformanceObserver(t.step_func((entries, obs, options) => { + if (!callback_ran) { + assert_greater_than(options['droppedEntriesCount'], 0, + 'There should be several dropped entries right now.'); + droppedEntriesCount = options['droppedEntriesCount']; + callback_ran = true; + obs.observe({type: 'mark'}); + performance.mark('woof'); + } else { + assert_equals(options['droppedEntriesCount'], droppedEntriesCount, + 'There should be droppedEntriesCount due to the new observe().'); + resolve(); + } + })).observe({type: 'resource'}); + fetch('resources/square.png?id=4'); + }); +}, 'Dropped entries surfaced after an observe() call!'); diff --git a/test/fixtures/wpt/performance-timeline/idlharness-shadowrealm.window.js b/test/fixtures/wpt/performance-timeline/idlharness-shadowrealm.window.js new file mode 100644 index 00000000000..6caaa330613 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/idlharness-shadowrealm.window.js @@ -0,0 +1,2 @@ +// META: script=/resources/idlharness-shadowrealm.js +idl_test_shadowrealm(["performance-timeline"], ["hr-time", "dom"]); diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-detached-frame.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-detached-frame.tentative.html new file mode 100644 index 00000000000..add11255af4 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-detached-frame.tentative.html @@ -0,0 +1,30 @@ + + + + + + The navigation_id Detached iframe Parent Page. + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-element-timing.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-element-timing.tentative.html new file mode 100644 index 00000000000..7ff415530bc --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-element-timing.tentative.html @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-initial-load.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-initial-load.tentative.html new file mode 100644 index 00000000000..b996f0f1179 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-initial-load.tentative.html @@ -0,0 +1,49 @@ + + + + + + + +

This text is to trigger a LCP entry emission.

+ + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-long-task-task-attribution.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-long-task-task-attribution.tentative.html new file mode 100644 index 00000000000..e1da9100aee --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-long-task-task-attribution.tentative.html @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-mark-measure.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-mark-measure.tentative.html new file mode 100644 index 00000000000..30613ebb980 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-mark-measure.tentative.html @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-reset.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-reset.tentative.html new file mode 100644 index 00000000000..f5a2428e5f5 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-reset.tentative.html @@ -0,0 +1,53 @@ + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-resource-timing.tentative.html b/test/fixtures/wpt/performance-timeline/navigation-id-resource-timing.tentative.html new file mode 100644 index 00000000000..6d0614a6e23 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-resource-timing.tentative.html @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id-worker-created-entries.html b/test/fixtures/wpt/performance-timeline/navigation-id-worker-created-entries.html new file mode 100644 index 00000000000..96fc57be1d4 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id-worker-created-entries.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/navigation-id.helper.js b/test/fixtures/wpt/performance-timeline/navigation-id.helper.js new file mode 100644 index 00000000000..1b72fe9908d --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/navigation-id.helper.js @@ -0,0 +1,144 @@ +// The test functions called in the navigation-counter test. They rely on +// artifacts defined in +// '/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js' +// which should be included before this file to use these functions. + +// This function is to obtain navigation ids of all performance entries to +// verify. +let testInitial = () => { + return window.performance.getEntries().map(e => e.navigationId); +} + +let testMarkMeasure = (markId, markName, MeasureName) => { + const markName1 = 'test-mark'; + const markName2 = 'test-mark' + markId; + const measureName = 'test-measure' + markId; + + window.performance.mark(markName1); + window.performance.mark(markName2); + window.performance.measure(measureName, markName1, markName2); + return window.performance.getEntriesByName(markName2).concat( + window.performance.getEntriesByName(measureName)).map(e => e.navigationId); +} + +let testResourceTiming = async (resourceTimingEntryId) => { + let navigationId; + + let p = new Promise(resolve => { + new PerformanceObserver((list) => { + const entry = list.getEntries().find( + e => e.name.includes('json_resource' + resourceTimingEntryId)); + if (entry) { + navigationId = entry.navigationId; + resolve(); + } + }).observe({ type: 'resource' }); + }); + + const resp = await fetch( + '/performance-timeline/resources/json_resource' + resourceTimingEntryId + '.json'); + await p; + return [navigationId]; +} + +let testElementTiming = async (elementTimingEntryId) => { + let navigationId; + let p = new Promise(resolve => { + new PerformanceObserver((list) => { + const entry = list.getEntries().find( + e => e.entryType === 'element' && e.identifier === 'test-element-timing' + elementTimingEntryId); + if (entry) { + navigationId = entry.navigationId; + resolve(); + } + }).observe({ type: 'element' }); + }); + + let el = document.createElement('p'); + el.setAttribute('elementtiming', 'test-element-timing' + elementTimingEntryId); + el.textContent = 'test element timing text'; + document.body.appendChild(el); + await p; + return [navigationId]; +} + +let testLongTask = async () => { + let navigationIds = []; + + let p = new Promise(resolve => { + new PerformanceObserver((list) => { + const entry = list.getEntries().find(e => e.entryType === 'longtask') + if (entry) { + navigationIds.push(entry.navigationId); + navigationIds = navigationIds.concat( + entry.attribution.map(a => a.navigationId)); + resolve(); + } + }).observe({ type: 'longtask' }); + }); + + const script = document.createElement('script'); + script.src = '/performance-timeline/resources/make_long_task.js'; + document.body.appendChild(script); + await p; + document.body.removeChild(script); + return navigationIds; +} + +const testFunctionMap = { + 'mark_measure': testMarkMeasure, + 'resource_timing': testResourceTiming, + 'element_timing': testElementTiming, + 'long_task_task_attribution': testLongTask, +}; + +function runNavigationIdTest(params, description) { + const defaultParams = { + openFunc: url => window.open(url, '_blank', 'noopener'), + scripts: [], + funcBeforeNavigation: () => { }, + targetOrigin: originCrossSite, + navigationTimes: 4, + funcAfterAssertion: () => { }, + } // Apply defaults. + params = { ...defaultParams, ...params }; + + promise_test(async t => { + const pageA = new RemoteContext(token()); + const pageB = new RemoteContext(token()); + + const urlA = executorPath + pageA.context_id; + const urlB = params.targetOrigin + executorPath + pageB.context_id; + // Open url A. + params.openFunc(urlA); + await pageA.execute_script(waitForPageShow); + + // Assert navigation ids of all performance entries are the same. + let navigationIds = await pageA.execute_script(testInitial); + assert_true( + navigationIds.every(t => t === navigationIds[0]), + 'Navigation Ids should be the same as the initial load.'); + + for (i = 1; i <= params.navigationTimes; i++) { + // Navigate away to url B and back. + await navigateAndThenBack(pageA, pageB, urlB); + + // Assert new navigation ids are generated when the document is load from bfcache. + let nextNavigationIds = await pageA.execute_script( + testFunctionMap[params.testName], [i + 1]); + + // Assert navigation ids of all performance entries are the same. + assert_true( + nextNavigationIds.every(t => t === nextNavigationIds[0]), + 'All Navigation Ids should be same after bfcache navigation.'); + + // Assert navigation ids after bfcache navigation are different from those before. + assert_true( + navigationIds[0] !== nextNavigationIds[0], + params.testName + + ' Navigation Ids should be re-generated and different from the previous ones.'); + + navigationIds = nextNavigationIds; + } + }, description); +} \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js new file mode 100644 index 00000000000..e5dbb0f43c8 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js @@ -0,0 +1,21 @@ +// META: title=Aborting a parser should block bfcache +// META: script=./test-helper.js +// META: timeout=long + + +async_test(t => { + if (!sessionStorage.getItem("pageVisited")) { + // This is the first time loading the page. + sessionStorage.setItem("pageVisited", 1); + t.step_timeout(() => { + // Go to another page and instantly come back to this page. + location.href = new URL("../resources/going-back.html", window.location); + }, 0); + // Abort parsing in the middle of loading the page. + window.stop(); + } else { + const nrr = performance.getEntriesByType('navigation')[0].notRestoredReasons; + assert_true(ReasonsInclude(nrr.reasons, "parser-aborted")); + t.done(); + } +}, "aborting a parser should block bfcache."); diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window.js new file mode 100644 index 00000000000..44495fa981b --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window.js @@ -0,0 +1,55 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; + +// Ensure that empty attributes are reported as empty strings and missing +// attributes are reported as null. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + // Add a cross-origin iframe. + const rc1_child = await rc1.addIframe( + /*extraConfig=*/ { + origin: 'HTTP_REMOTE_ORIGIN', + scripts: [], + headers: [], + }, + /*attributes=*/ {id: '', name: ''}, + ); + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + const rc1_child_url = await rc1_child.executeScript(() => { + return location.href; + }); + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/[{ + 'url': null, + 'src': rc1_child_url, + // Id and name should be empty. + 'id': '', + 'name': '', + 'reasons': null, + 'children': null + }]); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js new file mode 100644 index 00000000000..28dbc38575a --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js @@ -0,0 +1,47 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; + +// Ensure that notRestoredReasons are only updated after non BFCache navigation. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/ []); + + // This time no blocking feature is used, so the page is restored + // from BFCache. Ensure that the previous reasons stay there. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ true); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/ []); +}); diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js new file mode 100644 index 00000000000..bfb685451c3 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js @@ -0,0 +1,28 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: timeout=long + +'use strict'; + +// Ensure that notRestoredReasons is empty for successful BFCache restore. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + + // Check the BFCache result and verify that no reasons are recorded + // for successful restore. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ true); + assert_true(await rc1.executeScript(() => { + let reasons = + performance.getEntriesByType('navigation')[0].notRestoredReasons; + return reasons === null; + })); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js new file mode 100644 index 00000000000..2a313fe7b14 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js @@ -0,0 +1,60 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; + +// Ensure that cross-origin subtree's reasons are not exposed to +// notRestoredReasons. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + // Add a cross-origin iframe. + const rc1_child = await rc1.addIframe( + /*extraConfig=*/ { + origin: 'HTTP_REMOTE_ORIGIN', + scripts: [], + headers: [], + }, + /*attributes=*/ {id: 'test-id'}, + ); + // Use WebSocket to block BFCache. + await useWebSocket(rc1_child); + const rc1_child_url = await rc1_child.executeScript(() => { + return location.href; + }); + // Add a child to the iframe. + const rc1_grand_child = await rc1_child.addIframe(); + const rc1_grand_child_url = await rc1_grand_child.executeScript(() => { + return location.href; + }); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': "masked"}], + /*children=*/[{ + 'url': null, + 'src': rc1_child_url, + 'id': 'test-id', + 'name': null, + 'reasons': null, + 'children': null + }]); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window.js new file mode 100644 index 00000000000..c8f53a660fa --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window.js @@ -0,0 +1,40 @@ +// META: title=Ensure that ongoing fetch upon entering bfcache blocks bfcache and recorded. +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: timeout=long + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + const wavURL = new URL(get_host_info().HTTP_REMOTE_ORIGIN + '/fetch/range/resources/long-wav.py'); + await rc1.executeScript((wavURL) => { + // Register pagehide handler to create a fetch request. + addEventListener('pagehide', (wavURL) => { + fetch(wavURL, { + keepalive: true + }); + }) + }); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'fetch'}], + /*children=*/[]); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-iframes-without-attributes.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-iframes-without-attributes.tentative.window.js new file mode 100644 index 00000000000..cda0ac43944 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-iframes-without-attributes.tentative.window.js @@ -0,0 +1,103 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; + +// Ensure that empty attributes are reported as empty strings and missing +// attributes are reported as null. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + // Add a cross-origin iframe. + const rc1_child = await rc1.addIframe( + /*extraConfig=*/ { + origin: 'HTTP_REMOTE_ORIGIN', + scripts: [], + headers: [], + }, + /*attributes=*/ {id: '', name: ''}, + ); + const rc2_child = await rc1.addIframe( + /*extraConfig=*/ { + origin: 'HTTP_REMOTE_ORIGIN', + scripts: [], + headers: [], + }, + /*attributes=*/ {}, + ); + const rc3_child = await rc1.addIframe( + /*extraConfig=*/ {}, + /*attributes=*/ {}, + ); + const rc4_child = await rc1.addIframe( + /*extraConfig=*/ {}, + /*attributes=*/ {id: '', name: ''}, + ); + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + const rc1_child_url = await rc1_child.executeScript(() => { + return location.href; + }); + const rc2_child_url = await rc2_child.executeScript(() => { + return location.href; + }); + const rc3_child_url = await rc3_child.executeScript(() => { + return location.href; + }); + const rc4_child_url = await rc4_child.executeScript(() => { + return location.href; + }); + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/[{ + 'url': null, + 'src': rc1_child_url, + // Id and name should be empty. + 'id': '', + 'name': '', + 'reasons': null, + 'children': null + }, { + 'url': null, + 'src': rc2_child_url, + // Id and name should be null. + 'id': null, + 'name': null, + 'reasons': null, + 'children': null + },{ + 'url': rc3_child_url, + 'src': rc3_child_url, + // Id and name should be null. + 'id': null, + 'name': null, + 'reasons': [], + 'children': [] + }, { + 'url': rc4_child_url, + 'src': rc4_child_url, + 'id': '', + 'name': '', + 'reasons': [], + 'children': [] + }]); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window.js new file mode 100644 index 00000000000..46d8752f20d --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window.js @@ -0,0 +1,32 @@ +// META: title=Ensure that if WebLock is held upon entering bfcache, it cannot enter bfcache and gets reported. +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: timeout=long + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + + // Request a WebLock. + let return_value = await rc1.executeScript(() => { + return new Promise((resolve) => { + navigator.locks.request('resource', () => { + resolve(42); + }); + }) + }); + assert_equals(return_value, 42); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredFromBFCache(rc1, ['lock']); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window.js new file mode 100644 index 00000000000..faa7649bc33 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window.js @@ -0,0 +1,26 @@ +// META: title=Ensure that navigation failure blocks bfcache and gets recorded. +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/404.py +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: timeout=long + +'use strict'; +const {ORIGIN} = get_host_info(); + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ {status: 404}, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredFromBFCache(rc1, ['response-status-not-ok']); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js new file mode 100644 index 00000000000..1cf1d55d90f --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js @@ -0,0 +1,36 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; + +// Ensure that notRestoredReasons is populated when not restored. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/ []); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js new file mode 100644 index 00000000000..7191456cc84 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js @@ -0,0 +1,53 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; +const {ORIGIN, REMOTE_ORIGIN} = get_host_info(); + +// Ensure that notRestoredReasons reset after the server redirect. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + + // Create a remote context with the redirected URL. + let rc1_redirected = + await rcHelper.createContext(/*extraConfig=*/ { + origin: 'HTTP_ORIGIN', + scripts: [], + headers: [], + }); + + const redirectUrl = + `${ORIGIN}/common/redirect.py?location=${encodeURIComponent(rc1_redirected.url)}`; + // Replace the history state. + await rc1.executeScript((url) => { + window.history.replaceState(null, '', url); + }, [redirectUrl]); + + // Navigate away. + const newRemoteContextHelper = await rc1.navigateToNew(); + + // Go back. + await newRemoteContextHelper.historyBack(); + + const navigation_entry = await rc1_redirected.executeScript(() => { + return performance.getEntriesByType('navigation')[0]; + }); + assert_equals( + navigation_entry.redirectCount, 1, 'Expected redirectCount is 1.'); + // Becauase of the redirect, notRestoredReasons is reset. + assert_equals( + navigation_entry.notRestoredReasons, null, + 'Expected notRestoredReasons is null.'); +}); diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window.js new file mode 100644 index 00000000000..1a8972778d2 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window.js @@ -0,0 +1,50 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; +const {ORIGIN, REMOTE_ORIGIN} = get_host_info(); + +// Ensure that notRestoredReasons reset after the server redirect. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/ []); + + // Reload. + await rc1.navigate(() => { + location.reload(); + }, []); + + // Becauase of the reload, notRestoredReasons is reset. + const navigation_entry = await rc1.executeScript(() => { + return performance.getEntriesByType('navigation')[0]; + }); + + assert_equals( + navigation_entry.notRestoredReasons, null, + 'Expected notRestoredReasons is null.'); +}); diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js new file mode 100644 index 00000000000..89d66b070ed --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js @@ -0,0 +1,61 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + + +'use strict'; + +// Ensure that same-origin subtree's reasons are exposed to notRestoredReasons. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + // Add a same-origin iframe and use WebSocket. + const rc1_child = await rc1.addIframe( + /*extra_config=*/ {}, /*attributes=*/ {id: 'test-id'}); + await useWebSocket(rc1_child); + + const rc1_child_url = await rc1_child.executeScript(() => { + return location.href; + }); + // Add a child to the iframe. + const rc1_grand_child = await rc1_child.addIframe(); + const rc1_grand_child_url = await rc1_grand_child.executeScript(() => { + return location.href; + }); + + // Check the BFCache result and the reported reasons. + await assertBFCacheEligibility(rc1, /*shouldRestoreFromBFCache=*/ false); + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[], + /*children=*/[{ + 'url': rc1_child_url, + 'src': rc1_child_url, + 'id': 'test-id', + 'name': '', + 'reasons': [{'reason': 'websocket'}], + 'children': [{ + 'url': rc1_grand_child_url, + 'src': rc1_grand_child_url, + 'id': '', + 'name': '', + 'reasons': [], + 'children': [] + }] + }]); +}); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js new file mode 100644 index 00000000000..1162bfaf760 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js @@ -0,0 +1,43 @@ +// META: title=RemoteContextHelper navigation using BFCache +// META: script=./test-helper.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js +// META: script=/websockets/constants.sub.js +// META: timeout=long + +'use strict'; + +// Ensure that notRestoredReasons are accessible after history replace. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + // Open a window with noopener so that BFCache will work. + const rc1 = await rcHelper.addWindow( + /*config=*/ null, /*options=*/ {features: 'noopener'}); + const rc1_url = await rc1.executeScript(() => { + return location.href; + }); + + // Use WebSocket to block BFCache. + await useWebSocket(rc1); + // Navigate away. + const newRemoteContextHelper = await rc1.navigateToNew(); + // Replace the history state to a same-origin site. + await newRemoteContextHelper.executeScript((destUrl) => { + window.history.replaceState(null, '', '#'); + }); + // Go back. + await newRemoteContextHelper.historyBack(); + + // Reasons are not reset for same-origin replace. + await assertNotRestoredReasonsEquals( + rc1, + /*url=*/ rc1_url, + /*src=*/ null, + /*id=*/ null, + /*name=*/ null, + /*reasons=*/[{'reason': 'websocket'}], + /*children=*/ []); +}); diff --git a/test/fixtures/wpt/performance-timeline/not-restored-reasons/test-helper.js b/test/fixtures/wpt/performance-timeline/not-restored-reasons/test-helper.js new file mode 100644 index 00000000000..ba9a4c0342f --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/not-restored-reasons/test-helper.js @@ -0,0 +1,57 @@ +// META: script=../../html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js + +async function assertNotRestoredReasonsEquals( + remoteContextHelper, url, src, id, name, reasons, children) { + let result = await remoteContextHelper.executeScript(() => { + return performance.getEntriesByType('navigation')[0].notRestoredReasons; + }); + assertReasonsStructEquals( + result, url, src, id, name, reasons, children); +} + +function assertReasonsStructEquals( + result, url, src, id, name, reasons, children) { + assert_equals(result.url, url); + assert_equals(result.src, src); + assert_equals(result.id, id); + assert_equals(result.name, name); + + // Reasons should match. + let expected = new Set(reasons); + let actual = new Set(result.reasons); + matchReasons(extractReason(expected), extractReason(actual)); + + // Children should match. + if (children == null) { + assert_equals(result.children, children); + } else { + for (let j = 0; j < children.length; j++) { + assertReasonsStructEquals( + result.children[j], children[j].url, + children[j].src, children[j].id, children[j].name, children[j].reasons, + children[j].children); + } + } +} + +function ReasonsInclude(reasons, targetReason) { + for (const reason of reasons) { + if (reason.reason == targetReason) { + return true; + } + } + return false; +} + +// Requires: +// - /websockets/constants.sub.js in the test file and pass the domainPort +// constant here. +async function useWebSocket(remoteContextHelper) { + let return_value = await remoteContextHelper.executeScript((domain) => { + return new Promise((resolve) => { + var webSocketInNotRestoredReasonsTests = new WebSocket(domain + '/echo'); + webSocketInNotRestoredReasonsTests.onopen = () => { resolve(42); }; + }); + }, [SCHEME_DOMAIN_PORT]); + assert_equals(return_value, 42); +} \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/resources/child-frame.html b/test/fixtures/wpt/performance-timeline/resources/child-frame.html new file mode 100644 index 00000000000..40c8f726885 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/child-frame.html @@ -0,0 +1,7 @@ + + + + + diff --git a/test/fixtures/wpt/performance-timeline/resources/empty.html b/test/fixtures/wpt/performance-timeline/resources/empty.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/fixtures/wpt/performance-timeline/resources/going-back.html b/test/fixtures/wpt/performance-timeline/resources/going-back.html new file mode 100644 index 00000000000..f4a26669baa --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/going-back.html @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/resources/include-frames-helper.js b/test/fixtures/wpt/performance-timeline/resources/include-frames-helper.js new file mode 100644 index 00000000000..a56489baaf4 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/include-frames-helper.js @@ -0,0 +1,60 @@ +const verifyEntries = (entries, filterOptions) => { + for (const filterOption of filterOptions) { + let countBeforeFiltering = entries.length; + + // Using negate of the condition so that the next filtering is applied on less entries. + entries = entries.filter( + e => !(e.entryType == filterOption['entryType'] && e.name.includes(filterOption['name']))); + + assert_equals( + countBeforeFiltering - entries.length, filterOption['expectedCount'], filterOption['failureMsg']); + } +} + +const createFilterOption = (name, entryType, expectedCount, msgPrefix, description = '') => { + if (description) { + description = ' ' + description; + } + + let failureMsg = + `${msgPrefix} should have ${expectedCount} ${entryType} entries for name ${name}` + description; + + return { + name: name, + entryType: entryType, + expectedCount: expectedCount, + failureMsg: failureMsg + }; +} + +const loadChildFrame = (src) => { + return new Promise(resolve => { + + const childFrame = document.createElement('iframe'); + + childFrame.addEventListener("load", resolve); + + childFrame.src = src; + + document.body.appendChild(childFrame); + }); +} + +const loadChildFrameAndGrandchildFrame = (src) => { + return new Promise(resolve => { + + const crossOriginChildFrame = document.createElement('iframe'); + + // Wait for the child frame to send a message. The child frame would send a message + // when it loads its child frame. + window.addEventListener('message', e => { + if (e.data == 'Load completed') { + resolve(); + } + }); + + crossOriginChildFrame.src = src; + + document.body.appendChild(crossOriginChildFrame) + }); +} diff --git a/test/fixtures/wpt/performance-timeline/resources/include-frames-subframe.html b/test/fixtures/wpt/performance-timeline/resources/include-frames-subframe.html new file mode 100644 index 00000000000..0d43f418a09 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/include-frames-subframe.html @@ -0,0 +1,43 @@ + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/resources/json_resource.json b/test/fixtures/wpt/performance-timeline/resources/json_resource.json new file mode 100644 index 00000000000..68b6ac1d56f --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/json_resource.json @@ -0,0 +1,4 @@ +{ + "name": "nav_id_test", + "target": "resource_timing" +} \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/resources/make_long_task.js b/test/fixtures/wpt/performance-timeline/resources/make_long_task.js new file mode 100644 index 00000000000..a52d6d83929 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/make_long_task.js @@ -0,0 +1,4 @@ +(function () { + let now = window.performance.now(); + while (window.performance.now() < now + 60); +}()); \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/resources/navigation-id-detached-frame-page.html b/test/fixtures/wpt/performance-timeline/resources/navigation-id-detached-frame-page.html new file mode 100644 index 00000000000..02aafbb5c78 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/navigation-id-detached-frame-page.html @@ -0,0 +1,21 @@ + + + + + + The navigation_id Detached iframe Page. + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/performance-timeline/resources/worker-navigation-id.js b/test/fixtures/wpt/performance-timeline/resources/worker-navigation-id.js new file mode 100644 index 00000000000..3a2740d0675 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/resources/worker-navigation-id.js @@ -0,0 +1,6 @@ +self.onmessage = () => { + const mark_name = 'user_timig_mark'; + performance.mark(mark_name); + postMessage(performance.getEntriesByName(mark_name)[0].navigationId); + self.close(); +} diff --git a/test/fixtures/wpt/performance-timeline/supportedEntryTypes-cross-realm-access.html b/test/fixtures/wpt/performance-timeline/supportedEntryTypes-cross-realm-access.html new file mode 100644 index 00000000000..8b86a6398bf --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/supportedEntryTypes-cross-realm-access.html @@ -0,0 +1,18 @@ + + +Cross-realm access of supportedEntryTypes returns Array of another realm + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/detached-frame.html b/test/fixtures/wpt/performance-timeline/tentative/detached-frame.html new file mode 100644 index 00000000000..70019223a64 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/detached-frame.html @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A-A.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A-A.html new file mode 100644 index 00000000000..57623e5b33b --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A-A.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A.html new file mode 100644 index 00000000000..bcb9a81657f --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-A.html @@ -0,0 +1,76 @@ + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AA.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AA.html new file mode 100644 index 00000000000..cccbf4100dd --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AA.html @@ -0,0 +1,51 @@ + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AB.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AB.html new file mode 100644 index 00000000000..d630665b652 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-AB.html @@ -0,0 +1,53 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-A.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-A.html new file mode 100644 index 00000000000..58cad40faba --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-A.html @@ -0,0 +1,91 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-B.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-B.html new file mode 100644 index 00000000000..2368a8e881a --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B-B.html @@ -0,0 +1,57 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B.html b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B.html new file mode 100644 index 00000000000..b823d6edaa3 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/include-frames-originA-B.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/performance-entry-source.html b/test/fixtures/wpt/performance-timeline/tentative/performance-entry-source.html new file mode 100644 index 00000000000..d10d3c5ed51 --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/performance-entry-source.html @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/tentative/with-filter-options-originA.html b/test/fixtures/wpt/performance-timeline/tentative/with-filter-options-originA.html new file mode 100644 index 00000000000..6c6643df75c --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/tentative/with-filter-options-originA.html @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/test/fixtures/wpt/performance-timeline/timing-removed-iframe.html b/test/fixtures/wpt/performance-timeline/timing-removed-iframe.html new file mode 100644 index 00000000000..43988b21fbb --- /dev/null +++ b/test/fixtures/wpt/performance-timeline/timing-removed-iframe.html @@ -0,0 +1,16 @@ + + + + + + + diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index 103e3962845..6d521f98a4a 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -56,7 +56,7 @@ "path": "interfaces" }, "performance-timeline": { - "commit": "17ebc3aea0d6321e69554067c39ab5855e6fb67e", + "commit": "94caab7038b27c16d605fa3547dacbee3a2fde4e", "path": "performance-timeline" }, "resource-timing": { diff --git a/test/wpt/status/performance-timeline.json b/test/wpt/status/performance-timeline.json index 73e1aad56cf..799ee97538d 100644 --- a/test/wpt/status/performance-timeline.json +++ b/test/wpt/status/performance-timeline.json @@ -21,5 +21,58 @@ }, "webtiming-resolution.any.js": { "skip": "flaky" + }, + "not-restored-reasons/performance-navigation-timing-attributes.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-fetch.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-iframes-without-attributes.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-lock.https.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-reload.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js": { + "skip": "Depends on HTML WPT" + }, + "not-restored-reasons/abort-block-bfcache.window.js": { + "fail": { + "note": "Requires window.stop()", + "expected": [ + "aborting a parser should block bfcache." + ] + } + }, + "idlharness-shadowrealm.window.js": { + "skip": "ShadowRealm support is not enabled" + }, + "droppedentriescount.any.js": { + "skip": "WPTRunner does not support fetch()" } }