Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc

Issue 2519963002: predictors: Add browsertest that checks redirects. (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 #include "chrome/browser/predictors/resource_prefetch_predictor.h" 6 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
7 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h" 7 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
8 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h" 8 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h"
9 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h" 11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h" 12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/in_process_browser_test.h" 13 #include "chrome/test/base/in_process_browser_test.h"
14 #include "chrome/test/base/ui_test_utils.h" 14 #include "chrome/test/base/ui_test_utils.h"
15 #include "content/public/browser/render_frame_host.h" 15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/render_process_host.h" 16 #include "content/public/browser/render_process_host.h"
17 #include "net/test/embedded_test_server/http_request.h" 17 #include "net/test/embedded_test_server/http_request.h"
18 #include "net/test/embedded_test_server/http_response.h" 18 #include "net/test/embedded_test_server/http_response.h"
19 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
21 21
22 namespace predictors { 22 namespace predictors {
23 23
24 static const char kImageUrl[] = "/predictors/image.png"; 24 static const char kImagePath[] = "/predictors/image.png";
25 static const char kStyleUrl[] = "/predictors/style.css"; 25 static const char kStylePath[] = "/predictors/style.css";
26 static const char kScriptUrl[] = "/predictors/script.js"; 26 static const char kScriptPath[] = "/predictors/script.js";
27 static const char kFontUrl[] = "/predictors/font.ttf"; 27 static const char kFontPath[] = "/predictors/font.ttf";
28 static const char kHtmlSubresourcesUrl[] = "/predictors/html_subresources.html"; 28 static const char kHtmlSubresourcesPath[] =
29 "/predictors/html_subresources.html";
30 static const char kRedirectPath[] = "/predictors/redirect.html";
31 static const char kRedirectPath2[] = "/predictors/redirect2.html";
32 static const char kRedirectPath3[] = "/predictors/redirect3.html";
29 33
30 struct ResourceSummary { 34 struct ResourceSummary {
31 ResourceSummary() : is_no_store(false), version(0) {} 35 ResourceSummary() : is_no_store(false), version(0) {}
32 36
33 ResourcePrefetchPredictor::URLRequestSummary request; 37 ResourcePrefetchPredictor::URLRequestSummary request;
34 std::string content; 38 std::string content;
35 bool is_no_store; 39 bool is_no_store;
36 size_t version; 40 size_t version;
37 }; 41 };
38 42
43 struct RedirectEdge {
44 net::HttpStatusCode code;
45 GURL url;
46 };
47
39 class InitializationObserver : public TestObserver { 48 class InitializationObserver : public TestObserver {
40 public: 49 public:
41 explicit InitializationObserver(ResourcePrefetchPredictor* predictor) 50 explicit InitializationObserver(ResourcePrefetchPredictor* predictor)
42 : TestObserver(predictor) {} 51 : TestObserver(predictor) {}
43 52
44 void OnPredictorInitialized() override { run_loop_.Quit(); } 53 void OnPredictorInitialized() override { run_loop_.Quit(); }
45 54
46 void Wait() { run_loop_.Run(); } 55 void Wait() { run_loop_.Run(); }
47 56
48 private: 57 private:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 public: 101 public:
93 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 102 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
94 103
95 void SetUpCommandLine(base::CommandLine* command_line) override { 104 void SetUpCommandLine(base::CommandLine* command_line) override {
96 command_line->AppendSwitchASCII( 105 command_line->AppendSwitchASCII(
97 switches::kSpeculativeResourcePrefetching, 106 switches::kSpeculativeResourcePrefetching,
98 switches::kSpeculativeResourcePrefetchingEnabled); 107 switches::kSpeculativeResourcePrefetchingEnabled);
99 } 108 }
100 109
101 void SetUpOnMainThread() override { 110 void SetUpOnMainThread() override {
102 embedded_test_server()->RegisterRequestHandler( 111 embedded_test_server()->RegisterRequestHandler(base::Bind(
103 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRequest, 112 &ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest,
104 base::Unretained(this))); 113 base::Unretained(this), base::Unretained(embedded_test_server())));
114 embedded_test_server()->RegisterRequestHandler(base::Bind(
115 &ResourcePrefetchPredictorBrowserTest::HandleResourceRequest,
116 base::Unretained(this), base::Unretained(embedded_test_server())));
105 ASSERT_TRUE(embedded_test_server()->Start()); 117 ASSERT_TRUE(embedded_test_server()->Start());
106 predictor_ = 118 predictor_ =
107 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile()); 119 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile());
108 ASSERT_TRUE(predictor_); 120 ASSERT_TRUE(predictor_);
109 EnsurePredictorInitialized(); 121 EnsurePredictorInitialized();
110 } 122 }
111 123
112 void NavigateToURLAndCheckSubresources( 124 void NavigateToURLAndCheckSubresources(const GURL& main_frame_url) {
113 const std::string& main_frame_relative) { 125 GURL endpoint_url = GetRedirectEndpoint(main_frame_url);
114 GURL main_frame_absolute =
115 embedded_test_server()->GetURL(main_frame_relative);
116 std::vector<URLRequestSummary> url_request_summaries; 126 std::vector<URLRequestSummary> url_request_summaries;
117 for (const auto& kv : resources_) { 127 for (const auto& kv : resources_) {
118 if (kv.second.is_no_store) 128 if (kv.second.is_no_store)
119 continue; 129 continue;
120 url_request_summaries.push_back( 130 url_request_summaries.push_back(
121 GetURLRequestSummaryForResource(main_frame_absolute, kv.second)); 131 GetURLRequestSummaryForResource(endpoint_url, kv.second));
122 } 132 }
123 ResourcePrefetchPredictorTestObserver observer( 133 ResourcePrefetchPredictorTestObserver observer(
124 predictor_, UpdateAndGetVisitCount(main_frame_relative), 134 predictor_, UpdateAndGetVisitCount(main_frame_url),
125 CreatePageRequestSummary(main_frame_absolute.spec(), 135 CreatePageRequestSummary(endpoint_url.spec(), main_frame_url.spec(),
126 main_frame_absolute.spec(),
127 url_request_summaries)); 136 url_request_summaries));
128 ui_test_utils::NavigateToURL(browser(), main_frame_absolute); 137 ui_test_utils::NavigateToURL(browser(), main_frame_url);
129 observer.Wait(); 138 observer.Wait();
130 } 139 }
131 140
132 ResourceSummary* AddResource(const std::string& relative_url, 141 ResourceSummary* AddResource(const GURL& resource_url,
133 content::ResourceType resource_type, 142 content::ResourceType resource_type,
134 net::RequestPriority priority) { 143 net::RequestPriority priority) {
135 ResourceSummary resource; 144 ResourceSummary resource;
136 resource.request.resource_url = 145 resource.request.resource_url = resource_url;
137 embedded_test_server()->GetURL(relative_url);
138 resource.request.resource_type = resource_type; 146 resource.request.resource_type = resource_type;
139 resource.request.priority = priority; 147 resource.request.priority = priority;
140 auto result = resources_.insert(std::make_pair(relative_url, resource)); 148 resource.request.has_validators = true;
149 auto result = resources_.insert(std::make_pair(resource_url, resource));
141 return &(result.first->second); 150 return &(result.first->second);
142 } 151 }
143 152
153 void AddRedirectChain(const GURL& initial_url,
154 const std::vector<RedirectEdge>& redirect_chain) {
155 ASSERT_FALSE(redirect_chain.empty());
156 const GURL* current = &initial_url;
Benoit L 2016/11/22 10:58:28 Per offline discussion, this is slightly convolute
alexilin 2016/11/22 11:04:29 Done.
157 for (const auto& edge : redirect_chain) {
158 auto result = redirects_.insert(std::make_pair(*current, edge));
159 ASSERT_TRUE(result.second) << *current << " already has a redirect.";
160 current = &(edge.url);
161 }
162 }
163
164 // Simply shortcut for convenience.
Benoit L 2016/11/22 10:58:28 nit: s/Simply//
alexilin 2016/11/22 11:04:29 Done.
165 GURL GetURL(const std::string& path) const {
166 return embedded_test_server()->GetURL(path);
167 }
168
169 void EnableHttpsServer() {
170 ASSERT_FALSE(https_server_);
171 https_server_ = base::MakeUnique<net::EmbeddedTestServer>(
172 net::EmbeddedTestServer::TYPE_HTTPS);
173 https_server()->AddDefaultHandlers(
174 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
175 https_server()->RegisterRequestHandler(
176 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest,
177 base::Unretained(this), base::Unretained(https_server())));
178 https_server()->RegisterRequestHandler(
179 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest,
180 base::Unretained(this), base::Unretained(https_server())));
181 ASSERT_TRUE(https_server()->Start());
182 }
183
184 protected:
185 // Returns the embedded test server working over HTTPS. Must be enabled by
186 // calling EnableHttpsServer() before use.
187 const net::EmbeddedTestServer* https_server() const {
188 return https_server_.get();
189 }
190
191 net::EmbeddedTestServer* https_server() { return https_server_.get(); }
192
144 private: 193 private:
145 // ResourcePrefetchPredictor needs to be initialized before the navigation 194 // ResourcePrefetchPredictor needs to be initialized before the navigation
146 // happens otherwise this navigation will be ignored by predictor. 195 // happens otherwise this navigation will be ignored by predictor.
147 void EnsurePredictorInitialized() { 196 void EnsurePredictorInitialized() {
148 if (predictor_->initialization_state_ == 197 if (predictor_->initialization_state_ ==
149 ResourcePrefetchPredictor::INITIALIZED) { 198 ResourcePrefetchPredictor::INITIALIZED) {
150 return; 199 return;
151 } 200 }
152 201
153 InitializationObserver observer(predictor_); 202 InitializationObserver observer(predictor_);
154 if (predictor_->initialization_state_ == 203 if (predictor_->initialization_state_ ==
155 ResourcePrefetchPredictor::NOT_INITIALIZED) { 204 ResourcePrefetchPredictor::NOT_INITIALIZED) {
156 predictor_->StartInitialization(); 205 predictor_->StartInitialization();
157 } 206 }
158 observer.Wait(); 207 observer.Wait();
159 } 208 }
160 209
161 URLRequestSummary GetURLRequestSummaryForResource( 210 URLRequestSummary GetURLRequestSummaryForResource(
162 const GURL& main_frame_url, 211 const GURL& main_frame_url,
163 const ResourceSummary& resource_summary) { 212 const ResourceSummary& resource_summary) const {
164 URLRequestSummary summary(resource_summary.request); 213 URLRequestSummary summary(resource_summary.request);
165 content::WebContents* web_contents = 214 content::WebContents* web_contents =
166 browser()->tab_strip_model()->GetActiveWebContents(); 215 browser()->tab_strip_model()->GetActiveWebContents();
167 int process_id = web_contents->GetRenderProcessHost()->GetID(); 216 int process_id = web_contents->GetRenderProcessHost()->GetID();
168 int frame_id = web_contents->GetMainFrame()->GetRoutingID(); 217 int frame_id = web_contents->GetMainFrame()->GetRoutingID();
169 summary.navigation_id = 218 summary.navigation_id =
170 CreateNavigationID(process_id, frame_id, main_frame_url.spec()); 219 CreateNavigationID(process_id, frame_id, main_frame_url.spec());
171 return summary; 220 return summary;
172 } 221 }
173 222
174 std::unique_ptr<net::test_server::HttpResponse> HandleRequest( 223 GURL GetRedirectEndpoint(const GURL& initial_url) const {
175 const net::test_server::HttpRequest& request) { 224 const GURL* current = &initial_url;
176 auto resource_it = resources_.find(request.relative_url); 225 for (auto it = redirects_.find(*current); it != redirects_.end();
226 it = redirects_.find(*current)) {
227 current = &(it->second.url);
228 }
229 return *current;
230 }
231
232 std::unique_ptr<net::test_server::HttpResponse> HandleResourceRequest(
233 const net::test_server::EmbeddedTestServer* server,
234 const net::test_server::HttpRequest& request) const {
235 auto resource_it = resources_.find(server->GetURL(request.relative_url));
177 if (resource_it == resources_.end()) 236 if (resource_it == resources_.end())
178 return nullptr; 237 return nullptr;
179 238
180 const ResourceSummary& summary = resource_it->second; 239 const ResourceSummary& summary = resource_it->second;
181 auto http_response = 240 auto http_response =
182 base::MakeUnique<net::test_server::BasicHttpResponse>(); 241 base::MakeUnique<net::test_server::BasicHttpResponse>();
183 http_response->set_code(net::HTTP_OK); 242 http_response->set_code(net::HTTP_OK);
184 if (!summary.request.mime_type.empty()) 243 if (!summary.request.mime_type.empty())
185 http_response->set_content_type(summary.request.mime_type); 244 http_response->set_content_type(summary.request.mime_type);
186 http_response->set_content(summary.content); 245 if (!summary.content.empty())
246 http_response->set_content(summary.content);
187 if (summary.is_no_store) 247 if (summary.is_no_store)
188 http_response->AddCustomHeader("Cache-Control", "no-store"); 248 http_response->AddCustomHeader("Cache-Control", "no-store");
189 if (summary.request.has_validators) { 249 if (summary.request.has_validators) {
190 http_response->AddCustomHeader( 250 http_response->AddCustomHeader(
191 "ETag", base::StringPrintf("'%zu%s'", summary.version, 251 "ETag", base::StringPrintf("'%zu%s'", summary.version,
192 request.relative_url.c_str())); 252 request.relative_url.c_str()));
193 } 253 }
194 if (summary.request.always_revalidate) 254 if (summary.request.always_revalidate)
195 http_response->AddCustomHeader("Cache-Control", "no-cache"); 255 http_response->AddCustomHeader("Cache-Control", "no-cache");
196 else 256 else
197 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648"); 257 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648");
198 return std::move(http_response); 258 return std::move(http_response);
199 } 259 }
200 260
201 size_t UpdateAndGetVisitCount(const std::string& main_frame_relative) { 261 std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
202 return ++visit_count_[main_frame_relative]; 262 const net::test_server::EmbeddedTestServer* server,
263 const net::test_server::HttpRequest& request) const {
264 auto redirect_it = redirects_.find(server->GetURL(request.relative_url));
265 if (redirect_it == redirects_.end())
266 return nullptr;
267
268 auto http_response =
269 base::MakeUnique<net::test_server::BasicHttpResponse>();
270 http_response->set_code(redirect_it->second.code);
271 http_response->AddCustomHeader("Location", redirect_it->second.url.spec());
272 return std::move(http_response);
273 }
274
275 size_t UpdateAndGetVisitCount(const GURL& main_frame_url) {
276 return ++visit_count_[main_frame_url];
203 } 277 }
204 278
205 ResourcePrefetchPredictor* predictor_; 279 ResourcePrefetchPredictor* predictor_;
206 std::map<std::string, ResourceSummary> resources_; 280 std::unique_ptr<net::EmbeddedTestServer> https_server_;
207 std::map<std::string, size_t> visit_count_; 281 std::map<GURL, ResourceSummary> resources_;
282 std::map<GURL, RedirectEdge> redirects_;
283 std::map<GURL, size_t> visit_count_;
208 }; 284 };
209 285
210 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, LearningSimple) { 286 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, LearningSimple) {
211 // These resources have default priorities that correspond to 287 // These resources have default priorities that correspond to
212 // blink::typeToPriority function. 288 // blink::typeToPriority function.
213 AddResource(kImageUrl, content::RESOURCE_TYPE_IMAGE, net::LOWEST); 289 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
214 AddResource(kStyleUrl, content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); 290 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET,
215 AddResource(kScriptUrl, content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); 291 net::HIGHEST);
216 AddResource(kFontUrl, content::RESOURCE_TYPE_FONT_RESOURCE, net::HIGHEST); 292 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
217 NavigateToURLAndCheckSubresources(kHtmlSubresourcesUrl); 293 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE,
294 net::HIGHEST);
295 NavigateToURLAndCheckSubresources(GetURL(kHtmlSubresourcesPath));
296 }
297
298 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
299 LearningAfterRedirect) {
300 AddRedirectChain(GetURL(kRedirectPath), {{net::HTTP_MOVED_PERMANENTLY,
301 GetURL(kHtmlSubresourcesPath)}});
302 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
303 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET,
304 net::HIGHEST);
305 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
306 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE,
307 net::HIGHEST);
308 NavigateToURLAndCheckSubresources(GetURL(kRedirectPath));
309 }
310
311 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
312 LearningAfterRedirectChain) {
313 AddRedirectChain(GetURL(kRedirectPath),
314 {{net::HTTP_FOUND, GetURL(kRedirectPath2)},
315 {net::HTTP_MOVED_PERMANENTLY, GetURL(kRedirectPath3)},
316 {net::HTTP_FOUND, GetURL(kHtmlSubresourcesPath)}});
317 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
318 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET,
319 net::HIGHEST);
320 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
321 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE,
322 net::HIGHEST);
323 NavigateToURLAndCheckSubresources(GetURL(kRedirectPath));
324 }
325
326 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
327 LearningAfterHttpToHttpsRedirect) {
328 EnableHttpsServer();
329 AddRedirectChain(GetURL(kRedirectPath),
330 {{net::HTTP_FOUND, https_server()->GetURL(kRedirectPath2)},
331 {net::HTTP_MOVED_PERMANENTLY,
332 https_server()->GetURL(kHtmlSubresourcesPath)}});
333 AddResource(https_server()->GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE,
334 net::LOWEST);
335 AddResource(https_server()->GetURL(kStylePath),
336 content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST);
337 AddResource(https_server()->GetURL(kScriptPath),
338 content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
339 AddResource(https_server()->GetURL(kFontPath),
340 content::RESOURCE_TYPE_FONT_RESOURCE, net::HIGHEST);
341 NavigateToURLAndCheckSubresources(GetURL(kRedirectPath));
218 } 342 }
219 343
220 } // namespace predictors 344 } // namespace predictors
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698