16d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 26d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 36d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// found in the LICENSE file. 46d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 56d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" 66d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/memory/weak_ptr.h" 86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" 96d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "net/base/load_flags.h" 116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)namespace { 146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const size_t kMaxRequests = 25; // Maximum number of inflight requests allowed. 166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const int kMaxCacheEntries = 5; // Maximum number of cache entries. 176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} // namespace. 196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)class BitmapFetcherRequest { 216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) public: 226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BitmapFetcherRequest(BitmapFetcherService::RequestId request_id, 236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BitmapFetcherService::Observer* observer); 246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ~BitmapFetcherRequest(); 256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void NotifyImageChanged(const SkBitmap& bitmap); 276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BitmapFetcherService::RequestId request_id() const { return request_id_; } 286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Weak ptr |fetcher| is used to identify associated fetchers. 306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void set_fetcher(const chrome::BitmapFetcher* fetcher) { fetcher_ = fetcher; } 316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const chrome::BitmapFetcher* get_fetcher() const { return fetcher_; } 326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private: 346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const BitmapFetcherService::RequestId request_id_; 356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<BitmapFetcherService::Observer> observer_; 366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const chrome::BitmapFetcher* fetcher_; 376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BitmapFetcherRequest); 396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}; 406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherRequest::BitmapFetcherRequest( 426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BitmapFetcherService::RequestId request_id, 436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BitmapFetcherService::Observer* observer) 446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : request_id_(request_id), observer_(observer) { 456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherRequest::~BitmapFetcherRequest() { 486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BitmapFetcherRequest::NotifyImageChanged(const SkBitmap& bitmap) { 516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!bitmap.empty()) 526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) observer_->OnImageChanged(request_id_, bitmap); 536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherService::CacheEntry::CacheEntry() { 566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherService::CacheEntry::~CacheEntry() { 596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherService::BitmapFetcherService(content::BrowserContext* context) 626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) : cache_(kMaxCacheEntries), current_request_id_(1), context_(context) { 636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherService::~BitmapFetcherService() { 666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BitmapFetcherService::CancelRequest(int request_id) { 696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ScopedVector<BitmapFetcherRequest>::iterator iter; 706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (iter = requests_.begin(); iter != requests_.end(); ++iter) { 716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if ((*iter)->request_id() == request_id) { 726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) requests_.erase(iter); 736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Deliberately leave the associated fetcher running to populate cache. 746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)BitmapFetcherService::RequestId BitmapFetcherService::RequestImage( 806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const GURL& url, 816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) Observer* observer) { 826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Create a new request, assigning next available request ID. 836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ++current_request_id_; 846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (current_request_id_ == REQUEST_ID_INVALID) 856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ++current_request_id_; 866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int request_id = current_request_id_; 876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<BitmapFetcherRequest> request( 886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) new BitmapFetcherRequest(request_id, observer)); 896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 9034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // Reject invalid URLs. 9134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!url.is_valid()) 9234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return REQUEST_ID_INVALID; 9334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Check for existing images first. 956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::OwningMRUCache<GURL, CacheEntry*>::iterator iter = cache_.Get(url); 966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (iter != cache_.end()) { 976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BitmapFetcherService::CacheEntry* entry = iter->second; 986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) request->NotifyImageChanged(*(entry->bitmap.get())); 996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // There is no request ID associated with this - data is already delivered. 1016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return REQUEST_ID_INVALID; 1026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Limit number of simultaneous in-flight requests. 1056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (requests_.size() > kMaxRequests) 1066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return REQUEST_ID_INVALID; 1076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Make sure there's a fetcher for this URL and attach to request. 1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const chrome::BitmapFetcher* fetcher = EnsureFetcherForUrl(url); 1106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) request->set_fetcher(fetcher); 1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) requests_.push_back(request.release()); 1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return requests_.back()->request_id(); 1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BitmapFetcherService::Prefetch(const GURL& url) { 1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (url.is_valid()) 1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EnsureFetcherForUrl(url); 1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)chrome::BitmapFetcher* BitmapFetcherService::CreateFetcher(const GURL& url) { 1226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) chrome::BitmapFetcher* new_fetcher = new chrome::BitmapFetcher(url, this); 1236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) new_fetcher->Start( 1256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) context_->GetRequestContext(), 1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::string(), 1276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, 1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) net::LOAD_NORMAL); 1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return new_fetcher; 1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const chrome::BitmapFetcher* BitmapFetcherService::EnsureFetcherForUrl( 1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const GURL& url) { 1346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const chrome::BitmapFetcher* fetcher = FindFetcherForUrl(url); 1356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (fetcher) 1366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return fetcher; 1376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) chrome::BitmapFetcher* new_fetcher = CreateFetcher(url); 1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) active_fetchers_.push_back(new_fetcher); 1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return new_fetcher; 1416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const chrome::BitmapFetcher* BitmapFetcherService::FindFetcherForUrl( 1446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const GURL& url) { 1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (BitmapFetchers::iterator iter = active_fetchers_.begin(); 1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) iter != active_fetchers_.end(); 1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ++iter) { 1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (url == (*iter)->url()) 1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return *iter; 1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return NULL; 1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BitmapFetcherService::RemoveFetcher(const chrome::BitmapFetcher* fetcher) { 1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (BitmapFetchers::iterator iter = active_fetchers_.begin(); 1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) iter != active_fetchers_.end(); 1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ++iter) { 1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (fetcher == (*iter)) { 1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) active_fetchers_.erase(iter); 1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) NOTREACHED(); // RemoveFetcher should always result in removal. 1646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BitmapFetcherService::OnFetchComplete(const GURL url, 1676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const SkBitmap* bitmap) { 1686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DCHECK(bitmap); // can never be NULL, guaranteed by BitmapFetcher. 1696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const chrome::BitmapFetcher* fetcher = FindFetcherForUrl(url); 1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DCHECK(fetcher); 1726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Notify all attached requests of completion. 1746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ScopedVector<BitmapFetcherRequest>::iterator iter = requests_.begin(); 1756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) while (iter != requests_.end()) { 1766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if ((*iter)->get_fetcher() == fetcher) { 1776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) (*iter)->NotifyImageChanged(*bitmap); 1786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) iter = requests_.erase(iter); 1796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else { 1806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ++iter; 1816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!bitmap->isNull()) { 1856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) CacheEntry* entry = new CacheEntry; 1866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) entry->bitmap.reset(new SkBitmap(*bitmap)); 1876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) cache_.Put(fetcher->url(), entry); 1886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) RemoveFetcher(fetcher); 1916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 192