
We see in these 2 tests PerformanceObserver timeouts happens and they are mostly on Linux-lacros(checked few other builders the failures seems to be infra failures). This is disable the 2 tests for now. There was a refactor CL that landed 2 weeks ago. I'll take a look to see if the timeout is related. Bug: 1515095 Change-Id: Ibc70440e8a0143932f80ec0b16ebc13429cf96dd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5159608 Reviewed-by: Bo Liu <boliu@chromium.org> Reviewed-by: Ian Clelland <iclelland@chromium.org> Commit-Queue: Hao Liu <haoliuk@chromium.org> Cr-Commit-Position: refs/heads/main@{#1242052}
387 lines
14 KiB
C++
387 lines
14 KiB
C++
// Copyright 2022 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/base_paths.h"
|
|
#include "base/command_line.h"
|
|
#include "base/path_service.h"
|
|
#include "content/browser/web_contents/web_contents_impl.h"
|
|
#include "content/common/content_navigation_policy.h"
|
|
#include "content/public/common/content_switches.h"
|
|
#include "content/public/test/browser_test.h"
|
|
#include "content/public/test/content_browser_test.h"
|
|
#include "content/public/test/content_browser_test_utils.h"
|
|
#include "content/shell/browser/shell.h"
|
|
#include "content/shell/common/shell_switches.h"
|
|
#include "content/test/content_browser_test_utils_internal.h"
|
|
#include "net/dns/mock_host_resolver.h"
|
|
|
|
namespace content {
|
|
|
|
class PerformanceTimelineBrowserTest : public ContentBrowserTest {
|
|
protected:
|
|
void SetUpOnMainThread() override {
|
|
host_resolver()->AddRule("*", "127.0.0.1");
|
|
ContentBrowserTest::SetUpOnMainThread();
|
|
}
|
|
|
|
WebContentsImpl* web_contents() const {
|
|
return static_cast<WebContentsImpl*>(shell()->web_contents());
|
|
}
|
|
|
|
void SetUpCommandLine(base::CommandLine* command_line) override {
|
|
ContentBrowserTest::SetUpCommandLine(command_line);
|
|
}
|
|
|
|
RenderFrameHostImpl* current_frame_host() {
|
|
return web_contents()->GetPrimaryFrameTree().root()->current_frame_host();
|
|
}
|
|
|
|
[[nodiscard]] EvalJsResult GetNavigationId(const std::string& name) {
|
|
const char kGetPerformanceEntryTemplate[] = R"(
|
|
(() => {performance.mark($1);
|
|
return performance.getEntriesByName($1)[0].navigationId;})();
|
|
)";
|
|
std::string script = JsReplace(kGetPerformanceEntryTemplate, name);
|
|
return EvalJs(shell(), script);
|
|
}
|
|
};
|
|
|
|
IN_PROC_BROWSER_TEST_F(PerformanceTimelineBrowserTest,
|
|
NoResourceTimingEntryForFileProtocol) {
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
|
|
base::FilePath file_path;
|
|
CHECK(base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &file_path));
|
|
|
|
file_path = file_path.Append(GetTestDataFilePath())
|
|
.AppendASCII(
|
|
"performance_timeline/"
|
|
"resource-timing-not-for-file-protocol.html");
|
|
|
|
EXPECT_TRUE(NavigateToURL(shell(), GetFileUrlWithQuery(file_path, "")));
|
|
|
|
// The test html page references 2 css file. One is present and would be
|
|
// loaded via file protocol and the other is not present and would have load
|
|
// failure. Both should not emit a resource timing entry.
|
|
EXPECT_EQ(
|
|
0, EvalJs(shell(),
|
|
"window.performance.getEntriesByType('resource').filter(e=>e."
|
|
"name.includes('css')).length;"));
|
|
|
|
std::string applied_style_color = "rgb(0, 128, 0)";
|
|
|
|
// Verify that style.css is fetched by verifying color green is applied.
|
|
EXPECT_EQ(applied_style_color, EvalJs(shell(), "getTextColor()"));
|
|
|
|
// If the same page is loaded via http protocol, both the successful load nad
|
|
// failure load should emit a resource timing entry.
|
|
const GURL url(embedded_test_server()->GetURL(
|
|
"a.com",
|
|
"/performance_timeline/"
|
|
"resource-timing-not-for-file-protocol.html"));
|
|
|
|
EXPECT_TRUE(NavigateToURL(shell(), url));
|
|
|
|
EXPECT_EQ(
|
|
2, EvalJs(shell(),
|
|
"window.performance.getEntriesByType('resource').filter(e=>e."
|
|
"name.includes('css')).length;"));
|
|
|
|
// Verify that style.css is fetched by verifying color green is applied.
|
|
EXPECT_EQ(applied_style_color, EvalJs(shell(), "getTextColor()"));
|
|
|
|
// Verify that style.css that is fetched has its resource timing entry.
|
|
EXPECT_EQ(
|
|
1, EvalJs(shell(),
|
|
"window.performance.getEntriesByType('resource').filter(e=>e."
|
|
"name.includes('resources/style.css')).length;"));
|
|
|
|
// Verify that non_exist.css that is not fetched has its resource timing
|
|
// entry.
|
|
EXPECT_EQ(
|
|
1, EvalJs(shell(),
|
|
"window.performance.getEntriesByType('resource').filter(e=>e."
|
|
"name.includes('resources/non_exist_style.css')).length;"));
|
|
}
|
|
|
|
class PerformanceTimelineLCPStartTimePrecisionBrowserTest
|
|
: public PerformanceTimelineBrowserTest {
|
|
protected:
|
|
EvalJsResult GetIsEqualToPrecision() const {
|
|
std::string script =
|
|
content::JsReplace("isEqualToPrecision($1);", getPrecision());
|
|
return EvalJs(shell(), script);
|
|
}
|
|
|
|
int32_t getPrecision() const { return precision_; }
|
|
|
|
private:
|
|
int32_t precision_ = 10;
|
|
};
|
|
|
|
#if BUILDFLAG(IS_CHROMEOS_LACROS)
|
|
#define MAYBE_LCPStartTimePrecision DISABLED_LCPStartTimePrecision
|
|
#else
|
|
#define MAYBE_LCPStartTimePrecision LCPStartTimePrecision
|
|
#endif
|
|
IN_PROC_BROWSER_TEST_F(PerformanceTimelineLCPStartTimePrecisionBrowserTest,
|
|
MAYBE_LCPStartTimePrecision) {
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
const GURL url1(embedded_test_server()->GetURL(
|
|
"a.com", "/performance_timeline/lcp-start-time-precision.html"));
|
|
|
|
EXPECT_TRUE(NavigateToURL(shell(), url1));
|
|
|
|
EXPECT_TRUE(GetIsEqualToPrecision().ExtractBool());
|
|
}
|
|
|
|
class PerformanceTimelineNavigationIdBrowserTest
|
|
: public PerformanceTimelineBrowserTest {
|
|
protected:
|
|
void SetUpCommandLine(base::CommandLine* command_line) override {
|
|
ContentBrowserTest::SetUpCommandLine(command_line);
|
|
base::CommandLine::ForCurrentProcess()->AppendSwitch(
|
|
"--enable-blink-test-features");
|
|
}
|
|
};
|
|
|
|
// This test case is to verify PerformanceEntry.navigationId gets incremented
|
|
// for each back/forward cache restore.
|
|
IN_PROC_BROWSER_TEST_F(PerformanceTimelineNavigationIdBrowserTest,
|
|
BackForwardCacheRestore) {
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
const GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
|
const GURL url2(embedded_test_server()->GetURL("b.com", "/title1.html"));
|
|
|
|
EXPECT_TRUE(NavigateToURL(shell(), url1));
|
|
|
|
const std::string initial_navigation_id =
|
|
GetNavigationId("first_nav").ExtractString();
|
|
// Navigate away and back 3 times. The 1st time is to verify the
|
|
// navigation id is incremented. The 2nd time is to verify that the id is
|
|
// incremented on the same restored document. The 3rd time is to
|
|
// verify the increment does not stop at 2.
|
|
RenderFrameHostImplWrapper rfh_a(current_frame_host());
|
|
std::string prev_navigation_id = initial_navigation_id;
|
|
|
|
for (int i = 1; i <= 3; i++) {
|
|
// Navigate away
|
|
ASSERT_TRUE(NavigateToURL(shell(), url2));
|
|
|
|
// Verify `rfh_a` is stored in back/forward cache in case back/forward cache
|
|
// feature is enabled.
|
|
if (IsBackForwardCacheEnabled())
|
|
ASSERT_TRUE(rfh_a->IsInBackForwardCache());
|
|
else {
|
|
// Verify `rfh_a` is deleted in case back/forward cache feature is
|
|
// disabled.
|
|
ASSERT_TRUE(rfh_a.WaitUntilRenderFrameDeleted());
|
|
}
|
|
|
|
// Navigate back.
|
|
ASSERT_TRUE(HistoryGoBack(web_contents()));
|
|
|
|
// Verify navigation id is re-generated each time in case back/forward
|
|
// cache feature is enabled. Verify navigation id is not changed in case
|
|
// back/forward cache feature is not enabled.
|
|
std::string curr_navigation_id =
|
|
GetNavigationId("subsequent_nav" + base::NumberToString(i))
|
|
.ExtractString();
|
|
EXPECT_NE(curr_navigation_id, prev_navigation_id);
|
|
EXPECT_NE(curr_navigation_id, initial_navigation_id);
|
|
|
|
prev_navigation_id = curr_navigation_id;
|
|
}
|
|
}
|
|
|
|
class PerformanceTimelinePrefetchTransferSizeBrowserTest
|
|
: public PerformanceTimelineBrowserTest {
|
|
protected:
|
|
EvalJsResult Prefetch() {
|
|
std::string script = R"(
|
|
(() => {
|
|
return addPrefetch();
|
|
})();
|
|
)";
|
|
return EvalJs(shell(), script);
|
|
}
|
|
[[nodiscard]] EvalJsResult GetTransferSize() {
|
|
std::string script = R"(
|
|
(() => {
|
|
return performance.getEntriesByType('navigation')[0].transferSize;
|
|
})();
|
|
)";
|
|
return EvalJs(shell(), script);
|
|
}
|
|
};
|
|
|
|
IN_PROC_BROWSER_TEST_F(PerformanceTimelinePrefetchTransferSizeBrowserTest,
|
|
PrefetchTransferSize) {
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
|
|
const GURL prefetch_url(
|
|
embedded_test_server()->GetURL("a.com", "/title1.html"));
|
|
const GURL landing_url(embedded_test_server()->GetURL(
|
|
"a.com", "/performance_timeline/prefetch.html"));
|
|
|
|
EXPECT_TRUE(NavigateToURL(shell(), landing_url));
|
|
Prefetch();
|
|
EXPECT_TRUE(NavigateToURL(shell(), prefetch_url));
|
|
// Navigate to a prefetched url should result in a navigation timing entry
|
|
// with 0 transfer size.
|
|
EXPECT_EQ(0, GetTransferSize());
|
|
}
|
|
|
|
class PerformanceTimelineBackForwardCacheRestorationBrowserTest
|
|
: public PerformanceTimelineBrowserTest {
|
|
protected:
|
|
void SetUpCommandLine(base::CommandLine* command_line) override {
|
|
ContentBrowserTest::SetUpCommandLine(command_line);
|
|
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
|
switches::kEnableBlinkTestFeatures, "NavigationId");
|
|
command_line->AppendSwitch(switches::kExposeInternalsForTesting);
|
|
}
|
|
|
|
EvalJsResult GetBackForwardCacheRestorationEntriesByObserver() const {
|
|
std::string script = R"(
|
|
(
|
|
async ()=>Promise.all([entryTypesPromise, typePromise])
|
|
)();
|
|
)";
|
|
return EvalJs(shell(), script);
|
|
}
|
|
|
|
EvalJsResult GetDroppedEntriesCount() const {
|
|
std::string script = R"(
|
|
(
|
|
async ()=> {
|
|
let promise = new Promise(resolve=>{
|
|
new PerformanceObserver((list, observer, options) => {
|
|
resolve(options['droppedEntriesCount']);
|
|
}).observe({ type: 'back-forward-cache-restoration',
|
|
buffered: true });
|
|
});
|
|
return await promise;
|
|
}
|
|
)();
|
|
)";
|
|
return EvalJs(shell(), script);
|
|
}
|
|
|
|
EvalJsResult SetBackForwardCacheRestorationBufferSize(int size) const {
|
|
std::string script = R"(
|
|
internals.setBackForwardCacheRestorationBufferSize($1);
|
|
)";
|
|
script = content::JsReplace(script, size);
|
|
return EvalJs(shell(), script);
|
|
}
|
|
|
|
EvalJsResult RegisterPerformanceObservers(int max_size) const {
|
|
std::string script = R"(
|
|
let entryTypesEntries = [];
|
|
var entryTypesPromise = new Promise(resolve=>{
|
|
new PerformanceObserver((list) => {
|
|
const entries = list.getEntries().filter(
|
|
e => e.entryType == 'back-forward-cache-restoration').map(
|
|
e=>e.toJSON());;
|
|
if (entries.length > 0) {
|
|
entryTypesEntries = entryTypesEntries.concat(entries);
|
|
}
|
|
if(entryTypesEntries.length>=$1){
|
|
resolve(entryTypesEntries);
|
|
}
|
|
}).observe({ entryTypes: ['back-forward-cache-restoration'] });
|
|
});
|
|
|
|
let typeEntries = [];
|
|
var typePromise = new Promise(resolve=>{
|
|
new PerformanceObserver((list) => {
|
|
const entries = list.getEntries().filter(
|
|
e => e.entryType == 'back-forward-cache-restoration').map(
|
|
e=>e.toJSON());
|
|
if (entries.length > 0) {
|
|
typeEntries = typeEntries.concat(entries);
|
|
}
|
|
if(typeEntries.length>=$1){
|
|
resolve(typeEntries);
|
|
}
|
|
}).observe({type: 'back-forward-cache-restoration'});
|
|
});
|
|
)";
|
|
script = content::JsReplace(script, max_size);
|
|
return EvalJs(shell(), script);
|
|
}
|
|
|
|
// This method checks a list of performance entries of the
|
|
// back-forward-cache-restoration type. Each entry is created when there is
|
|
// a back/forward cache restoration.
|
|
void CheckEntries(const base::Value::List lst,
|
|
const std::string& initial_navigation_id) const {
|
|
std::string prev_navigation_id = initial_navigation_id;
|
|
|
|
for (const auto& i : lst) {
|
|
auto* dict = i.GetIfDict();
|
|
EXPECT_TRUE(dict);
|
|
EXPECT_EQ("", *dict->FindString("name"));
|
|
EXPECT_EQ("back-forward-cache-restoration",
|
|
*dict->FindString("entryType"));
|
|
|
|
const std::string* curr_navigation_id = dict->FindString("navigationId");
|
|
// This verifies the navigation id changes each time a back/forward
|
|
// restoration happens.
|
|
EXPECT_NE(prev_navigation_id, *curr_navigation_id);
|
|
|
|
prev_navigation_id = *curr_navigation_id;
|
|
|
|
EXPECT_LE(dict->FindDouble("pageshowEventStart").value(),
|
|
dict->FindDouble("pageshowEventEnd").value());
|
|
}
|
|
}
|
|
};
|
|
|
|
IN_PROC_BROWSER_TEST_F(
|
|
PerformanceTimelineBackForwardCacheRestorationBrowserTest,
|
|
Create) {
|
|
if (!IsBackForwardCacheEnabled())
|
|
return;
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
const GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
|
const GURL url2(embedded_test_server()->GetURL("b.com", "/title1.html"));
|
|
|
|
EXPECT_TRUE(NavigateToURL(shell(), url1));
|
|
|
|
RenderFrameHostImplWrapper rfh(current_frame_host());
|
|
|
|
int buffer_size = 10;
|
|
int num_of_loops = 12;
|
|
|
|
SetBackForwardCacheRestorationBufferSize(buffer_size);
|
|
RegisterPerformanceObservers(num_of_loops);
|
|
|
|
std::string initial_navigation_id =
|
|
GetNavigationId("initial_navigation_id").ExtractString();
|
|
for (int i = 0; i < num_of_loops; i++) {
|
|
// Navigate away
|
|
ASSERT_TRUE(NavigateToURL(shell(), url2));
|
|
|
|
// Verify `rfh` is stored in back/forward cache.
|
|
ASSERT_TRUE(rfh->IsInBackForwardCache());
|
|
|
|
// Navigate back.
|
|
ASSERT_TRUE(HistoryGoBack(web_contents()));
|
|
}
|
|
auto result = std::move(GetBackForwardCacheRestorationEntriesByObserver()
|
|
.ExtractList()
|
|
.GetList());
|
|
CheckEntries(std::move(result[0]).TakeList(), initial_navigation_id);
|
|
CheckEntries(std::move(result[1]).TakeList(), initial_navigation_id);
|
|
|
|
// Size of back forward restoration buffer is smaller than the number of back
|
|
// forward restoration instances expected by 2. Therefore the
|
|
// droppedEntriesCount is expected to be 2.
|
|
EXPECT_EQ(2, GetDroppedEntriesCount().ExtractInt());
|
|
}
|
|
|
|
} // namespace content
|