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

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

Issue 2937623007: predictors: Move more methods from ResourcePrefetchPredictor into LoadingDataCollector. (Closed)
Patch Set: Fix browser test Created 3 years, 5 months 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "chrome/browser/predictors/resource_prefetch_predictor.h" 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/rand_util.h" 14 #include "base/rand_util.h"
15 #include "base/time/time.h" 15 #include "base/time/time.h"
16 #include "base/trace_event/trace_event.h" 16 #include "base/trace_event/trace_event.h"
17 #include "chrome/browser/history/history_service_factory.h" 17 #include "chrome/browser/history/history_service_factory.h"
18 #include "chrome/browser/predictors/loading_data_collector.h"
18 #include "chrome/browser/predictors/loading_stats_collector.h" 19 #include "chrome/browser/predictors/loading_stats_collector.h"
19 #include "chrome/browser/predictors/predictor_database.h" 20 #include "chrome/browser/predictors/predictor_database.h"
20 #include "chrome/browser/predictors/predictor_database_factory.h" 21 #include "chrome/browser/predictors/predictor_database_factory.h"
21 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
22 #include "components/history/core/browser/history_database.h" 23 #include "components/history/core/browser/history_database.h"
23 #include "components/history/core/browser/history_service.h" 24 #include "components/history/core/browser/history_service.h"
24 #include "components/history/core/browser/url_utils.h" 25 #include "components/history/core/browser/url_utils.h"
25 #include "components/mime_util/mime_util.h" 26 #include "components/mime_util/mime_util.h"
26 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/resource_request_info.h" 28 #include "content/public/browser/resource_request_info.h"
28 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_contents.h"
29 #include "net/http/http_response_headers.h"
30 #include "net/url_request/url_request.h"
31 30
32 using content::BrowserThread; 31 using content::BrowserThread;
33 32
34 namespace predictors { 33 namespace predictors {
35 34
36 namespace { 35 namespace {
37 36
38 // Sorted by decreasing likelihood according to HTTP archive.
39 const char* kFontMimeTypes[] = {"font/woff2",
40 "application/x-font-woff",
41 "application/font-woff",
42 "application/font-woff2",
43 "font/x-woff",
44 "application/x-font-ttf",
45 "font/woff",
46 "font/ttf",
47 "application/x-font-otf",
48 "x-font/woff",
49 "application/font-sfnt",
50 "application/font-ttf"};
51
52 const size_t kNumSampleHosts = 50; 37 const size_t kNumSampleHosts = 50;
53 const size_t kReportReadinessThreshold = 50; 38 const size_t kReportReadinessThreshold = 50;
54 const float kMinOriginConfidenceToTriggerPreconnect = 0.75; 39 const float kMinOriginConfidenceToTriggerPreconnect = 0.75;
55 const float kMinOriginConfidenceToTriggerPreresolve = 0.2; 40 const float kMinOriginConfidenceToTriggerPreresolve = 0.2;
56 41
57 // For reporting events of interest that are not tied to any navigation. 42 // For reporting events of interest that are not tied to any navigation.
58 enum ReportingEvent { 43 enum ReportingEvent {
59 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 44 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
60 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 45 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
61 REPORTING_EVENT_COUNT = 2 46 REPORTING_EVENT_COUNT = 2
62 }; 47 };
63 48
64 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) { 49 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) {
65 return (redirect.number_of_hits() + 0.0) / 50 return (redirect.number_of_hits() + 0.0) /
66 (redirect.number_of_hits() + redirect.number_of_misses()); 51 (redirect.number_of_hits() + redirect.number_of_misses());
67 } 52 }
68 53
69 void UpdateOrAddToOrigins(
70 std::map<GURL, ResourcePrefetchPredictor::OriginRequestSummary>* summaries,
71 const ResourcePrefetchPredictor::URLRequestSummary& request_summary) {
72 const GURL& request_url = request_summary.request_url;
73 DCHECK(request_url.is_valid());
74 if (!request_url.is_valid())
75 return;
76
77 GURL origin = request_url.GetOrigin();
78 auto it = summaries->find(origin);
79 if (it == summaries->end()) {
80 ResourcePrefetchPredictor::OriginRequestSummary summary;
81 summary.origin = origin;
82 summary.first_occurrence = summaries->size();
83 it = summaries->insert({origin, summary}).first;
84 }
85
86 it->second.always_access_network |=
87 request_summary.always_revalidate || request_summary.is_no_store;
88 it->second.accessed_network |= request_summary.network_accessed;
89 }
90
91 void InitializeOriginStatFromOriginRequestSummary( 54 void InitializeOriginStatFromOriginRequestSummary(
92 OriginStat* origin, 55 OriginStat* origin,
93 const ResourcePrefetchPredictor::OriginRequestSummary& summary) { 56 const OriginRequestSummary& summary) {
94 origin->set_origin(summary.origin.spec()); 57 origin->set_origin(summary.origin.spec());
95 origin->set_number_of_hits(1); 58 origin->set_number_of_hits(1);
96 origin->set_average_position(summary.first_occurrence + 1); 59 origin->set_average_position(summary.first_occurrence + 1);
97 origin->set_always_access_network(summary.always_access_network); 60 origin->set_always_access_network(summary.always_access_network);
98 origin->set_accessed_network(summary.accessed_network); 61 origin->set_accessed_network(summary.accessed_network);
99 } 62 }
100 63
101 // Used to fetch the visit count for a URL from the History database. 64 // Used to fetch the visit count for a URL from the History database.
102 class GetUrlVisitCountTask : public history::HistoryDBTask { 65 class GetUrlVisitCountTask : public history::HistoryDBTask {
103 public: 66 public:
104 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
105 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
106 typedef base::OnceCallback<void(size_t, // URL visit count. 67 typedef base::OnceCallback<void(size_t, // URL visit count.
107 const PageRequestSummary&)> 68 const PageRequestSummary&)>
108 VisitInfoCallback; 69 VisitInfoCallback;
109 70
110 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, 71 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
111 VisitInfoCallback callback); 72 VisitInfoCallback callback);
112 73
113 bool RunOnDBThread(history::HistoryBackend* backend, 74 bool RunOnDBThread(history::HistoryBackend* backend,
114 history::HistoryDatabase* db) override; 75 history::HistoryDatabase* db) override;
115 76
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } // namespace 125 } // namespace
165 126
166 PreconnectPrediction::PreconnectPrediction() = default; 127 PreconnectPrediction::PreconnectPrediction() = default;
167 PreconnectPrediction::PreconnectPrediction( 128 PreconnectPrediction::PreconnectPrediction(
168 const PreconnectPrediction& prediction) = default; 129 const PreconnectPrediction& prediction) = default;
169 PreconnectPrediction::~PreconnectPrediction() = default; 130 PreconnectPrediction::~PreconnectPrediction() = default;
170 131
171 //////////////////////////////////////////////////////////////////////////////// 132 ////////////////////////////////////////////////////////////////////////////////
172 // ResourcePrefetchPredictor static functions. 133 // ResourcePrefetchPredictor static functions.
173 134
174 // static
175 content::ResourceType ResourcePrefetchPredictor::GetResourceType(
176 content::ResourceType resource_type,
177 const std::string& mime_type) {
178 // Restricts content::RESOURCE_TYPE_{PREFETCH,SUB_RESOURCE,XHR} to a small set
179 // of mime types, because these resource types don't communicate how the
180 // resources will be used.
181 if (resource_type == content::RESOURCE_TYPE_PREFETCH ||
182 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE ||
183 resource_type == content::RESOURCE_TYPE_XHR) {
184 return GetResourceTypeFromMimeType(mime_type,
185 content::RESOURCE_TYPE_LAST_TYPE);
186 }
187 return resource_type;
188 }
189
190 // static
191 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest& response) {
192 if (response.was_cached())
193 return false;
194
195 const net::HttpResponseInfo& response_info = response.response_info();
196 if (!response_info.headers.get())
197 return false;
198 return response_info.headers->HasHeaderValue("cache-control", "no-store");
199 }
200
201 // static
202 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
203 const std::string& mime_type,
204 content::ResourceType fallback) {
205 if (mime_type.empty()) {
206 return fallback;
207 } else if (mime_util::IsSupportedImageMimeType(mime_type)) {
208 return content::RESOURCE_TYPE_IMAGE;
209 } else if (mime_util::IsSupportedJavascriptMimeType(mime_type)) {
210 return content::RESOURCE_TYPE_SCRIPT;
211 } else if (net::MatchesMimeType("text/css", mime_type)) {
212 return content::RESOURCE_TYPE_STYLESHEET;
213 } else {
214 bool found =
215 std::any_of(std::begin(kFontMimeTypes), std::end(kFontMimeTypes),
216 [&mime_type](const std::string& mime) {
217 return net::MatchesMimeType(mime, mime_type);
218 });
219 if (found)
220 return content::RESOURCE_TYPE_FONT_RESOURCE;
221 }
222 return fallback;
223 }
224
225 bool ResourcePrefetchPredictor::GetRedirectEndpoint( 135 bool ResourcePrefetchPredictor::GetRedirectEndpoint(
226 const std::string& entry_point, 136 const std::string& entry_point,
227 const RedirectDataMap& redirect_data, 137 const RedirectDataMap& redirect_data,
228 std::string* redirect_endpoint) const { 138 std::string* redirect_endpoint) const {
229 DCHECK(redirect_endpoint); 139 DCHECK(redirect_endpoint);
230 140
231 RedirectData data; 141 RedirectData data;
232 bool exists = redirect_data.TryGetData(entry_point, &data); 142 bool exists = redirect_data.TryGetData(entry_point, &data);
233 if (!exists) { 143 if (!exists) {
234 // Fallback to fetching URLs based on the incoming URL/host. By default 144 // Fallback to fetching URLs based on the incoming URL/host. By default
(...skipping 26 matching lines...) Expand all
261 return false; 171 return false;
262 } 172 }
263 173
264 *redirect_endpoint = redirect.url(); 174 *redirect_endpoint = redirect.url();
265 return true; 175 return true;
266 } 176 }
267 177
268 //////////////////////////////////////////////////////////////////////////////// 178 ////////////////////////////////////////////////////////////////////////////////
269 // ResourcePrefetchPredictor nested types. 179 // ResourcePrefetchPredictor nested types.
270 180
271 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary()
272 : origin(),
273 always_access_network(false),
274 accessed_network(false),
275 first_occurrence(0) {}
276
277 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary(
278 const OriginRequestSummary& other) = default;
279
280 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {}
281
282 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
283 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
284 priority(net::IDLE),
285 before_first_contentful_paint(false),
286 was_cached(false),
287 has_validators(false),
288 always_revalidate(false),
289 is_no_store(false),
290 network_accessed(false) {}
291
292 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
293 const URLRequestSummary& other) = default;
294
295 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
296 }
297
298 // static
299 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
300 const net::URLRequest& request,
301 URLRequestSummary* summary) {
302 const content::ResourceRequestInfo* request_info =
303 content::ResourceRequestInfo::ForRequest(&request);
304 if (!request_info)
305 return false;
306
307 // This method is called when the response is started, so this field reflects
308 // the time at which the response began, not when it finished, as would
309 // arguably be ideal. This means if firstContentfulPaint happens after the
310 // response has started, but before it's finished, we will erroneously mark
311 // the resource as having been loaded before firstContentfulPaint. This is
312 // a rare and insignificant enough occurrence that we opt to record the time
313 // here for the sake of simplicity.
314 summary->response_time = base::TimeTicks::Now();
315 summary->resource_url = request.original_url();
316 summary->request_url = request.url();
317 content::ResourceType resource_type_from_request =
318 request_info->GetResourceType();
319 summary->priority = request.priority();
320 request.GetMimeType(&summary->mime_type);
321 summary->was_cached = request.was_cached();
322 summary->resource_type =
323 GetResourceType(resource_type_from_request, summary->mime_type);
324
325 scoped_refptr<net::HttpResponseHeaders> headers =
326 request.response_info().headers;
327 if (headers.get()) {
328 summary->has_validators = headers->HasValidators();
329 // RFC 2616, section 14.9.
330 summary->always_revalidate =
331 headers->HasHeaderValue("cache-control", "no-cache") ||
332 headers->HasHeaderValue("pragma", "no-cache") ||
333 headers->HasHeaderValue("vary", "*");
334 summary->is_no_store = IsNoStore(request);
335 }
336 summary->network_accessed = request.response_info().network_accessed;
337 return true;
338 }
339
340 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
341 const GURL& i_main_frame_url)
342 : main_frame_url(i_main_frame_url),
343 initial_url(i_main_frame_url),
344 first_contentful_paint(base::TimeTicks::Max()) {}
345
346 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
347 const PageRequestSummary& other) = default;
348
349 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {}
350
351 ResourcePrefetchPredictor::Prediction::Prediction() = default; 181 ResourcePrefetchPredictor::Prediction::Prediction() = default;
352 182
353 ResourcePrefetchPredictor::Prediction::Prediction( 183 ResourcePrefetchPredictor::Prediction::Prediction(
354 const ResourcePrefetchPredictor::Prediction& other) = default; 184 const ResourcePrefetchPredictor::Prediction& other) = default;
355 185
356 ResourcePrefetchPredictor::Prediction::~Prediction() = default; 186 ResourcePrefetchPredictor::Prediction::~Prediction() = default;
357 187
358 //////////////////////////////////////////////////////////////////////////////// 188 ////////////////////////////////////////////////////////////////////////////////
359 // ResourcePrefetchPredictor. 189 // ResourcePrefetchPredictor.
360 190
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 auto reply = base::BindOnce( 235 auto reply = base::BindOnce(
406 &ResourcePrefetchPredictor::CreateCaches, weak_factory_.GetWeakPtr(), 236 &ResourcePrefetchPredictor::CreateCaches, weak_factory_.GetWeakPtr(),
407 std::move(url_resource_data), std::move(host_resource_data), 237 std::move(url_resource_data), std::move(host_resource_data),
408 std::move(url_redirect_data), std::move(host_redirect_data), 238 std::move(url_redirect_data), std::move(host_redirect_data),
409 std::move(origin_data)); 239 std::move(origin_data));
410 240
411 BrowserThread::PostTaskAndReply(BrowserThread::DB, FROM_HERE, std::move(task), 241 BrowserThread::PostTaskAndReply(BrowserThread::DB, FROM_HERE, std::move(task),
412 std::move(reply)); 242 std::move(reply));
413 } 243 }
414 244
415 void ResourcePrefetchPredictor::RecordURLRequest(
416 const URLRequestSummary& request) {
417 DCHECK_CURRENTLY_ON(BrowserThread::UI);
418 if (initialization_state_ != INITIALIZED)
419 return;
420
421 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
422 OnMainFrameRequest(request);
423 }
424
425 void ResourcePrefetchPredictor::RecordURLResponse(
426 const URLRequestSummary& response) {
427 DCHECK_CURRENTLY_ON(BrowserThread::UI);
428 if (initialization_state_ != INITIALIZED)
429 return;
430
431 if (response.resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
432 OnSubresourceResponse(response);
433 }
434
435 void ResourcePrefetchPredictor::RecordURLRedirect(
436 const URLRequestSummary& response) {
437 DCHECK_CURRENTLY_ON(BrowserThread::UI);
438 if (initialization_state_ != INITIALIZED)
439 return;
440
441 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
442 OnMainFrameRedirect(response);
443 else
444 OnSubresourceRedirect(response);
445 }
446
447 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete(
448 const NavigationID& navigation_id) {
449 switch (initialization_state_) {
450 case NOT_INITIALIZED:
451 StartInitialization();
452 break;
453 case INITIALIZING:
454 break;
455 case INITIALIZED:
456 // WebContents can return an empty URL if the navigation entry
457 // corresponding to the navigation has not been created yet.
458 if (!navigation_id.main_frame_url.is_empty())
459 OnNavigationComplete(navigation_id);
460 break;
461 default:
462 NOTREACHED() << "Unexpected initialization_state_: "
463 << initialization_state_;
464 }
465 }
466
467 void ResourcePrefetchPredictor::RecordFirstContentfulPaint(
468 const NavigationID& navigation_id,
469 const base::TimeTicks& first_contentful_paint) {
470 DCHECK_CURRENTLY_ON(BrowserThread::UI);
471 if (initialization_state_ != INITIALIZED)
472 return;
473
474 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id);
475 if (nav_it != inflight_navigations_.end())
476 nav_it->second->first_contentful_paint = first_contentful_paint;
477 }
478
479 bool ResourcePrefetchPredictor::IsUrlPrefetchable( 245 bool ResourcePrefetchPredictor::IsUrlPrefetchable(
480 const GURL& main_frame_url) const { 246 const GURL& main_frame_url) const {
481 return GetPrefetchData(main_frame_url, nullptr); 247 return GetPrefetchData(main_frame_url, nullptr);
482 } 248 }
483 249
484 bool ResourcePrefetchPredictor::IsResourcePrefetchable( 250 bool ResourcePrefetchPredictor::IsResourcePrefetchable(
485 const ResourceData& resource) const { 251 const ResourceData& resource) const {
486 float confidence = static_cast<float>(resource.number_of_hits()) / 252 float confidence = static_cast<float>(resource.number_of_hits()) /
487 (resource.number_of_hits() + resource.number_of_misses()); 253 (resource.number_of_hits() + resource.number_of_misses());
488 return confidence >= config_.min_resource_confidence_to_trigger_prefetch && 254 return confidence >= config_.min_resource_confidence_to_trigger_prefetch &&
489 resource.number_of_hits() >= 255 resource.number_of_hits() >=
490 config_.min_resource_hits_to_trigger_prefetch; 256 config_.min_resource_hits_to_trigger_prefetch;
491 } 257 }
492 258
493 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) { 259 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) {
494 observer_ = observer; 260 observer_ = observer;
495 } 261 }
496 262
497 void ResourcePrefetchPredictor::SetStatsCollector( 263 void ResourcePrefetchPredictor::SetStatsCollector(
498 LoadingStatsCollector* stats_collector) { 264 LoadingStatsCollector* stats_collector) {
499 stats_collector_ = stats_collector; 265 stats_collector_ = stats_collector;
500 } 266 }
501 267
502 void ResourcePrefetchPredictor::Shutdown() { 268 void ResourcePrefetchPredictor::Shutdown() {
503 history_service_observer_.RemoveAll(); 269 history_service_observer_.RemoveAll();
504 } 270 }
505 271
506 void ResourcePrefetchPredictor::OnMainFrameRequest( 272 void ResourcePrefetchPredictor::RecordPageRequestSummary(
507 const URLRequestSummary& request) { 273 std::unique_ptr<PageRequestSummary> summary) {
508 DCHECK_CURRENTLY_ON(BrowserThread::UI); 274 // Make sure initialization is done or start initialization if necessary.
509 DCHECK_EQ(INITIALIZED, initialization_state_); 275 if (initialization_state_ == NOT_INITIALIZED) {
510 276 StartInitialization();
511 CleanupAbandonedNavigations(request.navigation_id); 277 return;
512 278 } else if (initialization_state_ == INITIALIZING) {
513 // New empty navigation entry. 279 return;
514 const GURL& main_frame_url = request.navigation_id.main_frame_url; 280 } else if (initialization_state_ != INITIALIZED) {
515 inflight_navigations_.emplace( 281 NOTREACHED() << "Unexpected initialization_state_: "
516 request.navigation_id, 282 << initialization_state_;
517 base::MakeUnique<PageRequestSummary>(main_frame_url)); 283 return;
518 }
519
520 void ResourcePrefetchPredictor::OnMainFrameRedirect(
521 const URLRequestSummary& response) {
522 DCHECK_CURRENTLY_ON(BrowserThread::UI);
523 DCHECK_EQ(INITIALIZED, initialization_state_);
524
525 const GURL& main_frame_url = response.navigation_id.main_frame_url;
526 std::unique_ptr<PageRequestSummary> summary;
527 NavigationMap::iterator nav_it =
528 inflight_navigations_.find(response.navigation_id);
529 if (nav_it != inflight_navigations_.end()) {
530 summary = std::move(nav_it->second);
531 inflight_navigations_.erase(nav_it);
532 } 284 }
533 285
534 // The redirect url may be empty if the URL was invalid.
535 if (response.redirect_url.is_empty())
536 return;
537
538 // If we lost the information about the first hop for some reason.
539 if (!summary) {
540 summary = base::MakeUnique<PageRequestSummary>(main_frame_url);
541 }
542
543 // A redirect will not lead to another OnMainFrameRequest call, so record the
544 // redirect url as a new navigation id and save the initial url.
545 NavigationID navigation_id(response.navigation_id);
546 navigation_id.main_frame_url = response.redirect_url;
547 summary->main_frame_url = response.redirect_url;
548 inflight_navigations_.emplace(navigation_id, std::move(summary));
549 }
550
551 void ResourcePrefetchPredictor::OnSubresourceResponse(
552 const URLRequestSummary& response) {
553 DCHECK_CURRENTLY_ON(BrowserThread::UI);
554 DCHECK_EQ(INITIALIZED, initialization_state_);
555
556 NavigationMap::const_iterator nav_it =
557 inflight_navigations_.find(response.navigation_id);
558 if (nav_it == inflight_navigations_.end())
559 return;
560 auto& page_request_summary = *nav_it->second;
561
562 if (!response.is_no_store)
563 page_request_summary.subresource_requests.push_back(response);
564
565 if (config_.is_origin_learning_enabled)
566 UpdateOrAddToOrigins(&page_request_summary.origins, response);
567 }
568
569 void ResourcePrefetchPredictor::OnSubresourceRedirect(
570 const URLRequestSummary& response) {
571 DCHECK_CURRENTLY_ON(BrowserThread::UI);
572 DCHECK_EQ(INITIALIZED, initialization_state_);
573
574 if (!config_.is_origin_learning_enabled)
575 return;
576
577 NavigationMap::const_iterator nav_it =
578 inflight_navigations_.find(response.navigation_id);
579 if (nav_it == inflight_navigations_.end())
580 return;
581 auto& page_request_summary = *nav_it->second;
582 UpdateOrAddToOrigins(&page_request_summary.origins, response);
583 }
584
585 void ResourcePrefetchPredictor::OnNavigationComplete(
586 const NavigationID& nav_id_without_timing_info) {
587 DCHECK_CURRENTLY_ON(BrowserThread::UI);
588 DCHECK_EQ(INITIALIZED, initialization_state_);
589
590 NavigationMap::iterator nav_it =
591 inflight_navigations_.find(nav_id_without_timing_info);
592 if (nav_it == inflight_navigations_.end())
593 return;
594
595 // Remove the navigation from the inflight navigations.
596 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second);
597 inflight_navigations_.erase(nav_it);
598
599 // Set before_first_contentful paint for each resource.
600 for (auto& request_summary : summary->subresource_requests) {
601 request_summary.before_first_contentful_paint =
602 request_summary.response_time < summary->first_contentful_paint;
603 }
604
605 if (stats_collector_)
606 stats_collector_->RecordPageRequestSummary(*summary);
607
608 // Kick off history lookup to determine if we should record the URL. 286 // Kick off history lookup to determine if we should record the URL.
609 history::HistoryService* history_service = 287 history::HistoryService* history_service =
610 HistoryServiceFactory::GetForProfile(profile_, 288 HistoryServiceFactory::GetForProfile(profile_,
611 ServiceAccessType::EXPLICIT_ACCESS); 289 ServiceAccessType::EXPLICIT_ACCESS);
612 DCHECK(history_service); 290 DCHECK(history_service);
613 history_service->ScheduleDBTask( 291 history_service->ScheduleDBTask(
614 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( 292 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
615 std::move(summary), 293 std::move(summary),
616 base::BindOnce(&ResourcePrefetchPredictor::OnVisitCountLookup, 294 base::BindOnce(&ResourcePrefetchPredictor::OnVisitCountLookup,
617 weak_factory_.GetWeakPtr()))), 295 weak_factory_.GetWeakPtr()))),
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 429
752 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 430 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
753 DCHECK_CURRENTLY_ON(BrowserThread::UI); 431 DCHECK_CURRENTLY_ON(BrowserThread::UI);
754 DCHECK_EQ(INITIALIZING, initialization_state_); 432 DCHECK_EQ(INITIALIZING, initialization_state_);
755 433
756 initialization_state_ = INITIALIZED; 434 initialization_state_ = INITIALIZED;
757 if (observer_) 435 if (observer_)
758 observer_->OnPredictorInitialized(); 436 observer_->OnPredictorInitialized();
759 } 437 }
760 438
761 void ResourcePrefetchPredictor::CleanupAbandonedNavigations(
762 const NavigationID& navigation_id) {
763 if (stats_collector_)
764 stats_collector_->CleanupAbandonedStats();
765
766 static const base::TimeDelta max_navigation_age =
767 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds);
768
769 base::TimeTicks time_now = base::TimeTicks::Now();
770 for (NavigationMap::iterator it = inflight_navigations_.begin();
771 it != inflight_navigations_.end();) {
772 if ((it->first.tab_id == navigation_id.tab_id) ||
773 (time_now - it->first.creation_time > max_navigation_age)) {
774 inflight_navigations_.erase(it++);
775 } else {
776 ++it;
777 }
778 }
779 }
780
781 void ResourcePrefetchPredictor::DeleteAllUrls() { 439 void ResourcePrefetchPredictor::DeleteAllUrls() {
782 inflight_navigations_.clear();
783
784 url_resource_data_->DeleteAllData(); 440 url_resource_data_->DeleteAllData();
785 host_resource_data_->DeleteAllData(); 441 host_resource_data_->DeleteAllData();
786 url_redirect_data_->DeleteAllData(); 442 url_redirect_data_->DeleteAllData();
787 host_redirect_data_->DeleteAllData(); 443 host_redirect_data_->DeleteAllData();
788 origin_data_->DeleteAllData(); 444 origin_data_->DeleteAllData();
789 } 445 }
790 446
791 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { 447 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
792 std::vector<std::string> urls_to_delete; 448 std::vector<std::string> urls_to_delete;
793 std::vector<std::string> hosts_to_delete; 449 std::vector<std::string> hosts_to_delete;
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 void ResourcePrefetchPredictor::OnHistoryServiceLoaded( 830 void ResourcePrefetchPredictor::OnHistoryServiceLoaded(
1175 history::HistoryService* history_service) { 831 history::HistoryService* history_service) {
1176 if (initialization_state_ == INITIALIZING) { 832 if (initialization_state_ == INITIALIZING) {
1177 OnHistoryAndCacheLoaded(); 833 OnHistoryAndCacheLoaded();
1178 } 834 }
1179 } 835 }
1180 836
1181 void ResourcePrefetchPredictor::ConnectToHistoryService() { 837 void ResourcePrefetchPredictor::ConnectToHistoryService() {
1182 DCHECK_CURRENTLY_ON(BrowserThread::UI); 838 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1183 DCHECK_EQ(INITIALIZING, initialization_state_); 839 DCHECK_EQ(INITIALIZING, initialization_state_);
1184 DCHECK(inflight_navigations_.empty());
1185 840
1186 // Register for HistoryServiceLoading if it is not ready. 841 // Register for HistoryServiceLoading if it is not ready.
1187 history::HistoryService* history_service = 842 history::HistoryService* history_service =
1188 HistoryServiceFactory::GetForProfile(profile_, 843 HistoryServiceFactory::GetForProfile(profile_,
1189 ServiceAccessType::EXPLICIT_ACCESS); 844 ServiceAccessType::EXPLICIT_ACCESS);
1190 if (!history_service) 845 if (!history_service)
1191 return; 846 return;
1192 DCHECK(!history_service_observer_.IsObserving(history_service)); 847 DCHECK(!history_service_observer_.IsObserving(history_service));
1193 history_service_observer_.Add(history_service); 848 history_service_observer_.Add(history_service);
1194 if (history_service->BackendLoaded()) { 849 if (history_service->BackendLoaded()) {
1195 // HistoryService is already loaded. Continue with Initialization. 850 // HistoryService is already loaded. Continue with Initialization.
1196 OnHistoryAndCacheLoaded(); 851 OnHistoryAndCacheLoaded();
1197 } 852 }
1198 } 853 }
1199 854
1200 //////////////////////////////////////////////////////////////////////////////// 855 ////////////////////////////////////////////////////////////////////////////////
1201 // TestObserver. 856 // TestObserver.
1202 857
1203 TestObserver::~TestObserver() { 858 TestObserver::~TestObserver() {
1204 predictor_->SetObserverForTesting(nullptr); 859 predictor_->SetObserverForTesting(nullptr);
1205 } 860 }
1206 861
1207 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) 862 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor)
1208 : predictor_(predictor) { 863 : predictor_(predictor) {
1209 predictor_->SetObserverForTesting(this); 864 predictor_->SetObserverForTesting(this);
1210 } 865 }
1211 866
1212 } // namespace predictors 867 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698