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
3 // found in the LICENSE file.
5 #include "chrome/browser/predictors/resource_prefetcher_manager.h"
8 #include "base/stl_util.h"
9 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "net/url_request/url_request.h"
12 #include "net/url_request/url_request_context_getter.h"
14 using content::BrowserThread
;
16 namespace predictors
{
18 ResourcePrefetcherManager::ResourcePrefetcherManager(
19 ResourcePrefetchPredictor
* predictor
,
20 const ResourcePrefetchPredictorConfig
& config
,
21 net::URLRequestContextGetter
* context_getter
)
22 : predictor_(predictor
),
24 context_getter_(context_getter
) {
25 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
27 CHECK(context_getter_
);
30 ResourcePrefetcherManager::~ResourcePrefetcherManager() {
31 DCHECK(prefetcher_map_
.empty())
32 << "Did not call ShutdownOnUIThread or ShutdownOnIOThread. "
33 " Will leak Prefetcher pointers.";
36 void ResourcePrefetcherManager::ShutdownOnUIThread() {
37 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
40 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
41 base::Bind(&ResourcePrefetcherManager::ShutdownOnIOThread
,
45 void ResourcePrefetcherManager::ShutdownOnIOThread() {
46 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
47 STLDeleteContainerPairSecondPointers(prefetcher_map_
.begin(),
48 prefetcher_map_
.end());
51 void ResourcePrefetcherManager::MaybeAddPrefetch(
52 const NavigationID
& navigation_id
,
53 PrefetchKeyType key_type
,
54 scoped_ptr
<ResourcePrefetcher::RequestVector
> requests
) {
55 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
57 // Don't add a duplicate prefetch for the same host or URL.
58 std::string key
= key_type
== PREFETCH_KEY_TYPE_HOST
?
59 navigation_id
.main_frame_url
.host() : navigation_id
.main_frame_url
.spec();
60 if (ContainsKey(prefetcher_map_
, key
))
63 ResourcePrefetcher
* prefetcher
= new ResourcePrefetcher(
64 this, config_
, navigation_id
, key_type
, requests
.Pass());
65 prefetcher_map_
.insert(std::make_pair(key
, prefetcher
));
69 void ResourcePrefetcherManager::MaybeRemovePrefetch(
70 const NavigationID
& navigation_id
) {
71 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
73 // Look for a URL based prefetch first.
74 PrefetcherMap::iterator it
= prefetcher_map_
.find(
75 navigation_id
.main_frame_url
.spec());
76 if (it
!= prefetcher_map_
.end() &&
77 it
->second
->navigation_id() == navigation_id
) {
82 // No URL based prefetching, look for host based.
83 it
= prefetcher_map_
.find(navigation_id
.main_frame_url
.host());
84 if (it
!= prefetcher_map_
.end() &&
85 it
->second
->navigation_id() == navigation_id
) {
90 void ResourcePrefetcherManager::ResourcePrefetcherFinished(
91 ResourcePrefetcher
* resource_prefetcher
,
92 ResourcePrefetcher::RequestVector
* requests
) {
93 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
95 // |predictor_| can only be accessed from the UI thread.
96 scoped_ptr
<ResourcePrefetcher::RequestVector
> scoped_requests(requests
);
97 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
98 base::Bind(&ResourcePrefetcherManager::ResourcePrefetcherFinishedOnUI
,
100 resource_prefetcher
->navigation_id(),
101 resource_prefetcher
->key_type(),
102 base::Passed(&scoped_requests
)));
104 const GURL
& main_frame_url
=
105 resource_prefetcher
->navigation_id().main_frame_url
;
106 const std::string key
=
107 resource_prefetcher
->key_type() == PREFETCH_KEY_TYPE_HOST
?
108 main_frame_url
.host() : main_frame_url
.spec();
109 PrefetcherMap::iterator it
= prefetcher_map_
.find(key
);
110 DCHECK(it
!= prefetcher_map_
.end());
112 prefetcher_map_
.erase(it
);
115 void ResourcePrefetcherManager::ResourcePrefetcherFinishedOnUI(
116 const NavigationID
& navigation_id
,
117 PrefetchKeyType key_type
,
118 scoped_ptr
<ResourcePrefetcher::RequestVector
> requests
) {
119 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
121 // |predictor_| may have been set to NULL if the predictor is shutting down.
123 predictor_
->FinishedPrefetchForNavigation(navigation_id
,
129 net::URLRequestContext
* ResourcePrefetcherManager::GetURLRequestContext() {
130 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
132 return context_getter_
->GetURLRequestContext();
135 } // namespace predictors