• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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.
4 
5 #include "chrome/browser/predictors/resource_prefetcher_manager.h"
6 
7 #include "base/bind.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"
13 
14 using content::BrowserThread;
15 
16 namespace predictors {
17 
ResourcePrefetcherManager(ResourcePrefetchPredictor * predictor,const ResourcePrefetchPredictorConfig & config,net::URLRequestContextGetter * context_getter)18 ResourcePrefetcherManager::ResourcePrefetcherManager(
19     ResourcePrefetchPredictor* predictor,
20     const ResourcePrefetchPredictorConfig& config,
21     net::URLRequestContextGetter* context_getter)
22     : predictor_(predictor),
23       config_(config),
24       context_getter_(context_getter) {
25   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
26   CHECK(predictor_);
27   CHECK(context_getter_);
28 }
29 
~ResourcePrefetcherManager()30 ResourcePrefetcherManager::~ResourcePrefetcherManager() {
31   DCHECK(prefetcher_map_.empty())
32       << "Did not call ShutdownOnUIThread or ShutdownOnIOThread. "
33          " Will leak Prefetcher pointers.";
34 }
35 
ShutdownOnUIThread()36 void ResourcePrefetcherManager::ShutdownOnUIThread() {
37   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38 
39   predictor_ = NULL;
40   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
41       base::Bind(&ResourcePrefetcherManager::ShutdownOnIOThread,
42                  this));
43 }
44 
ShutdownOnIOThread()45 void ResourcePrefetcherManager::ShutdownOnIOThread() {
46   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
47   STLDeleteContainerPairSecondPointers(prefetcher_map_.begin(),
48                                        prefetcher_map_.end());
49 }
50 
MaybeAddPrefetch(const NavigationID & navigation_id,PrefetchKeyType key_type,scoped_ptr<ResourcePrefetcher::RequestVector> requests)51 void ResourcePrefetcherManager::MaybeAddPrefetch(
52     const NavigationID& navigation_id,
53     PrefetchKeyType key_type,
54     scoped_ptr<ResourcePrefetcher::RequestVector> requests) {
55   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
56 
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   PrefetcherMap::iterator prefetcher_it = prefetcher_map_.find(key);
61   if (prefetcher_it != prefetcher_map_.end())
62     return;
63 
64   ResourcePrefetcher* prefetcher = new ResourcePrefetcher(
65       this, config_, navigation_id, key_type, requests.Pass());
66   prefetcher_map_.insert(std::make_pair(key, prefetcher));
67   prefetcher->Start();
68 }
69 
MaybeRemovePrefetch(const NavigationID & navigation_id)70 void ResourcePrefetcherManager::MaybeRemovePrefetch(
71     const NavigationID& navigation_id) {
72   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
73 
74   // Look for a URL based prefetch first.
75   PrefetcherMap::iterator it = prefetcher_map_.find(
76       navigation_id.main_frame_url.spec());
77   if (it != prefetcher_map_.end() &&
78       it->second->navigation_id() == navigation_id) {
79     it->second->Stop();
80     return;
81   }
82 
83   // No URL based prefetching, look for host based.
84   it = prefetcher_map_.find(navigation_id.main_frame_url.host());
85   if (it != prefetcher_map_.end() &&
86       it->second->navigation_id() == navigation_id) {
87     it->second->Stop();
88   }
89 }
90 
ResourcePrefetcherFinished(ResourcePrefetcher * resource_prefetcher,ResourcePrefetcher::RequestVector * requests)91 void ResourcePrefetcherManager::ResourcePrefetcherFinished(
92     ResourcePrefetcher* resource_prefetcher,
93     ResourcePrefetcher::RequestVector* requests) {
94   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
95 
96   // |predictor_| can only be accessed from the UI thread.
97   scoped_ptr<ResourcePrefetcher::RequestVector> requests_ptr(requests);
98   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
99       base::Bind(&ResourcePrefetcherManager::ResourcePrefetcherFinishedOnUI,
100                  this,
101                  resource_prefetcher->navigation_id(),
102                  resource_prefetcher->key_type(),
103                  base::Passed(&requests_ptr)));
104 
105   const GURL& main_frame_url =
106       resource_prefetcher->navigation_id().main_frame_url;
107   const std::string key =
108       resource_prefetcher->key_type() == PREFETCH_KEY_TYPE_HOST ?
109           main_frame_url.host() : main_frame_url.spec();
110   PrefetcherMap::iterator it = prefetcher_map_.find(key);
111   DCHECK(it != prefetcher_map_.end());
112   delete it->second;
113   prefetcher_map_.erase(it);
114 }
115 
ResourcePrefetcherFinishedOnUI(const NavigationID & navigation_id,PrefetchKeyType key_type,scoped_ptr<ResourcePrefetcher::RequestVector> requests)116 void ResourcePrefetcherManager::ResourcePrefetcherFinishedOnUI(
117     const NavigationID& navigation_id,
118     PrefetchKeyType key_type,
119     scoped_ptr<ResourcePrefetcher::RequestVector> requests) {
120   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
121 
122   // |predictor_| may have been set to NULL if the predictor is shutting down.
123   if (predictor_)
124     predictor_->FinishedPrefetchForNavigation(navigation_id,
125                                               key_type,
126                                               requests.release());
127 }
128 
GetURLRequestContext()129 net::URLRequestContext* ResourcePrefetcherManager::GetURLRequestContext() {
130   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
131 
132   return context_getter_->GetURLRequestContext();
133 }
134 
135 }  // namespace predictors
136