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

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

Issue 2937623007: predictors: Move more methods from ResourcePrefetchPredictor into LoadingDataCollector. (Closed)
Patch Set: Combine RecordMainFrameLoadComplete and OnNavigationComplete. Created 3 years, 6 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/predictors/resource_prefetcher_manager.h" 22 #include "chrome/browser/predictors/resource_prefetcher_manager.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
23 #include "components/history/core/browser/history_database.h" 24 #include "components/history/core/browser/history_database.h"
24 #include "components/history/core/browser/history_service.h" 25 #include "components/history/core/browser/history_service.h"
25 #include "components/history/core/browser/url_utils.h" 26 #include "components/history/core/browser/url_utils.h"
26 #include "components/mime_util/mime_util.h" 27 #include "components/mime_util/mime_util.h"
27 #include "components/precache/core/precache_manifest_util.h" 28 #include "components/precache/core/precache_manifest_util.h"
28 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/resource_request_info.h" 30 #include "content/public/browser/resource_request_info.h"
30 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
31 #include "net/http/http_response_headers.h"
32 #include "net/url_request/url_request.h"
33 32
34 using content::BrowserThread; 33 using content::BrowserThread;
35 34
36 namespace predictors { 35 namespace predictors {
37 36
38 namespace { 37 namespace {
39 38
40 // Sorted by decreasing likelihood according to HTTP archive.
41 const char* kFontMimeTypes[] = {"font/woff2",
42 "application/x-font-woff",
43 "application/font-woff",
44 "application/font-woff2",
45 "font/x-woff",
46 "application/x-font-ttf",
47 "font/woff",
48 "font/ttf",
49 "application/x-font-otf",
50 "x-font/woff",
51 "application/font-sfnt",
52 "application/font-ttf"};
53
54 const size_t kMaxManifestByteSize = 16 * 1024; 39 const size_t kMaxManifestByteSize = 16 * 1024;
55 const size_t kNumSampleHosts = 50; 40 const size_t kNumSampleHosts = 50;
56 const size_t kReportReadinessThreshold = 50; 41 const size_t kReportReadinessThreshold = 50;
57 42
58 // For reporting events of interest that are not tied to any navigation. 43 // For reporting events of interest that are not tied to any navigation.
59 enum ReportingEvent { 44 enum ReportingEvent {
60 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 45 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
61 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 46 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
62 REPORTING_EVENT_COUNT = 2 47 REPORTING_EVENT_COUNT = 2
63 }; 48 };
64 49
65 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) { 50 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) {
66 return (redirect.number_of_hits() + 0.0) / 51 return (redirect.number_of_hits() + 0.0) /
67 (redirect.number_of_hits() + redirect.number_of_misses()); 52 (redirect.number_of_hits() + redirect.number_of_misses());
68 } 53 }
69 54
70 void UpdateOrAddToOrigins(
71 std::map<GURL, ResourcePrefetchPredictor::OriginRequestSummary>* summaries,
72 const ResourcePrefetchPredictor::URLRequestSummary& request_summary) {
73 const GURL& request_url = request_summary.request_url;
74 DCHECK(request_url.is_valid());
75 if (!request_url.is_valid())
76 return;
77
78 GURL origin = request_url.GetOrigin();
79 auto it = summaries->find(origin);
80 if (it == summaries->end()) {
81 ResourcePrefetchPredictor::OriginRequestSummary summary;
82 summary.origin = origin;
83 summary.first_occurrence = summaries->size();
84 it = summaries->insert({origin, summary}).first;
85 }
86
87 it->second.always_access_network |=
88 request_summary.always_revalidate || request_summary.is_no_store;
89 it->second.accessed_network |= request_summary.network_accessed;
90 }
91
92 void InitializeOriginStatFromOriginRequestSummary( 55 void InitializeOriginStatFromOriginRequestSummary(
93 OriginStat* origin, 56 OriginStat* origin,
94 const ResourcePrefetchPredictor::OriginRequestSummary& summary) { 57 const OriginRequestSummary& summary) {
95 origin->set_origin(summary.origin.spec()); 58 origin->set_origin(summary.origin.spec());
96 origin->set_number_of_hits(1); 59 origin->set_number_of_hits(1);
97 origin->set_average_position(summary.first_occurrence + 1); 60 origin->set_average_position(summary.first_occurrence + 1);
98 origin->set_always_access_network(summary.always_access_network); 61 origin->set_always_access_network(summary.always_access_network);
99 origin->set_accessed_network(summary.accessed_network); 62 origin->set_accessed_network(summary.accessed_network);
100 } 63 }
101 64
102 bool IsManifestTooOld(const precache::PrecacheManifest& manifest) { 65 bool IsManifestTooOld(const precache::PrecacheManifest& manifest) {
103 const base::TimeDelta kMaxManifestAge = base::TimeDelta::FromDays(5); 66 const base::TimeDelta kMaxManifestAge = base::TimeDelta::FromDays(5);
104 return base::Time::Now() - base::Time::FromDoubleT(manifest.id().id()) > 67 return base::Time::Now() - base::Time::FromDoubleT(manifest.id().id()) >
105 kMaxManifestAge; 68 kMaxManifestAge;
106 } 69 }
107 70
108 // Used to fetch the visit count for a URL from the History database. 71 // Used to fetch the visit count for a URL from the History database.
109 class GetUrlVisitCountTask : public history::HistoryDBTask { 72 class GetUrlVisitCountTask : public history::HistoryDBTask {
110 public: 73 public:
111 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
112 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
113 typedef base::OnceCallback<void(size_t, // URL visit count. 74 typedef base::OnceCallback<void(size_t, // URL visit count.
114 const PageRequestSummary&)> 75 const PageRequestSummary&)>
115 VisitInfoCallback; 76 VisitInfoCallback;
116 77
117 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, 78 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
118 VisitInfoCallback callback); 79 VisitInfoCallback callback);
119 80
120 bool RunOnDBThread(history::HistoryBackend* backend, 81 bool RunOnDBThread(history::HistoryBackend* backend,
121 history::HistoryDatabase* db) override; 82 history::HistoryDatabase* db) override;
122 83
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 bool ManifestCompare::operator()(const precache::PrecacheManifest& lhs, 123 bool ManifestCompare::operator()(const precache::PrecacheManifest& lhs,
163 const precache::PrecacheManifest& rhs) const { 124 const precache::PrecacheManifest& rhs) const {
164 return lhs.id().id() < rhs.id().id(); 125 return lhs.id().id() < rhs.id().id();
165 } 126 }
166 127
167 } // namespace internal 128 } // namespace internal
168 129
169 //////////////////////////////////////////////////////////////////////////////// 130 ////////////////////////////////////////////////////////////////////////////////
170 // ResourcePrefetchPredictor static functions. 131 // ResourcePrefetchPredictor static functions.
171 132
172 // static
173 content::ResourceType ResourcePrefetchPredictor::GetResourceType(
174 content::ResourceType resource_type,
175 const std::string& mime_type) {
176 // Restricts content::RESOURCE_TYPE_{PREFETCH,SUB_RESOURCE,XHR} to a small set
177 // of mime types, because these resource types don't communicate how the
178 // resources will be used.
179 if (resource_type == content::RESOURCE_TYPE_PREFETCH ||
180 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE ||
181 resource_type == content::RESOURCE_TYPE_XHR) {
182 return GetResourceTypeFromMimeType(mime_type,
183 content::RESOURCE_TYPE_LAST_TYPE);
184 }
185 return resource_type;
186 }
187
188 // static
189 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest& response) {
190 if (response.was_cached())
191 return false;
192
193 const net::HttpResponseInfo& response_info = response.response_info();
194 if (!response_info.headers.get())
195 return false;
196 return response_info.headers->HasHeaderValue("cache-control", "no-store");
197 }
198
199 // static
200 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
201 const std::string& mime_type,
202 content::ResourceType fallback) {
203 if (mime_type.empty()) {
204 return fallback;
205 } else if (mime_util::IsSupportedImageMimeType(mime_type)) {
206 return content::RESOURCE_TYPE_IMAGE;
207 } else if (mime_util::IsSupportedJavascriptMimeType(mime_type)) {
208 return content::RESOURCE_TYPE_SCRIPT;
209 } else if (net::MatchesMimeType("text/css", mime_type)) {
210 return content::RESOURCE_TYPE_STYLESHEET;
211 } else {
212 bool found =
213 std::any_of(std::begin(kFontMimeTypes), std::end(kFontMimeTypes),
214 [&mime_type](const std::string& mime) {
215 return net::MatchesMimeType(mime, mime_type);
216 });
217 if (found)
218 return content::RESOURCE_TYPE_FONT_RESOURCE;
219 }
220 return fallback;
221 }
222
223 bool ResourcePrefetchPredictor::GetRedirectEndpoint( 133 bool ResourcePrefetchPredictor::GetRedirectEndpoint(
224 const std::string& entry_point, 134 const std::string& entry_point,
225 const RedirectDataMap& redirect_data, 135 const RedirectDataMap& redirect_data,
226 std::string* redirect_endpoint) const { 136 std::string* redirect_endpoint) const {
227 DCHECK(redirect_endpoint); 137 DCHECK(redirect_endpoint);
228 138
229 RedirectData data; 139 RedirectData data;
230 bool exists = redirect_data.TryGetData(entry_point, &data); 140 bool exists = redirect_data.TryGetData(entry_point, &data);
231 if (!exists) { 141 if (!exists) {
232 // Fallback to fetching URLs based on the incoming URL/host. By default 142 // Fallback to fetching URLs based on the incoming URL/host. By default
(...skipping 26 matching lines...) Expand all
259 return false; 169 return false;
260 } 170 }
261 171
262 *redirect_endpoint = redirect.url(); 172 *redirect_endpoint = redirect.url();
263 return true; 173 return true;
264 } 174 }
265 175
266 //////////////////////////////////////////////////////////////////////////////// 176 ////////////////////////////////////////////////////////////////////////////////
267 // ResourcePrefetchPredictor nested types. 177 // ResourcePrefetchPredictor nested types.
268 178
269 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary()
270 : origin(),
271 always_access_network(false),
272 accessed_network(false),
273 first_occurrence(0) {}
274
275 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary(
276 const OriginRequestSummary& other) = default;
277
278 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {}
279
280 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
281 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
282 priority(net::IDLE),
283 before_first_contentful_paint(false),
284 was_cached(false),
285 has_validators(false),
286 always_revalidate(false),
287 is_no_store(false),
288 network_accessed(false) {}
289
290 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
291 const URLRequestSummary& other) = default;
292
293 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
294 }
295
296 // static
297 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
298 const net::URLRequest& request,
299 URLRequestSummary* summary) {
300 const content::ResourceRequestInfo* request_info =
301 content::ResourceRequestInfo::ForRequest(&request);
302 if (!request_info)
303 return false;
304
305 // This method is called when the response is started, so this field reflects
306 // the time at which the response began, not when it finished, as would
307 // arguably be ideal. This means if firstContentfulPaint happens after the
308 // response has started, but before it's finished, we will erroneously mark
309 // the resource as having been loaded before firstContentfulPaint. This is
310 // a rare and insignificant enough occurrence that we opt to record the time
311 // here for the sake of simplicity.
312 summary->response_time = base::TimeTicks::Now();
313 summary->resource_url = request.original_url();
314 summary->request_url = request.url();
315 content::ResourceType resource_type_from_request =
316 request_info->GetResourceType();
317 summary->priority = request.priority();
318 request.GetMimeType(&summary->mime_type);
319 summary->was_cached = request.was_cached();
320 summary->resource_type =
321 GetResourceType(resource_type_from_request, summary->mime_type);
322
323 scoped_refptr<net::HttpResponseHeaders> headers =
324 request.response_info().headers;
325 if (headers.get()) {
326 summary->has_validators = headers->HasValidators();
327 // RFC 2616, section 14.9.
328 summary->always_revalidate =
329 headers->HasHeaderValue("cache-control", "no-cache") ||
330 headers->HasHeaderValue("pragma", "no-cache") ||
331 headers->HasHeaderValue("vary", "*");
332 summary->is_no_store = IsNoStore(request);
333 }
334 summary->network_accessed = request.response_info().network_accessed;
335 return true;
336 }
337
338 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
339 const GURL& i_main_frame_url)
340 : main_frame_url(i_main_frame_url),
341 initial_url(i_main_frame_url),
342 first_contentful_paint(base::TimeTicks::Max()) {}
343
344 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
345 const PageRequestSummary& other) = default;
346
347 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {}
348
349 ResourcePrefetchPredictor::Prediction::Prediction() = default; 179 ResourcePrefetchPredictor::Prediction::Prediction() = default;
350 180
351 ResourcePrefetchPredictor::Prediction::Prediction( 181 ResourcePrefetchPredictor::Prediction::Prediction(
352 const ResourcePrefetchPredictor::Prediction& other) = default; 182 const ResourcePrefetchPredictor::Prediction& other) = default;
353 183
354 ResourcePrefetchPredictor::Prediction::~Prediction() = default; 184 ResourcePrefetchPredictor::Prediction::~Prediction() = default;
355 185
356 //////////////////////////////////////////////////////////////////////////////// 186 ////////////////////////////////////////////////////////////////////////////////
357 // ResourcePrefetchPredictor. 187 // ResourcePrefetchPredictor.
358 188
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 236
407 // Storage objects have to be initialized on a DB thread. 237 // Storage objects have to be initialized on a DB thread.
408 BrowserThread::PostTaskAndReply( 238 BrowserThread::PostTaskAndReply(
409 BrowserThread::DB, FROM_HERE, 239 BrowserThread::DB, FROM_HERE,
410 base::BindOnce(&ResourcePrefetchPredictor::InitializeOnDBThread, 240 base::BindOnce(&ResourcePrefetchPredictor::InitializeOnDBThread,
411 base::Unretained(this)), 241 base::Unretained(this)),
412 base::BindOnce(&ResourcePrefetchPredictor::ConnectToHistoryService, 242 base::BindOnce(&ResourcePrefetchPredictor::ConnectToHistoryService,
413 AsWeakPtr())); 243 AsWeakPtr()));
414 } 244 }
415 245
416 void ResourcePrefetchPredictor::RecordURLRequest(
417 const URLRequestSummary& request) {
418 DCHECK_CURRENTLY_ON(BrowserThread::UI);
419 if (initialization_state_ != INITIALIZED)
420 return;
421
422 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
423 OnMainFrameRequest(request);
424 }
425
426 void ResourcePrefetchPredictor::RecordURLResponse(
427 const URLRequestSummary& response) {
428 DCHECK_CURRENTLY_ON(BrowserThread::UI);
429 if (initialization_state_ != INITIALIZED)
430 return;
431
432 if (response.resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
433 OnSubresourceResponse(response);
434 }
435
436 void ResourcePrefetchPredictor::RecordURLRedirect(
437 const URLRequestSummary& response) {
438 DCHECK_CURRENTLY_ON(BrowserThread::UI);
439 if (initialization_state_ != INITIALIZED)
440 return;
441
442 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
443 OnMainFrameRedirect(response);
444 else
445 OnSubresourceRedirect(response);
446 }
447
448 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete(
449 const NavigationID& navigation_id) {
450 switch (initialization_state_) {
451 case NOT_INITIALIZED:
452 StartInitialization();
453 break;
454 case INITIALIZING:
455 break;
456 case INITIALIZED:
457 // WebContents can return an empty URL if the navigation entry
458 // corresponding to the navigation has not been created yet.
459 if (!navigation_id.main_frame_url.is_empty())
460 OnNavigationComplete(navigation_id);
461 break;
462 default:
463 NOTREACHED() << "Unexpected initialization_state_: "
464 << initialization_state_;
465 }
466 }
467
468 void ResourcePrefetchPredictor::RecordFirstContentfulPaint(
469 const NavigationID& navigation_id,
470 const base::TimeTicks& first_contentful_paint) {
471 DCHECK_CURRENTLY_ON(BrowserThread::UI);
472 if (initialization_state_ != INITIALIZED)
473 return;
474
475 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id);
476 if (nav_it != inflight_navigations_.end())
477 nav_it->second->first_contentful_paint = first_contentful_paint;
478 }
479
480 void ResourcePrefetchPredictor::OnPrefetchingFinished( 246 void ResourcePrefetchPredictor::OnPrefetchingFinished(
481 const GURL& main_frame_url, 247 const GURL& main_frame_url,
482 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) { 248 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) {
483 if (observer_) 249 if (observer_)
484 observer_->OnPrefetchingFinished(main_frame_url); 250 observer_->OnPrefetchingFinished(main_frame_url);
485 251
486 if (stats_collector_) 252 if (stats_collector_)
487 stats_collector_->RecordPrefetcherStats(std::move(stats)); 253 stats_collector_->RecordPrefetcherStats(std::move(stats));
488 } 254 }
489 255
(...skipping 21 matching lines...) Expand all
511 } 277 }
512 278
513 void ResourcePrefetchPredictor::Shutdown() { 279 void ResourcePrefetchPredictor::Shutdown() {
514 if (prefetch_manager_.get()) { 280 if (prefetch_manager_.get()) {
515 prefetch_manager_->ShutdownOnUIThread(); 281 prefetch_manager_->ShutdownOnUIThread();
516 prefetch_manager_ = NULL; 282 prefetch_manager_ = NULL;
517 } 283 }
518 history_service_observer_.RemoveAll(); 284 history_service_observer_.RemoveAll();
519 } 285 }
520 286
521 void ResourcePrefetchPredictor::OnMainFrameRequest( 287 void ResourcePrefetchPredictor::HandlePageRequestSummary(
522 const URLRequestSummary& request) { 288 std::unique_ptr<PageRequestSummary> summary) {
trevordixon 2017/06/16 05:35:55 Especially review what I did here. I copied the in
alexilin 2017/06/16 09:31:57 Thanks! I think it's acceptable solution for now.
trevordixon 2017/06/16 10:53:19 👍
523 DCHECK_CURRENTLY_ON(BrowserThread::UI); 289 // Make sure initialization is done or start initialization if necessary.
524 DCHECK_EQ(INITIALIZED, initialization_state_); 290 if (initialization_state_ == NOT_INITIALIZED) {
525 291 StartInitialization();
526 CleanupAbandonedNavigations(request.navigation_id); 292 return;
527 293 } else if (initialization_state_ == INITIALIZING) {
528 // New empty navigation entry. 294 return;
529 const GURL& main_frame_url = request.navigation_id.main_frame_url; 295 } else if (initialization_state_ != INITIALIZED) {
530 inflight_navigations_.emplace( 296 NOTREACHED() << "Unexpected initialization_state_: "
531 request.navigation_id, 297 << initialization_state_;
532 base::MakeUnique<PageRequestSummary>(main_frame_url)); 298 return;
533 }
534
535 void ResourcePrefetchPredictor::OnMainFrameRedirect(
536 const URLRequestSummary& response) {
537 DCHECK_CURRENTLY_ON(BrowserThread::UI);
538 DCHECK_EQ(INITIALIZED, initialization_state_);
539
540 const GURL& main_frame_url = response.navigation_id.main_frame_url;
541 std::unique_ptr<PageRequestSummary> summary;
542 NavigationMap::iterator nav_it =
543 inflight_navigations_.find(response.navigation_id);
544 if (nav_it != inflight_navigations_.end()) {
545 summary = std::move(nav_it->second);
546 inflight_navigations_.erase(nav_it);
547 } 299 }
548 300
549 // The redirect url may be empty if the URL was invalid.
550 if (response.redirect_url.is_empty())
551 return;
552
553 // If we lost the information about the first hop for some reason.
554 if (!summary) {
555 summary = base::MakeUnique<PageRequestSummary>(main_frame_url);
556 }
557
558 // A redirect will not lead to another OnMainFrameRequest call, so record the
559 // redirect url as a new navigation id and save the initial url.
560 NavigationID navigation_id(response.navigation_id);
561 navigation_id.main_frame_url = response.redirect_url;
562 summary->main_frame_url = response.redirect_url;
563 inflight_navigations_.emplace(navigation_id, std::move(summary));
564 }
565
566 void ResourcePrefetchPredictor::OnSubresourceResponse(
567 const URLRequestSummary& response) {
568 DCHECK_CURRENTLY_ON(BrowserThread::UI);
569 DCHECK_EQ(INITIALIZED, initialization_state_);
570
571 NavigationMap::const_iterator nav_it =
572 inflight_navigations_.find(response.navigation_id);
573 if (nav_it == inflight_navigations_.end())
574 return;
575 auto& page_request_summary = *nav_it->second;
576
577 if (!response.is_no_store)
578 page_request_summary.subresource_requests.push_back(response);
579
580 if (config_.is_origin_learning_enabled)
581 UpdateOrAddToOrigins(&page_request_summary.origins, response);
582 }
583
584 void ResourcePrefetchPredictor::OnSubresourceRedirect(
585 const URLRequestSummary& response) {
586 DCHECK_CURRENTLY_ON(BrowserThread::UI);
587 DCHECK_EQ(INITIALIZED, initialization_state_);
588
589 if (!config_.is_origin_learning_enabled)
590 return;
591
592 NavigationMap::const_iterator nav_it =
593 inflight_navigations_.find(response.navigation_id);
594 if (nav_it == inflight_navigations_.end())
595 return;
596 auto& page_request_summary = *nav_it->second;
597 UpdateOrAddToOrigins(&page_request_summary.origins, response);
598 }
599
600 void ResourcePrefetchPredictor::OnNavigationComplete(
601 const NavigationID& nav_id_without_timing_info) {
602 DCHECK_CURRENTLY_ON(BrowserThread::UI);
603 DCHECK_EQ(INITIALIZED, initialization_state_);
604
605 NavigationMap::iterator nav_it =
606 inflight_navigations_.find(nav_id_without_timing_info);
607 if (nav_it == inflight_navigations_.end())
608 return;
609
610 // Remove the navigation from the inflight navigations.
611 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second);
612 inflight_navigations_.erase(nav_it);
613
614 // Set before_first_contentful paint for each resource.
615 for (auto& request_summary : summary->subresource_requests) {
616 request_summary.before_first_contentful_paint =
617 request_summary.response_time < summary->first_contentful_paint;
618 }
619
620 if (stats_collector_)
621 stats_collector_->RecordPageRequestSummary(*summary);
622
623 // Kick off history lookup to determine if we should record the URL. 301 // Kick off history lookup to determine if we should record the URL.
624 history::HistoryService* history_service = 302 history::HistoryService* history_service =
625 HistoryServiceFactory::GetForProfile(profile_, 303 HistoryServiceFactory::GetForProfile(profile_,
626 ServiceAccessType::EXPLICIT_ACCESS); 304 ServiceAccessType::EXPLICIT_ACCESS);
627 DCHECK(history_service); 305 DCHECK(history_service);
628 history_service->ScheduleDBTask( 306 history_service->ScheduleDBTask(
629 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( 307 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
630 std::move(summary), 308 std::move(summary),
631 base::BindOnce(&ResourcePrefetchPredictor::OnVisitCountLookup, 309 base::BindOnce(&ResourcePrefetchPredictor::OnVisitCountLookup,
632 AsWeakPtr()))), 310 AsWeakPtr()))),
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) { 461 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) {
784 prefetch_manager_ = new ResourcePrefetcherManager( 462 prefetch_manager_ = new ResourcePrefetcherManager(
785 this, config_, profile_->GetRequestContext()); 463 this, config_, profile_->GetRequestContext());
786 } 464 }
787 initialization_state_ = INITIALIZED; 465 initialization_state_ = INITIALIZED;
788 466
789 if (observer_) 467 if (observer_)
790 observer_->OnPredictorInitialized(); 468 observer_->OnPredictorInitialized();
791 } 469 }
792 470
793 void ResourcePrefetchPredictor::CleanupAbandonedNavigations(
794 const NavigationID& navigation_id) {
795 if (stats_collector_)
796 stats_collector_->CleanupAbandonedStats();
797
798 static const base::TimeDelta max_navigation_age =
799 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds);
800
801 base::TimeTicks time_now = base::TimeTicks::Now();
802 for (NavigationMap::iterator it = inflight_navigations_.begin();
803 it != inflight_navigations_.end();) {
804 if ((it->first.tab_id == navigation_id.tab_id) ||
805 (time_now - it->first.creation_time > max_navigation_age)) {
806 inflight_navigations_.erase(it++);
807 } else {
808 ++it;
809 }
810 }
811 }
812
813 void ResourcePrefetchPredictor::DeleteAllUrls() { 471 void ResourcePrefetchPredictor::DeleteAllUrls() {
814 inflight_navigations_.clear(); 472 inflight_navigations_.clear();
815 473
816 url_resource_data_->DeleteAllData(); 474 url_resource_data_->DeleteAllData();
817 host_resource_data_->DeleteAllData(); 475 host_resource_data_->DeleteAllData();
818 url_redirect_data_->DeleteAllData(); 476 url_redirect_data_->DeleteAllData();
819 host_redirect_data_->DeleteAllData(); 477 host_redirect_data_->DeleteAllData();
820 manifest_data_->DeleteAllData(); 478 manifest_data_->DeleteAllData();
821 origin_data_->DeleteAllData(); 479 origin_data_->DeleteAllData();
822 } 480 }
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 TestObserver::~TestObserver() { 998 TestObserver::~TestObserver() {
1341 predictor_->SetObserverForTesting(nullptr); 999 predictor_->SetObserverForTesting(nullptr);
1342 } 1000 }
1343 1001
1344 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) 1002 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor)
1345 : predictor_(predictor) { 1003 : predictor_(predictor) {
1346 predictor_->SetObserverForTesting(this); 1004 predictor_->SetObserverForTesting(this);
1347 } 1005 }
1348 1006
1349 } // namespace predictors 1007 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698