blob: 0a549b98a459de92a4e50a8892d4bbb720fc1a57 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/predictors/loading_data_collector.h"
#include <iostream>
#include <memory>
#include <utility>
#include "base/test/histogram_tester.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/predictors/loading_predictor_config.h"
#include "chrome/browser/predictors/loading_test_util.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::StrictMock;
namespace predictors {
class LoadingDataCollectorTest : public testing::Test {
public:
LoadingDataCollectorTest() : profile_(base::MakeUnique<TestingProfile>()) {
LoadingPredictorConfig config;
PopulateTestConfig(&config);
mock_predictor_ =
base::MakeUnique<StrictMock<MockResourcePrefetchPredictor>>(
config, profile_.get()),
collector_ = base::MakeUnique<LoadingDataCollector>(mock_predictor_.get(),
nullptr, config);
}
void SetUp() override {
content::RunAllBlockingPoolTasksUntilIdle(); // Runs the DB lookup.
url_request_job_factory_.Reset();
url_request_context_.set_job_factory(&url_request_job_factory_);
}
protected:
content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestingProfile> profile_;
net::TestURLRequestContext url_request_context_;
MockURLRequestJobFactory url_request_job_factory_;
std::unique_ptr<StrictMock<MockResourcePrefetchPredictor>> mock_predictor_;
std::unique_ptr<LoadingDataCollector> collector_;
};
TEST_F(LoadingDataCollectorTest, SummarizeResponse) {
net::HttpResponseInfo response_info;
response_info.headers =
MakeResponseHeaders("HTTP/1.1 200 OK\n\nSome: Headers\n");
response_info.was_cached = true;
url_request_job_factory_.set_response_info(response_info);
GURL url("http://www.google.com/cat.png");
std::unique_ptr<net::URLRequest> request =
CreateURLRequest(url_request_context_, url, net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, true);
URLRequestSummary summary;
EXPECT_TRUE(URLRequestSummary::SummarizeResponse(*request, &summary));
EXPECT_EQ(url, summary.resource_url);
EXPECT_EQ(content::RESOURCE_TYPE_IMAGE, summary.resource_type);
EXPECT_TRUE(summary.was_cached);
EXPECT_FALSE(summary.has_validators);
EXPECT_FALSE(summary.always_revalidate);
// Navigation_id elements should be unset by default.
EXPECT_EQ(-1, summary.navigation_id.tab_id);
EXPECT_EQ(GURL(), summary.navigation_id.main_frame_url);
}
TEST_F(LoadingDataCollectorTest, SummarizeResponseContentType) {
net::HttpResponseInfo response_info;
response_info.headers = MakeResponseHeaders(
"HTTP/1.1 200 OK\n\n"
"Some: Headers\n"
"Content-Type: image/whatever\n");
url_request_job_factory_.set_response_info(response_info);
url_request_job_factory_.set_mime_type("image/png");
std::unique_ptr<net::URLRequest> request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_PREFETCH, true);
URLRequestSummary summary;
EXPECT_TRUE(URLRequestSummary::SummarizeResponse(*request, &summary));
EXPECT_EQ(content::RESOURCE_TYPE_IMAGE, summary.resource_type);
}
TEST_F(LoadingDataCollectorTest, SummarizeResponseCachePolicy) {
net::HttpResponseInfo response_info;
response_info.headers = MakeResponseHeaders(
"HTTP/1.1 200 OK\n"
"Some: Headers\n");
url_request_job_factory_.set_response_info(response_info);
std::unique_ptr<net::URLRequest> request_no_validators = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_PREFETCH, true);
URLRequestSummary summary;
EXPECT_TRUE(
URLRequestSummary::SummarizeResponse(*request_no_validators, &summary));
EXPECT_FALSE(summary.has_validators);
response_info.headers = MakeResponseHeaders(
"HTTP/1.1 200 OK\n"
"ETag: \"Cr66\"\n"
"Cache-Control: no-cache\n");
url_request_job_factory_.set_response_info(response_info);
std::unique_ptr<net::URLRequest> request_etag = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_PREFETCH, true);
EXPECT_TRUE(URLRequestSummary::SummarizeResponse(*request_etag, &summary));
EXPECT_TRUE(summary.has_validators);
EXPECT_TRUE(summary.always_revalidate);
}
TEST_F(LoadingDataCollectorTest, HandledResourceTypes) {
EXPECT_TRUE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_STYLESHEET, "bogus/mime-type"));
EXPECT_TRUE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_STYLESHEET, ""));
EXPECT_FALSE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_WORKER, "text/css"));
EXPECT_FALSE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_WORKER, ""));
EXPECT_TRUE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_PREFETCH, "text/css"));
EXPECT_FALSE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_PREFETCH, "bogus/mime-type"));
EXPECT_FALSE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_PREFETCH, ""));
EXPECT_TRUE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_PREFETCH, "application/font-woff"));
EXPECT_TRUE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_PREFETCH, "font/woff2"));
EXPECT_FALSE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_XHR, ""));
EXPECT_FALSE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_XHR, "bogus/mime-type"));
EXPECT_TRUE(LoadingDataCollector::IsHandledResourceType(
content::RESOURCE_TYPE_XHR, "application/javascript"));
}
TEST_F(LoadingDataCollectorTest, ShouldRecordRequestMainFrame) {
std::unique_ptr<net::URLRequest> http_request =
CreateURLRequest(url_request_context_, GURL("http://www.google.com"),
net::MEDIUM, content::RESOURCE_TYPE_IMAGE, true);
EXPECT_TRUE(LoadingDataCollector::ShouldRecordRequest(
http_request.get(), content::RESOURCE_TYPE_MAIN_FRAME));
std::unique_ptr<net::URLRequest> https_request =
CreateURLRequest(url_request_context_, GURL("https://www.google.com"),
net::MEDIUM, content::RESOURCE_TYPE_IMAGE, true);
EXPECT_TRUE(LoadingDataCollector::ShouldRecordRequest(
https_request.get(), content::RESOURCE_TYPE_MAIN_FRAME));
std::unique_ptr<net::URLRequest> file_request =
CreateURLRequest(url_request_context_, GURL("file://www.google.com"),
net::MEDIUM, content::RESOURCE_TYPE_IMAGE, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordRequest(
file_request.get(), content::RESOURCE_TYPE_MAIN_FRAME));
std::unique_ptr<net::URLRequest> https_request_with_port =
CreateURLRequest(url_request_context_, GURL("https://www.google.com:666"),
net::MEDIUM, content::RESOURCE_TYPE_IMAGE, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordRequest(
https_request_with_port.get(), content::RESOURCE_TYPE_MAIN_FRAME));
}
TEST_F(LoadingDataCollectorTest, ShouldRecordRequestSubResource) {
std::unique_ptr<net::URLRequest> http_request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, false);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordRequest(
http_request.get(), content::RESOURCE_TYPE_IMAGE));
std::unique_ptr<net::URLRequest> https_request = CreateURLRequest(
url_request_context_, GURL("https://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, false);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordRequest(
https_request.get(), content::RESOURCE_TYPE_IMAGE));
std::unique_ptr<net::URLRequest> file_request = CreateURLRequest(
url_request_context_, GURL("file://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, false);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordRequest(
file_request.get(), content::RESOURCE_TYPE_IMAGE));
std::unique_ptr<net::URLRequest> https_request_with_port = CreateURLRequest(
url_request_context_, GURL("https://www.google.com:666/cat.png"),
net::MEDIUM, content::RESOURCE_TYPE_IMAGE, false);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordRequest(
https_request_with_port.get(), content::RESOURCE_TYPE_IMAGE));
}
TEST_F(LoadingDataCollectorTest, ShouldRecordResponseMainFrame) {
net::HttpResponseInfo response_info;
response_info.headers = MakeResponseHeaders("");
url_request_job_factory_.set_response_info(response_info);
std::unique_ptr<net::URLRequest> http_request =
CreateURLRequest(url_request_context_, GURL("http://www.google.com"),
net::MEDIUM, content::RESOURCE_TYPE_MAIN_FRAME, true);
EXPECT_TRUE(LoadingDataCollector::ShouldRecordResponse(http_request.get()));
std::unique_ptr<net::URLRequest> https_request =
CreateURLRequest(url_request_context_, GURL("https://www.google.com"),
net::MEDIUM, content::RESOURCE_TYPE_MAIN_FRAME, true);
EXPECT_TRUE(LoadingDataCollector::ShouldRecordResponse(https_request.get()));
std::unique_ptr<net::URLRequest> file_request =
CreateURLRequest(url_request_context_, GURL("file://www.google.com"),
net::MEDIUM, content::RESOURCE_TYPE_MAIN_FRAME, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordResponse(file_request.get()));
std::unique_ptr<net::URLRequest> https_request_with_port =
CreateURLRequest(url_request_context_, GURL("https://www.google.com:666"),
net::MEDIUM, content::RESOURCE_TYPE_MAIN_FRAME, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordResponse(
https_request_with_port.get()));
}
TEST_F(LoadingDataCollectorTest, ShouldRecordResponseSubresource) {
net::HttpResponseInfo response_info;
response_info.headers =
MakeResponseHeaders("HTTP/1.1 200 OK\n\nSome: Headers\n");
response_info.was_cached = true;
url_request_job_factory_.set_response_info(response_info);
// Protocol.
std::unique_ptr<net::URLRequest> http_image_request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, true);
EXPECT_TRUE(
LoadingDataCollector::ShouldRecordResponse(http_image_request.get()));
std::unique_ptr<net::URLRequest> https_image_request = CreateURLRequest(
url_request_context_, GURL("https://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, true);
EXPECT_TRUE(
LoadingDataCollector::ShouldRecordResponse(https_image_request.get()));
std::unique_ptr<net::URLRequest> https_image_request_with_port =
CreateURLRequest(url_request_context_,
GURL("https://www.google.com:666/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordResponse(
https_image_request_with_port.get()));
std::unique_ptr<net::URLRequest> file_image_request = CreateURLRequest(
url_request_context_, GURL("file://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_IMAGE, true);
EXPECT_FALSE(
LoadingDataCollector::ShouldRecordResponse(file_image_request.get()));
// ResourceType.
std::unique_ptr<net::URLRequest> sub_frame_request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/frame.html"),
net::MEDIUM, content::RESOURCE_TYPE_SUB_FRAME, true);
EXPECT_FALSE(
LoadingDataCollector::ShouldRecordResponse(sub_frame_request.get()));
std::unique_ptr<net::URLRequest> font_request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/comic-sans-ms.woff"),
net::MEDIUM, content::RESOURCE_TYPE_FONT_RESOURCE, true);
EXPECT_TRUE(LoadingDataCollector::ShouldRecordResponse(font_request.get()));
// From MIME Type.
url_request_job_factory_.set_mime_type("image/png");
std::unique_ptr<net::URLRequest> prefetch_image_request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_PREFETCH, true);
EXPECT_TRUE(
LoadingDataCollector::ShouldRecordResponse(prefetch_image_request.get()));
url_request_job_factory_.set_mime_type("image/my-wonderful-format");
std::unique_ptr<net::URLRequest> prefetch_unknown_image_request =
CreateURLRequest(url_request_context_,
GURL("http://www.google.com/cat.png"), net::MEDIUM,
content::RESOURCE_TYPE_PREFETCH, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordResponse(
prefetch_unknown_image_request.get()));
url_request_job_factory_.set_mime_type("font/woff");
std::unique_ptr<net::URLRequest> prefetch_font_request = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/comic-sans-ms.woff"),
net::MEDIUM, content::RESOURCE_TYPE_PREFETCH, true);
EXPECT_TRUE(
LoadingDataCollector::ShouldRecordResponse(prefetch_font_request.get()));
url_request_job_factory_.set_mime_type("font/woff-woff");
std::unique_ptr<net::URLRequest> prefetch_unknown_font_request =
CreateURLRequest(url_request_context_,
GURL("http://www.google.com/comic-sans-ms.woff"),
net::MEDIUM, content::RESOURCE_TYPE_PREFETCH, true);
EXPECT_FALSE(LoadingDataCollector::ShouldRecordResponse(
prefetch_unknown_font_request.get()));
// Not main frame.
std::unique_ptr<net::URLRequest> font_request_sub_frame = CreateURLRequest(
url_request_context_, GURL("http://www.google.com/comic-sans-ms.woff"),
net::MEDIUM, content::RESOURCE_TYPE_FONT_RESOURCE, false);
EXPECT_FALSE(
LoadingDataCollector::ShouldRecordResponse(font_request_sub_frame.get()));
}
// Single navigation that will be recorded. Will check for duplicate
// resources and also for number of resources saved.
TEST_F(LoadingDataCollectorTest, SimpleNavigation) {
URLRequestSummary main_frame =
CreateURLRequestSummary(1, "http://www.google.com");
collector_->RecordURLRequest(main_frame);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
std::vector<URLRequestSummary> resources;
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/style1.css",
content::RESOURCE_TYPE_STYLESHEET, net::MEDIUM, "text/css", false));
collector_->RecordURLResponse(resources.back());
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script1.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", false));
collector_->RecordURLResponse(resources.back());
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script2.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", false));
collector_->RecordURLResponse(resources.back());
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script1.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", true));
collector_->RecordURLResponse(resources.back());
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/image1.png",
content::RESOURCE_TYPE_IMAGE, net::MEDIUM, "image/png", false));
collector_->RecordURLResponse(resources.back());
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/image2.png",
content::RESOURCE_TYPE_IMAGE, net::MEDIUM, "image/png", false));
collector_->RecordURLResponse(resources.back());
resources.push_back(CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/style2.css",
content::RESOURCE_TYPE_STYLESHEET, net::MEDIUM, "text/css", true));
collector_->RecordURLResponse(resources.back());
auto no_store = CreateURLRequestSummary(
1, "http://www.google.com",
"http://static.google.com/style2-no-store.css",
content::RESOURCE_TYPE_STYLESHEET, net::MEDIUM, "text/css", true);
no_store.is_no_store = true;
collector_->RecordURLResponse(no_store);
auto redirected = CreateURLRequestSummary(
1, "http://www.google.com", "http://reader.google.com/style.css",
content::RESOURCE_TYPE_STYLESHEET, net::MEDIUM, "text/css", true);
redirected.redirect_url = GURL("http://dev.null.google.com/style.css");
collector_->RecordURLRedirect(redirected);
auto summary = CreatePageRequestSummary("http://www.google.com",
"http://www.google.com", resources);
summary.UpdateOrAddToOrigins(no_store);
summary.UpdateOrAddToOrigins(redirected);
redirected.is_no_store = true;
redirected.request_url = redirected.redirect_url;
redirected.redirect_url = GURL();
collector_->RecordURLResponse(redirected);
summary.UpdateOrAddToOrigins(redirected);
EXPECT_CALL(*mock_predictor_,
RecordPageRequestSummaryProxy(testing::Pointee(summary)));
collector_->RecordMainFrameLoadComplete(main_frame.navigation_id);
}
TEST_F(LoadingDataCollectorTest, SimpleRedirect) {
URLRequestSummary fb1 = CreateURLRequestSummary(1, "http://fb.com/google");
collector_->RecordURLRequest(fb1);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
URLRequestSummary fb2 = CreateRedirectRequestSummary(
1, "http://fb.com/google", "http://facebook.com/google");
collector_->RecordURLRedirect(fb2);
URLRequestSummary fb3 = CreateRedirectRequestSummary(
1, "http://facebook.com/google", "https://facebook.com/google");
collector_->RecordURLRedirect(fb3);
NavigationID fb_end = CreateNavigationID(1, "https://facebook.com/google");
EXPECT_CALL(
*mock_predictor_,
RecordPageRequestSummaryProxy(testing::Pointee(CreatePageRequestSummary(
"https://facebook.com/google", "http://fb.com/google",
std::vector<URLRequestSummary>()))));
collector_->RecordMainFrameLoadComplete(fb_end);
}
TEST_F(LoadingDataCollectorTest, OnMainFrameRequest) {
URLRequestSummary summary1 = CreateURLRequestSummary(
1, "http://www.google.com", "http://www.google.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
URLRequestSummary summary2 = CreateURLRequestSummary(
2, "http://www.google.com", "http://www.google.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
URLRequestSummary summary3 = CreateURLRequestSummary(
3, "http://www.yahoo.com", "http://www.yahoo.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
collector_->RecordURLRequest(summary1);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
collector_->RecordURLRequest(summary2);
EXPECT_EQ(2U, collector_->inflight_navigations_.size());
collector_->RecordURLRequest(summary3);
EXPECT_EQ(3U, collector_->inflight_navigations_.size());
// Insert another with same navigation id. It should replace.
URLRequestSummary summary4 = CreateURLRequestSummary(
1, "http://www.nike.com", "http://www.nike.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
URLRequestSummary summary5 = CreateURLRequestSummary(
2, "http://www.google.com", "http://www.google.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
collector_->RecordURLRequest(summary4);
EXPECT_EQ(3U, collector_->inflight_navigations_.size());
// Change this creation time so that it will go away on the next insert.
summary5.navigation_id.creation_time =
base::TimeTicks::Now() - base::TimeDelta::FromDays(1);
collector_->RecordURLRequest(summary5);
EXPECT_EQ(3U, collector_->inflight_navigations_.size());
URLRequestSummary summary6 = CreateURLRequestSummary(
4, "http://www.shoes.com", "http://www.shoes.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
collector_->RecordURLRequest(summary6);
EXPECT_EQ(3U, collector_->inflight_navigations_.size());
EXPECT_TRUE(collector_->inflight_navigations_.find(summary3.navigation_id) !=
collector_->inflight_navigations_.end());
EXPECT_TRUE(collector_->inflight_navigations_.find(summary4.navigation_id) !=
collector_->inflight_navigations_.end());
EXPECT_TRUE(collector_->inflight_navigations_.find(summary6.navigation_id) !=
collector_->inflight_navigations_.end());
}
TEST_F(LoadingDataCollectorTest, OnMainFrameRedirect) {
URLRequestSummary yahoo = CreateURLRequestSummary(1, "http://yahoo.com");
URLRequestSummary bbc1 = CreateURLRequestSummary(2, "http://bbc.com");
URLRequestSummary bbc2 =
CreateRedirectRequestSummary(2, "http://bbc.com", "https://www.bbc.com");
NavigationID bbc_end = CreateNavigationID(2, "https://www.bbc.com");
URLRequestSummary youtube1 = CreateURLRequestSummary(3, "http://youtube.com");
URLRequestSummary youtube2 = CreateRedirectRequestSummary(
3, "http://youtube.com", "https://youtube.com");
NavigationID youtube_end = CreateNavigationID(3, "https://youtube.com");
URLRequestSummary nyt1 = CreateURLRequestSummary(4, "http://nyt.com");
URLRequestSummary nyt2 =
CreateRedirectRequestSummary(4, "http://nyt.com", "http://nytimes.com");
URLRequestSummary nyt3 = CreateRedirectRequestSummary(4, "http://nytimes.com",
"http://m.nytimes.com");
NavigationID nyt_end = CreateNavigationID(4, "http://m.nytimes.com");
URLRequestSummary fb1 = CreateURLRequestSummary(5, "http://fb.com");
URLRequestSummary fb2 =
CreateRedirectRequestSummary(5, "http://fb.com", "http://facebook.com");
URLRequestSummary fb3 = CreateRedirectRequestSummary(5, "http://facebook.com",
"https://facebook.com");
URLRequestSummary fb4 = CreateRedirectRequestSummary(
5, "https://facebook.com",
"https://m.facebook.com/?refsrc=https%3A%2F%2Fwww.facebook.com%2F&_rdr");
NavigationID fb_end = CreateNavigationID(
5,
"https://m.facebook.com/?refsrc=https%3A%2F%2Fwww.facebook.com%2F&_rdr");
// Redirect with empty redirect_url will be deleted.
collector_->RecordURLRequest(yahoo);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
collector_->OnMainFrameRedirect(yahoo);
EXPECT_TRUE(collector_->inflight_navigations_.empty());
// Redirect without previous request works fine.
// collector_->RecordURLRequest(bbc1) missing.
collector_->OnMainFrameRedirect(bbc2);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
EXPECT_EQ(bbc1.navigation_id.main_frame_url,
collector_->inflight_navigations_[bbc_end]->initial_url);
// http://youtube.com -> https://youtube.com.
collector_->RecordURLRequest(youtube1);
EXPECT_EQ(2U, collector_->inflight_navigations_.size());
collector_->OnMainFrameRedirect(youtube2);
EXPECT_EQ(2U, collector_->inflight_navigations_.size());
EXPECT_EQ(youtube1.navigation_id.main_frame_url,
collector_->inflight_navigations_[youtube_end]->initial_url);
// http://nyt.com -> http://nytimes.com -> http://m.nytimes.com.
collector_->RecordURLRequest(nyt1);
EXPECT_EQ(3U, collector_->inflight_navigations_.size());
collector_->OnMainFrameRedirect(nyt2);
collector_->OnMainFrameRedirect(nyt3);
EXPECT_EQ(3U, collector_->inflight_navigations_.size());
EXPECT_EQ(nyt1.navigation_id.main_frame_url,
collector_->inflight_navigations_[nyt_end]->initial_url);
// http://fb.com -> http://facebook.com -> https://facebook.com ->
// https://m.facebook.com/?refsrc=https%3A%2F%2Fwww.facebook.com%2F&_rdr.
collector_->RecordURLRequest(fb1);
EXPECT_EQ(4U, collector_->inflight_navigations_.size());
collector_->OnMainFrameRedirect(fb2);
collector_->OnMainFrameRedirect(fb3);
collector_->OnMainFrameRedirect(fb4);
EXPECT_EQ(4U, collector_->inflight_navigations_.size());
EXPECT_EQ(fb1.navigation_id.main_frame_url,
collector_->inflight_navigations_[fb_end]->initial_url);
}
TEST_F(LoadingDataCollectorTest, OnSubresourceResponse) {
// If there is no inflight navigation, nothing happens.
URLRequestSummary resource1 = CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/style1.css",
content::RESOURCE_TYPE_STYLESHEET, net::MEDIUM, "text/css", false);
collector_->RecordURLResponse(resource1);
EXPECT_TRUE(collector_->inflight_navigations_.empty());
// Add an inflight navigation.
URLRequestSummary main_frame1 = CreateURLRequestSummary(
1, "http://www.google.com", "http://www.google.com",
content::RESOURCE_TYPE_MAIN_FRAME, net::MEDIUM, std::string(), false);
collector_->RecordURLRequest(main_frame1);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
// Now add a few subresources.
URLRequestSummary resource2 = CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script1.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", false);
URLRequestSummary resource3 = CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script2.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", false);
collector_->RecordURLResponse(resource1);
collector_->RecordURLResponse(resource2);
collector_->RecordURLResponse(resource3);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
EXPECT_EQ(3U, collector_->inflight_navigations_[main_frame1.navigation_id]
->subresource_requests.size());
EXPECT_EQ(resource1,
collector_->inflight_navigations_[main_frame1.navigation_id]
->subresource_requests[0]);
EXPECT_EQ(resource2,
collector_->inflight_navigations_[main_frame1.navigation_id]
->subresource_requests[1]);
EXPECT_EQ(resource3,
collector_->inflight_navigations_[main_frame1.navigation_id]
->subresource_requests[2]);
}
TEST_F(LoadingDataCollectorTest, TestRecordFirstContentfulPaint) {
auto res1_time = base::TimeTicks::FromInternalValue(1);
auto res2_time = base::TimeTicks::FromInternalValue(2);
auto fcp_time = base::TimeTicks::FromInternalValue(3);
auto res3_time = base::TimeTicks::FromInternalValue(4);
URLRequestSummary main_frame =
CreateURLRequestSummary(1, "http://www.google.com");
collector_->RecordURLRequest(main_frame);
EXPECT_EQ(1U, collector_->inflight_navigations_.size());
URLRequestSummary resource1 = CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/style1.css",
content::RESOURCE_TYPE_STYLESHEET, net::MEDIUM, "text/css", false);
resource1.response_time = res1_time;
collector_->RecordURLResponse(resource1);
URLRequestSummary resource2 = CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script1.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", false);
resource2.response_time = res2_time;
collector_->RecordURLResponse(resource2);
URLRequestSummary resource3 = CreateURLRequestSummary(
1, "http://www.google.com", "http://google.com/script2.js",
content::RESOURCE_TYPE_SCRIPT, net::MEDIUM, "text/javascript", false);
resource3.response_time = res3_time;
collector_->RecordURLResponse(resource3);
collector_->RecordFirstContentfulPaint(main_frame.navigation_id, fcp_time);
// Since res3_time is after fcp_time, we expect this field to have been set to
// false before RecordPageRequestSummary is called.
resource3.before_first_contentful_paint = false;
EXPECT_CALL(
*mock_predictor_,
RecordPageRequestSummaryProxy(testing::Pointee(CreatePageRequestSummary(
"http://www.google.com", "http://www.google.com",
{resource1, resource2, resource3}))));
collector_->RecordMainFrameLoadComplete(main_frame.navigation_id);
}
} // namespace predictors