OLD | NEW |
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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 const char kHtmlAppendChildPath[] = "/predictors/append_child.html"; | 58 const char kHtmlAppendChildPath[] = "/predictors/append_child.html"; |
59 const char kScriptAppendChildPath[] = "/predictors/append_child.js"; | 59 const char kScriptAppendChildPath[] = "/predictors/append_child.js"; |
60 const char kHtmlInnerHtmlPath[] = "/predictors/inner_html.html"; | 60 const char kHtmlInnerHtmlPath[] = "/predictors/inner_html.html"; |
61 const char kScriptInnerHtmlPath[] = "/predictors/inner_html.js"; | 61 const char kScriptInnerHtmlPath[] = "/predictors/inner_html.js"; |
62 const char kHtmlXHRPath[] = "/predictors/xhr.html"; | 62 const char kHtmlXHRPath[] = "/predictors/xhr.html"; |
63 const char kScriptXHRPath[] = "/predictors/xhr.js"; | 63 const char kScriptXHRPath[] = "/predictors/xhr.js"; |
64 const char kHtmlIframePath[] = "/predictors/html_iframe.html"; | 64 const char kHtmlIframePath[] = "/predictors/html_iframe.html"; |
65 | 65 |
66 struct ResourceSummary { | 66 struct ResourceSummary { |
67 ResourceSummary() | 67 ResourceSummary() |
68 : is_no_store(false), | 68 : version(0), |
69 version(0), | 69 is_no_store(false), |
70 is_external(false), | 70 is_external(false), |
71 should_be_recorded(true) {} | 71 is_observable(true), |
| 72 is_prohibited(false) {} |
72 | 73 |
73 ResourcePrefetchPredictor::URLRequestSummary request; | 74 ResourcePrefetchPredictor::URLRequestSummary request; |
74 std::string content; | 75 std::string content; |
| 76 // Allows to update HTTP ETag. |
| 77 size_t version; |
| 78 // True iff "Cache-control: no-store" header is present. |
75 bool is_no_store; | 79 bool is_no_store; |
76 size_t version; | 80 // True iff a request for this resource must be ignored by the custom handler. |
77 bool is_external; | 81 bool is_external; |
78 bool should_be_recorded; | 82 // True iff the LearningObserver must observe this resource. |
| 83 bool is_observable; |
| 84 // A request with |is_prohibited| set to true makes the test that originates |
| 85 // the request fail. |
| 86 bool is_prohibited; |
79 }; | 87 }; |
80 | 88 |
81 struct RedirectEdge { | 89 struct RedirectEdge { |
82 // This response code should be returned by previous url in the chain. | 90 // This response code should be returned by previous url in the chain. |
83 net::HttpStatusCode code; | 91 net::HttpStatusCode code; |
84 GURL url; | 92 GURL url; |
85 }; | 93 }; |
86 | 94 |
87 // Helper class to track and allow waiting for ResourcePrefetchPredictor | 95 // Helper class to track and allow waiting for ResourcePrefetchPredictor |
88 // initialization. WARNING: OnPredictorInitialized event will not be fired if | 96 // initialization. WARNING: OnPredictorInitialized event will not be fired if |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 176 |
169 for (auto& subresource : actual_subresources) | 177 for (auto& subresource : actual_subresources) |
170 ModifySubresourceForComparison(&subresource, match_navigation_id); | 178 ModifySubresourceForComparison(&subresource, match_navigation_id); |
171 for (auto& subresource : expected_subresources) | 179 for (auto& subresource : expected_subresources) |
172 ModifySubresourceForComparison(&subresource, match_navigation_id); | 180 ModifySubresourceForComparison(&subresource, match_navigation_id); |
173 | 181 |
174 EXPECT_THAT(actual_subresources, | 182 EXPECT_THAT(actual_subresources, |
175 testing::UnorderedElementsAreArray(expected_subresources)); | 183 testing::UnorderedElementsAreArray(expected_subresources)); |
176 } | 184 } |
177 | 185 |
| 186 std::string CreateVersionedETag(size_t version, const std::string& path) { |
| 187 return base::StringPrintf("'%zu%s'", version, path.c_str()); |
| 188 } |
| 189 |
178 } // namespace | 190 } // namespace |
179 | 191 |
180 // Helper class to track and allow waiting for a single OnNavigationLearned | 192 // Helper class to track and allow waiting for a single OnNavigationLearned |
181 // event. The information provided by this event is also used to verify that | 193 // event. The information provided by this event is also used to verify that |
182 // ResourcePrefetchPredictor works as expected. | 194 // ResourcePrefetchPredictor works as expected. |
183 class LearningObserver : public TestObserver { | 195 class LearningObserver : public TestObserver { |
184 public: | 196 public: |
185 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; | 197 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; |
186 | 198 |
187 LearningObserver(ResourcePrefetchPredictor* predictor, | 199 LearningObserver(ResourcePrefetchPredictor* predictor, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 void SetUpOnMainThread() override { | 275 void SetUpOnMainThread() override { |
264 // Resolving all hosts to local allows us to have | 276 // Resolving all hosts to local allows us to have |
265 // cross domains navigations (matching url_visit_count_, etc). | 277 // cross domains navigations (matching url_visit_count_, etc). |
266 host_resolver()->AddRule("*", "127.0.0.1"); | 278 host_resolver()->AddRule("*", "127.0.0.1"); |
267 embedded_test_server()->RegisterRequestHandler( | 279 embedded_test_server()->RegisterRequestHandler( |
268 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest, | 280 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest, |
269 base::Unretained(this))); | 281 base::Unretained(this))); |
270 embedded_test_server()->RegisterRequestHandler( | 282 embedded_test_server()->RegisterRequestHandler( |
271 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest, | 283 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest, |
272 base::Unretained(this))); | 284 base::Unretained(this))); |
| 285 embedded_test_server()->RegisterRequestMonitor(base::Bind( |
| 286 &ResourcePrefetchPredictorBrowserTest::MonitorResourceRequest, |
| 287 base::Unretained(this))); |
273 ASSERT_TRUE(embedded_test_server()->Start()); | 288 ASSERT_TRUE(embedded_test_server()->Start()); |
274 predictor_ = | 289 predictor_ = |
275 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile()); | 290 ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile()); |
276 ASSERT_TRUE(predictor_); | 291 ASSERT_TRUE(predictor_); |
277 EnsurePredictorInitialized(); | 292 EnsurePredictorInitialized(); |
278 } | 293 } |
279 | 294 |
280 void TestLearningAndPrefetching(const GURL& main_frame_url) { | 295 void TestLearningAndPrefetching(const GURL& main_frame_url) { |
281 // Navigate to |main_frame_url| and check all the expectations. | 296 // Navigate to |main_frame_url| and check all the expectations. |
282 NavigateToURLAndCheckSubresources(main_frame_url); | 297 NavigateToURLAndCheckSubresources(main_frame_url); |
283 ClearCache(); | 298 ClearCache(); |
284 // It is needed to have at least two resource hits to trigger prefetch. | 299 // It is needed to have at least two resource hits to trigger prefetch. |
285 NavigateToURLAndCheckSubresources(main_frame_url); | 300 NavigateToURLAndCheckSubresources(main_frame_url); |
286 ClearCache(); | 301 ClearCache(); |
287 // Prefetch all needed resources and change expectations so that all | 302 // Prefetch all needed resources and change expectations so that all |
288 // cacheable resources should be served from cache next navigation. | 303 // cacheable resources should be served from cache next navigation. |
289 PrefetchURL(main_frame_url); | 304 PrefetchURL(main_frame_url); |
| 305 // To be sure that the browser send no requests to the server after |
| 306 // prefetching. |
| 307 for (auto& kv : resources_) { |
| 308 if (kv.second.is_observable) |
| 309 kv.second.is_prohibited = true; |
| 310 } |
290 NavigateToURLAndCheckSubresources(main_frame_url); | 311 NavigateToURLAndCheckSubresources(main_frame_url); |
| 312 for (auto& kv : resources_) { |
| 313 if (kv.second.is_observable) |
| 314 kv.second.is_prohibited = false; |
| 315 } |
291 } | 316 } |
292 | 317 |
293 void NavigateToURLAndCheckSubresources( | 318 void NavigateToURLAndCheckSubresources( |
294 const GURL& main_frame_url, | 319 const GURL& main_frame_url, |
295 WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB) { | 320 WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB) { |
296 GURL endpoint_url = GetRedirectEndpoint(main_frame_url); | 321 GURL endpoint_url = GetRedirectEndpoint(main_frame_url); |
297 std::vector<URLRequestSummary> url_request_summaries; | 322 std::vector<URLRequestSummary> url_request_summaries; |
298 for (const auto& kv : resources_) { | 323 for (const auto& kv : resources_) { |
299 if (kv.second.is_no_store || !kv.second.should_be_recorded) | 324 if (kv.second.is_observable) { |
300 continue; | 325 url_request_summaries.push_back( |
301 url_request_summaries.push_back( | 326 GetURLRequestSummaryForResource(endpoint_url, kv.second)); |
302 GetURLRequestSummaryForResource(endpoint_url, kv.second)); | 327 } |
303 } | 328 } |
304 | 329 |
305 bool match_navigation_id = | 330 bool match_navigation_id = |
306 disposition == WindowOpenDisposition::CURRENT_TAB; | 331 disposition == WindowOpenDisposition::CURRENT_TAB; |
307 | 332 |
308 LearningObserver observer( | 333 LearningObserver observer( |
309 predictor_, UpdateAndGetVisitCount(main_frame_url), | 334 predictor_, UpdateAndGetVisitCount(main_frame_url), |
310 CreatePageRequestSummary(endpoint_url.spec(), main_frame_url.spec(), | 335 CreatePageRequestSummary(endpoint_url.spec(), main_frame_url.spec(), |
311 url_request_summaries), | 336 url_request_summaries), |
312 match_navigation_id); | 337 match_navigation_id); |
313 ui_test_utils::NavigateToURLWithDisposition( | 338 ui_test_utils::NavigateToURLWithDisposition( |
314 browser(), main_frame_url, disposition, | 339 browser(), main_frame_url, disposition, |
315 ui_test_utils::BROWSER_TEST_NONE); | 340 ui_test_utils::BROWSER_TEST_NONE); |
316 observer.Wait(); | 341 observer.Wait(); |
317 for (auto& kv : resources_) { | 342 for (auto& kv : resources_) { |
318 if (!kv.second.is_no_store && kv.second.should_be_recorded) | 343 if (kv.second.is_observable) |
319 kv.second.request.was_cached = true; | 344 kv.second.request.was_cached = true; |
320 } | 345 } |
321 for (const auto& nav : observer.current_navigation_ids()) | 346 for (const auto& nav : observer.current_navigation_ids()) |
322 navigation_id_history_.insert(nav); | 347 navigation_id_history_.insert(nav); |
323 } | 348 } |
324 | 349 |
325 void PrefetchURL(const GURL& main_frame_url) { | 350 void PrefetchURL(const GURL& main_frame_url) { |
326 PrefetchingObserver observer(predictor_, main_frame_url); | 351 PrefetchingObserver observer(predictor_, main_frame_url); |
327 predictor_->StartPrefetching(main_frame_url, PrefetchOrigin::EXTERNAL); | 352 predictor_->StartPrefetching(main_frame_url, PrefetchOrigin::EXTERNAL); |
328 observer.Wait(); | 353 observer.Wait(); |
329 for (auto& kv : resources_) { | 354 for (auto& kv : resources_) { |
330 if (!kv.second.is_no_store && kv.second.should_be_recorded) | 355 if (kv.second.is_observable) |
331 kv.second.request.was_cached = true; | 356 kv.second.request.was_cached = true; |
332 } | 357 } |
333 } | 358 } |
334 | 359 |
335 ResourceSummary* AddResource(const GURL& resource_url, | 360 ResourceSummary* AddResource(const GURL& resource_url, |
336 content::ResourceType resource_type, | 361 content::ResourceType resource_type, |
337 net::RequestPriority priority) { | 362 net::RequestPriority priority) { |
338 auto pair_and_whether_inserted = | 363 auto pair_and_whether_inserted = |
339 resources_.insert(std::make_pair(resource_url, ResourceSummary())); | 364 resources_.insert(std::make_pair(resource_url, ResourceSummary())); |
340 EXPECT_TRUE(pair_and_whether_inserted.second) << resource_url | 365 EXPECT_TRUE(pair_and_whether_inserted.second) << resource_url |
341 << " was inserted twice"; | 366 << " was inserted twice"; |
342 ResourceSummary* resource = &pair_and_whether_inserted.first->second; | 367 ResourceSummary* resource = &pair_and_whether_inserted.first->second; |
343 resource->request.resource_url = resource_url; | 368 resource->request.resource_url = resource_url; |
344 resource->request.resource_type = resource_type; | 369 resource->request.resource_type = resource_type; |
345 resource->request.priority = priority; | 370 resource->request.priority = priority; |
346 resource->request.has_validators = true; | 371 resource->request.has_validators = true; |
347 return resource; | 372 return resource; |
348 } | 373 } |
349 | 374 |
350 ResourceSummary* AddExternalResource(const GURL& resource_url, | 375 ResourceSummary* AddExternalResource(const GURL& resource_url, |
351 content::ResourceType resource_type, | 376 content::ResourceType resource_type, |
352 net::RequestPriority priority) { | 377 net::RequestPriority priority) { |
353 auto resource = AddResource(resource_url, resource_type, priority); | 378 auto resource = AddResource(resource_url, resource_type, priority); |
354 resource->is_external = true; | 379 resource->is_external = true; |
355 return resource; | 380 return resource; |
356 } | 381 } |
357 | 382 |
358 void AddUnrecordedResources(const std::vector<GURL>& resource_urls) { | 383 void AddUnobservableResources(const std::vector<GURL>& resource_urls) { |
359 for (const GURL& resource_url : resource_urls) { | 384 for (const GURL& resource_url : resource_urls) { |
360 auto resource = | 385 auto resource = |
361 AddResource(resource_url, content::RESOURCE_TYPE_SUB_RESOURCE, | 386 AddResource(resource_url, content::RESOURCE_TYPE_SUB_RESOURCE, |
362 net::DEFAULT_PRIORITY); | 387 net::DEFAULT_PRIORITY); |
363 resource->should_be_recorded = false; | 388 resource->is_observable = false; |
364 } | 389 } |
365 } | 390 } |
366 | 391 |
367 void AddRedirectChain(const GURL& initial_url, | 392 void AddRedirectChain(const GURL& initial_url, |
368 const std::vector<RedirectEdge>& redirect_chain) { | 393 const std::vector<RedirectEdge>& redirect_chain) { |
369 ASSERT_FALSE(redirect_chain.empty()); | 394 ASSERT_FALSE(redirect_chain.empty()); |
370 GURL current = initial_url; | 395 GURL current = initial_url; |
371 for (const auto& edge : redirect_chain) { | 396 for (const auto& edge : redirect_chain) { |
372 auto result = redirects_.insert(std::make_pair(current, edge)); | 397 auto result = redirects_.insert(std::make_pair(current, edge)); |
373 EXPECT_TRUE(result.second) << current << " already has a redirect."; | 398 EXPECT_TRUE(result.second) << current << " already has a redirect."; |
(...skipping 26 matching lines...) Expand all Loading... |
400 https_server_ = base::MakeUnique<net::EmbeddedTestServer>( | 425 https_server_ = base::MakeUnique<net::EmbeddedTestServer>( |
401 net::EmbeddedTestServer::TYPE_HTTPS); | 426 net::EmbeddedTestServer::TYPE_HTTPS); |
402 https_server()->AddDefaultHandlers( | 427 https_server()->AddDefaultHandlers( |
403 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); | 428 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); |
404 https_server()->RegisterRequestHandler( | 429 https_server()->RegisterRequestHandler( |
405 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest, | 430 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleRedirectRequest, |
406 base::Unretained(this))); | 431 base::Unretained(this))); |
407 https_server()->RegisterRequestHandler( | 432 https_server()->RegisterRequestHandler( |
408 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest, | 433 base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest, |
409 base::Unretained(this))); | 434 base::Unretained(this))); |
| 435 https_server()->RegisterRequestMonitor(base::Bind( |
| 436 &ResourcePrefetchPredictorBrowserTest::MonitorResourceRequest, |
| 437 base::Unretained(this))); |
410 ASSERT_TRUE(https_server()->Start()); | 438 ASSERT_TRUE(https_server()->Start()); |
411 } | 439 } |
412 | 440 |
413 // Returns the embedded test server working over HTTPS. Must be enabled by | 441 // Returns the embedded test server working over HTTPS. Must be enabled by |
414 // calling EnableHttpsServer() before use. | 442 // calling EnableHttpsServer() before use. |
415 const net::EmbeddedTestServer* https_server() const { | 443 const net::EmbeddedTestServer* https_server() const { |
416 return https_server_.get(); | 444 return https_server_.get(); |
417 } | 445 } |
418 | 446 |
419 net::EmbeddedTestServer* https_server() { return https_server_.get(); } | 447 net::EmbeddedTestServer* https_server() { return https_server_.get(); } |
(...skipping 26 matching lines...) Expand all Loading... |
446 content::WebContents* web_contents = | 474 content::WebContents* web_contents = |
447 browser()->tab_strip_model()->GetActiveWebContents(); | 475 browser()->tab_strip_model()->GetActiveWebContents(); |
448 summary.navigation_id = | 476 summary.navigation_id = |
449 NavigationID(web_contents, main_frame_url, base::TimeTicks::Now()); | 477 NavigationID(web_contents, main_frame_url, base::TimeTicks::Now()); |
450 return summary; | 478 return summary; |
451 } | 479 } |
452 | 480 |
453 GURL GetRedirectEndpoint(const GURL& initial_url) const { | 481 GURL GetRedirectEndpoint(const GURL& initial_url) const { |
454 GURL current = initial_url; | 482 GURL current = initial_url; |
455 while (true) { | 483 while (true) { |
456 auto it = redirects_.find(current); | 484 std::map<GURL, RedirectEdge>::const_iterator it = |
| 485 redirects_.find(current); |
457 if (it == redirects_.end()) | 486 if (it == redirects_.end()) |
458 break; | 487 break; |
459 current = it->second.url; | 488 current = it->second.url; |
460 } | 489 } |
461 return current; | 490 return current; |
462 } | 491 } |
463 | 492 |
| 493 void MonitorResourceRequest( |
| 494 const net::test_server::HttpRequest& request) const { |
| 495 std::map<GURL, ResourceSummary>::const_iterator resource_it = |
| 496 resources_.find(request.GetURL()); |
| 497 if (resource_it == resources_.end()) |
| 498 return; |
| 499 |
| 500 const ResourceSummary& summary = resource_it->second; |
| 501 EXPECT_FALSE(summary.is_prohibited) << request.GetURL() << "\n" |
| 502 << request.all_headers; |
| 503 } |
| 504 |
| 505 // The custom handler for resource requests from the browser to an |
| 506 // EmbeddedTestServer. Runs on the EmbeddedTestServer IO thread. |
| 507 // Finds the data to serve requests in |resources_| map keyed by a request |
| 508 // URL. |
| 509 // Uses also the following headers from the |request|: |
| 510 // - "Host" to retrieve the host that actually was issued by the browser. |
| 511 // - "If-None-Match" to determine if the resource is still valid. If the |
| 512 // ETag values match, the handler responds with a HTTP 304 status. |
464 std::unique_ptr<net::test_server::HttpResponse> HandleResourceRequest( | 513 std::unique_ptr<net::test_server::HttpResponse> HandleResourceRequest( |
465 const net::test_server::HttpRequest& request) const { | 514 const net::test_server::HttpRequest& request) const { |
466 GURL resource_url = request.GetURL(); | 515 GURL resource_url = request.GetURL(); |
467 // Retrieve the host that was used in the request because | 516 // Retrieve the host that was used in the request because |
468 // resource_url contains a resolved host (e.g. 127.0.0.1). | 517 // resource_url contains a resolved host (e.g. 127.0.0.1). |
469 if (request.headers.find("Host") != request.headers.end()) { | 518 if (request.headers.find("Host") != request.headers.end()) { |
470 auto host_port_pair = | 519 auto host_port_pair = |
471 net::HostPortPair::FromString(request.headers.at("Host")); | 520 net::HostPortPair::FromString(request.headers.at("Host")); |
472 GURL::Replacements replace_host; | 521 GURL::Replacements replace_host; |
473 replace_host.SetHostStr(host_port_pair.host()); | 522 replace_host.SetHostStr(host_port_pair.host()); |
474 resource_url = resource_url.ReplaceComponents(replace_host); | 523 resource_url = resource_url.ReplaceComponents(replace_host); |
475 } else { | 524 } else { |
476 ADD_FAILURE() << "Host header was not found in a HttpRequest to url: " | 525 ADD_FAILURE() << "Host header was not found in a HttpRequest to url: " |
477 << resource_url.spec(); | 526 << resource_url.spec(); |
478 } | 527 } |
479 | 528 |
480 auto resource_it = resources_.find(resource_url); | 529 std::map<GURL, ResourceSummary>::const_iterator resource_it = |
| 530 resources_.find(resource_url); |
481 if (resource_it == resources_.end()) | 531 if (resource_it == resources_.end()) |
482 return nullptr; | 532 return nullptr; |
483 | 533 |
484 const ResourceSummary& summary = resource_it->second; | 534 const ResourceSummary& summary = resource_it->second; |
485 if (summary.is_external) | 535 if (summary.is_external) |
486 return nullptr; | 536 return nullptr; |
487 | 537 |
488 auto http_response = | 538 auto http_response = |
489 base::MakeUnique<net::test_server::BasicHttpResponse>(); | 539 base::MakeUnique<net::test_server::BasicHttpResponse>(); |
490 http_response->set_code(net::HTTP_OK); | 540 |
| 541 if (request.headers.find("If-None-Match") != request.headers.end() && |
| 542 request.headers.at("If-None-Match") == |
| 543 CreateVersionedETag(summary.version, request.relative_url)) { |
| 544 http_response->set_code(net::HTTP_NOT_MODIFIED); |
| 545 } else { |
| 546 http_response->set_code(net::HTTP_OK); |
| 547 } |
| 548 |
491 if (!summary.request.mime_type.empty()) | 549 if (!summary.request.mime_type.empty()) |
492 http_response->set_content_type(summary.request.mime_type); | 550 http_response->set_content_type(summary.request.mime_type); |
493 if (!summary.content.empty()) | 551 if (!summary.content.empty()) |
494 http_response->set_content(summary.content); | 552 http_response->set_content(summary.content); |
495 if (summary.is_no_store) | 553 if (summary.is_no_store) |
496 http_response->AddCustomHeader("Cache-Control", "no-store"); | 554 http_response->AddCustomHeader("Cache-Control", "no-store"); |
497 if (summary.request.has_validators) { | 555 if (summary.request.has_validators) { |
498 http_response->AddCustomHeader( | 556 http_response->AddCustomHeader( |
499 "ETag", base::StringPrintf("'%zu%s'", summary.version, | 557 "ETag", CreateVersionedETag(summary.version, request.relative_url)); |
500 request.relative_url.c_str())); | |
501 } | 558 } |
502 if (summary.request.always_revalidate) | 559 if (summary.request.always_revalidate) |
503 http_response->AddCustomHeader("Cache-Control", "no-cache"); | 560 http_response->AddCustomHeader("Cache-Control", "no-cache"); |
504 else | 561 else |
505 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648"); | 562 http_response->AddCustomHeader("Cache-Control", "max-age=2147483648"); |
506 return std::move(http_response); | 563 return std::move(http_response); |
507 } | 564 } |
508 | 565 |
| 566 // The custom handler for redirect requests from the browser to an |
| 567 // EmbeddedTestServer. Running on the EmbeddedTestServer IO thread. |
| 568 // Finds the data to serve requests in |redirects_| map keyed by a request |
| 569 // URL. |
509 std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest( | 570 std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest( |
510 const net::test_server::HttpRequest& request) const { | 571 const net::test_server::HttpRequest& request) const { |
511 auto redirect_it = redirects_.find(request.GetURL()); | 572 std::map<GURL, RedirectEdge>::const_iterator redirect_it = |
| 573 redirects_.find(request.GetURL()); |
512 if (redirect_it == redirects_.end()) | 574 if (redirect_it == redirects_.end()) |
513 return nullptr; | 575 return nullptr; |
514 | 576 |
515 auto http_response = | 577 auto http_response = |
516 base::MakeUnique<net::test_server::BasicHttpResponse>(); | 578 base::MakeUnique<net::test_server::BasicHttpResponse>(); |
517 http_response->set_code(redirect_it->second.code); | 579 http_response->set_code(redirect_it->second.code); |
518 http_response->AddCustomHeader("Location", redirect_it->second.url.spec()); | 580 http_response->AddCustomHeader("Location", redirect_it->second.url.spec()); |
519 return std::move(http_response); | 581 return std::move(http_response); |
520 } | 582 } |
521 | 583 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, | 678 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, |
617 JavascriptInnerHtml) { | 679 JavascriptInnerHtml) { |
618 auto externalScript = AddExternalResource( | 680 auto externalScript = AddExternalResource( |
619 GetURL(kScriptInnerHtmlPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); | 681 GetURL(kScriptInnerHtmlPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); |
620 externalScript->request.mime_type = kJavascriptMime; | 682 externalScript->request.mime_type = kJavascriptMime; |
621 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST); | 683 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST); |
622 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET, | 684 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET, |
623 net::HIGHEST); | 685 net::HIGHEST); |
624 // https://www.w3.org/TR/2014/REC-html5-20141028/scripting-1.html#the-script-e
lement | 686 // https://www.w3.org/TR/2014/REC-html5-20141028/scripting-1.html#the-script-e
lement |
625 // Script elements don't execute when inserted using innerHTML attribute. | 687 // Script elements don't execute when inserted using innerHTML attribute. |
626 AddUnrecordedResources({GetURL(kScriptPath)}); | 688 AddUnobservableResources({GetURL(kScriptPath)}); |
627 TestLearningAndPrefetching(GetURL(kHtmlInnerHtmlPath)); | 689 TestLearningAndPrefetching(GetURL(kHtmlInnerHtmlPath)); |
628 } | 690 } |
629 | 691 |
630 // Requests originated by XMLHttpRequest have content::RESOURCE_TYPE_XHR. | 692 // Requests originated by XMLHttpRequest have content::RESOURCE_TYPE_XHR. |
631 // Actual resource type is inferred from the mime-type. | 693 // Actual resource type is inferred from the mime-type. |
632 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, JavascriptXHR) { | 694 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, JavascriptXHR) { |
633 auto externalScript = AddExternalResource( | 695 auto externalScript = AddExternalResource( |
634 GetURL(kScriptXHRPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); | 696 GetURL(kScriptXHRPath), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); |
635 externalScript->request.mime_type = kJavascriptMime; | 697 externalScript->request.mime_type = kJavascriptMime; |
636 auto image = AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, | 698 auto image = AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, |
637 net::HIGHEST); | 699 net::HIGHEST); |
638 image->request.mime_type = kImageMime; | 700 image->request.mime_type = kImageMime; |
639 auto style = AddResource(GetURL(kStylePath), | 701 auto style = AddResource(GetURL(kStylePath), |
640 content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); | 702 content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); |
641 style->request.mime_type = kStyleMime; | 703 style->request.mime_type = kStyleMime; |
642 auto script = AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, | 704 auto script = AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, |
643 net::HIGHEST); | 705 net::HIGHEST); |
644 script->request.mime_type = kJavascriptMime; | 706 script->request.mime_type = kJavascriptMime; |
645 TestLearningAndPrefetching(GetURL(kHtmlXHRPath)); | 707 TestLearningAndPrefetching(GetURL(kHtmlXHRPath)); |
646 } | 708 } |
647 | 709 |
648 // ResourcePrefetchPredictor ignores all resources requested from subframes. | 710 // ResourcePrefetchPredictor ignores all resources requested from subframes. |
649 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, | 711 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, |
650 IframeShouldBeIgnored) { | 712 IframeShouldBeIgnored) { |
651 // Included from html_iframe.html. | 713 // Included from html_iframe.html. |
652 AddResource(GetURL(kImagePath2), content::RESOURCE_TYPE_IMAGE, net::LOWEST); | 714 AddResource(GetURL(kImagePath2), content::RESOURCE_TYPE_IMAGE, net::LOWEST); |
653 AddResource(GetURL(kStylePath2), content::RESOURCE_TYPE_STYLESHEET, | 715 AddResource(GetURL(kStylePath2), content::RESOURCE_TYPE_STYLESHEET, |
654 net::HIGHEST); | 716 net::HIGHEST); |
655 AddResource(GetURL(kScriptPath2), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); | 717 AddResource(GetURL(kScriptPath2), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); |
656 // Included from <iframe src="html_subresources.html"> and not recored. | 718 // Included from <iframe src="html_subresources.html"> and shouldn't be |
657 AddUnrecordedResources({GetURL(kImagePath), GetURL(kStylePath), | 719 // observed. |
658 GetURL(kScriptPath), GetURL(kFontPath)}); | 720 AddUnobservableResources({GetURL(kImagePath), GetURL(kStylePath), |
| 721 GetURL(kScriptPath), GetURL(kFontPath)}); |
659 TestLearningAndPrefetching(GetURL(kHtmlIframePath)); | 722 TestLearningAndPrefetching(GetURL(kHtmlIframePath)); |
660 } | 723 } |
661 | 724 |
662 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, | 725 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, |
663 CrossSiteNavigation) { | 726 CrossSiteNavigation) { |
664 AddResource(embedded_test_server()->GetURL(kFooHost, kImagePath), | 727 AddResource(embedded_test_server()->GetURL(kFooHost, kImagePath), |
665 content::RESOURCE_TYPE_IMAGE, net::LOWEST); | 728 content::RESOURCE_TYPE_IMAGE, net::LOWEST); |
666 AddResource(embedded_test_server()->GetURL(kFooHost, kStylePath), | 729 AddResource(embedded_test_server()->GetURL(kFooHost, kStylePath), |
667 content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); | 730 content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); |
668 AddResource(embedded_test_server()->GetURL(kFooHost, kScriptPath), | 731 AddResource(embedded_test_server()->GetURL(kFooHost, kScriptPath), |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 ClearCache(); | 774 ClearCache(); |
712 NavigateToURLAndCheckSubresources(GetURL(kHtmlSubresourcesPath), | 775 NavigateToURLAndCheckSubresources(GetURL(kHtmlSubresourcesPath), |
713 WindowOpenDisposition::NEW_WINDOW); | 776 WindowOpenDisposition::NEW_WINDOW); |
714 EXPECT_EQ(navigation_ids_history_size(), 3U); | 777 EXPECT_EQ(navigation_ids_history_size(), 3U); |
715 ClearCache(); | 778 ClearCache(); |
716 NavigateToURLAndCheckSubresources(GetURL(kHtmlSubresourcesPath), | 779 NavigateToURLAndCheckSubresources(GetURL(kHtmlSubresourcesPath), |
717 WindowOpenDisposition::NEW_POPUP); | 780 WindowOpenDisposition::NEW_POPUP); |
718 EXPECT_EQ(navigation_ids_history_size(), 4U); | 781 EXPECT_EQ(navigation_ids_history_size(), 4U); |
719 } | 782 } |
720 | 783 |
| 784 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, AlwaysRevalidate) { |
| 785 std::vector<ResourceSummary*> resources = { |
| 786 AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, |
| 787 net::LOWEST), |
| 788 AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET, |
| 789 net::HIGHEST), |
| 790 AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, |
| 791 net::MEDIUM), |
| 792 AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE, |
| 793 net::HIGHEST), |
| 794 }; |
| 795 for (auto& resource : resources) |
| 796 resource->request.always_revalidate = true; |
| 797 TestLearningAndPrefetching(GetURL(kHtmlSubresourcesPath)); |
| 798 } |
| 799 |
721 } // namespace predictors | 800 } // namespace predictors |
OLD | NEW |