Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / bitmap_fetcher / bitmap_fetcher_service.cc
blob17d4f313cd1cdf4367f472a4c080739e6559e65f
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/bitmap_fetcher/bitmap_fetcher_service.h"
7 #include "base/memory/weak_ptr.h"
8 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "net/base/load_flags.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
13 namespace {
15 const size_t kMaxRequests = 25; // Maximum number of inflight requests allowed.
16 const int kMaxCacheEntries = 5; // Maximum number of cache entries.
18 } // namespace.
20 class BitmapFetcherRequest {
21 public:
22 BitmapFetcherRequest(BitmapFetcherService::RequestId request_id,
23 BitmapFetcherService::Observer* observer);
24 ~BitmapFetcherRequest();
26 void NotifyImageChanged(const SkBitmap* bitmap);
27 BitmapFetcherService::RequestId request_id() const { return request_id_; }
29 // Weak ptr |fetcher| is used to identify associated fetchers.
30 void set_fetcher(const chrome::BitmapFetcher* fetcher) { fetcher_ = fetcher; }
31 const chrome::BitmapFetcher* get_fetcher() const { return fetcher_; }
33 private:
34 const BitmapFetcherService::RequestId request_id_;
35 scoped_ptr<BitmapFetcherService::Observer> observer_;
36 const chrome::BitmapFetcher* fetcher_;
38 DISALLOW_COPY_AND_ASSIGN(BitmapFetcherRequest);
41 BitmapFetcherRequest::BitmapFetcherRequest(
42 BitmapFetcherService::RequestId request_id,
43 BitmapFetcherService::Observer* observer)
44 : request_id_(request_id), observer_(observer) {
47 BitmapFetcherRequest::~BitmapFetcherRequest() {
50 void BitmapFetcherRequest::NotifyImageChanged(const SkBitmap* bitmap) {
51 if (bitmap && !bitmap->empty())
52 observer_->OnImageChanged(request_id_, *bitmap);
55 BitmapFetcherService::CacheEntry::CacheEntry() {
58 BitmapFetcherService::CacheEntry::~CacheEntry() {
61 BitmapFetcherService::BitmapFetcherService(content::BrowserContext* context)
62 : cache_(kMaxCacheEntries), current_request_id_(1), context_(context) {
65 BitmapFetcherService::~BitmapFetcherService() {
68 void BitmapFetcherService::CancelRequest(int request_id) {
69 ScopedVector<BitmapFetcherRequest>::iterator iter;
70 for (iter = requests_.begin(); iter != requests_.end(); ++iter) {
71 if ((*iter)->request_id() == request_id) {
72 requests_.erase(iter);
73 // Deliberately leave the associated fetcher running to populate cache.
74 return;
79 BitmapFetcherService::RequestId BitmapFetcherService::RequestImage(
80 const GURL& url,
81 Observer* observer) {
82 // Create a new request, assigning next available request ID.
83 ++current_request_id_;
84 if (current_request_id_ == REQUEST_ID_INVALID)
85 ++current_request_id_;
86 int request_id = current_request_id_;
87 scoped_ptr<BitmapFetcherRequest> request(
88 new BitmapFetcherRequest(request_id, observer));
90 // Reject invalid URLs.
91 if (!url.is_valid())
92 return REQUEST_ID_INVALID;
94 // Check for existing images first.
95 base::OwningMRUCache<GURL, CacheEntry*>::iterator iter = cache_.Get(url);
96 if (iter != cache_.end()) {
97 BitmapFetcherService::CacheEntry* entry = iter->second;
98 request->NotifyImageChanged(entry->bitmap.get());
100 // There is no request ID associated with this - data is already delivered.
101 return REQUEST_ID_INVALID;
104 // Limit number of simultaneous in-flight requests.
105 if (requests_.size() > kMaxRequests)
106 return REQUEST_ID_INVALID;
108 // Make sure there's a fetcher for this URL and attach to request.
109 const chrome::BitmapFetcher* fetcher = EnsureFetcherForUrl(url);
110 request->set_fetcher(fetcher);
112 requests_.push_back(request.release());
113 return requests_.back()->request_id();
116 void BitmapFetcherService::Prefetch(const GURL& url) {
117 if (url.is_valid())
118 EnsureFetcherForUrl(url);
121 chrome::BitmapFetcher* BitmapFetcherService::CreateFetcher(const GURL& url) {
122 chrome::BitmapFetcher* new_fetcher = new chrome::BitmapFetcher(url, this);
124 new_fetcher->Init(
125 context_->GetRequestContext(),
126 std::string(),
127 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
128 net::LOAD_NORMAL);
129 new_fetcher->Start();
130 return new_fetcher;
133 const chrome::BitmapFetcher* BitmapFetcherService::EnsureFetcherForUrl(
134 const GURL& url) {
135 const chrome::BitmapFetcher* fetcher = FindFetcherForUrl(url);
136 if (fetcher)
137 return fetcher;
139 chrome::BitmapFetcher* new_fetcher = CreateFetcher(url);
140 active_fetchers_.push_back(new_fetcher);
141 return new_fetcher;
144 const chrome::BitmapFetcher* BitmapFetcherService::FindFetcherForUrl(
145 const GURL& url) {
146 for (BitmapFetchers::iterator iter = active_fetchers_.begin();
147 iter != active_fetchers_.end();
148 ++iter) {
149 if (url == (*iter)->url())
150 return *iter;
152 return NULL;
155 void BitmapFetcherService::RemoveFetcher(const chrome::BitmapFetcher* fetcher) {
156 for (BitmapFetchers::iterator iter = active_fetchers_.begin();
157 iter != active_fetchers_.end();
158 ++iter) {
159 if (fetcher == (*iter)) {
160 active_fetchers_.erase(iter);
161 return;
164 NOTREACHED(); // RemoveFetcher should always result in removal.
167 void BitmapFetcherService::OnFetchComplete(const GURL& url,
168 const SkBitmap* bitmap) {
169 const chrome::BitmapFetcher* fetcher = FindFetcherForUrl(url);
170 DCHECK(fetcher);
172 // Notify all attached requests of completion.
173 ScopedVector<BitmapFetcherRequest>::iterator iter = requests_.begin();
174 while (iter != requests_.end()) {
175 if ((*iter)->get_fetcher() == fetcher) {
176 (*iter)->NotifyImageChanged(bitmap);
177 iter = requests_.erase(iter);
178 } else {
179 ++iter;
183 if (bitmap && !bitmap->isNull()) {
184 CacheEntry* entry = new CacheEntry;
185 entry->bitmap.reset(new SkBitmap(*bitmap));
186 cache_.Put(fetcher->url(), entry);
189 RemoveFetcher(fetcher);