| OLD | NEW |
| (Empty) |
| 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/ui/intents/web_intent_icon_loader.h" | |
| 6 | |
| 7 #include "chrome/browser/favicon/favicon_service.h" | |
| 8 #include "chrome/browser/favicon/favicon_service_factory.h" | |
| 9 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | |
| 10 #include "content/public/browser/browser_thread.h" | |
| 11 #include "net/base/load_flags.h" | |
| 12 #include "net/url_request/url_fetcher.h" | |
| 13 #include "net/url_request/url_fetcher_delegate.h" | |
| 14 #include "skia/ext/image_operations.h" | |
| 15 #include "ui/gfx/codec/png_codec.h" | |
| 16 #include "ui/gfx/favicon_size.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 typedef base::Callback<void(const gfx::Image&)> | |
| 21 ExtensionIconAvailableCallback; | |
| 22 | |
| 23 // Decodes an |icon_repsonse| as delivered via URLFetcher. The response should | |
| 24 // be in PNG format, but is not guaranteed to be. Posts the |callback| task | |
| 25 // when done. | |
| 26 void DecodeExtensionIconAndResize( | |
| 27 scoped_ptr<std::string> icon_response, | |
| 28 const ExtensionIconAvailableCallback& callback) { | |
| 29 SkBitmap icon_bitmap; | |
| 30 if (gfx::PNGCodec::Decode( | |
| 31 reinterpret_cast<const unsigned char*>(icon_response->data()), | |
| 32 icon_response->length(), | |
| 33 &icon_bitmap)) { | |
| 34 SkBitmap resized_icon = skia::ImageOperations::Resize( | |
| 35 icon_bitmap, | |
| 36 skia::ImageOperations::RESIZE_BEST, | |
| 37 gfx::kFaviconSize, gfx::kFaviconSize); | |
| 38 gfx::Image icon_image = gfx::Image::CreateFrom1xBitmap(resized_icon); | |
| 39 | |
| 40 content::BrowserThread::PostTask( | |
| 41 content::BrowserThread::UI, | |
| 42 FROM_HERE, | |
| 43 base::Bind(callback, icon_image)); | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 // Self-deleting trampoline that forwards A URLFetcher response to a callback. | |
| 48 class URLFetcherTrampoline : public net::URLFetcherDelegate { | |
| 49 public: | |
| 50 typedef base::Callback<void(const net::URLFetcher* source)> | |
| 51 ForwardingCallback; | |
| 52 | |
| 53 explicit URLFetcherTrampoline(const ForwardingCallback& callback) | |
| 54 : callback_(callback) {} | |
| 55 virtual ~URLFetcherTrampoline() {} | |
| 56 | |
| 57 // net::URLFetcherDelegate implementation. | |
| 58 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; | |
| 59 | |
| 60 private: | |
| 61 // Fowarding callback from |OnURLFetchComplete|. | |
| 62 ForwardingCallback callback_; | |
| 63 }; | |
| 64 | |
| 65 void URLFetcherTrampoline::OnURLFetchComplete( | |
| 66 const net::URLFetcher* source) { | |
| 67 DCHECK(!callback_.is_null()); | |
| 68 callback_.Run(source); | |
| 69 delete source; | |
| 70 delete this; | |
| 71 } | |
| 72 | |
| 73 } | |
| 74 | |
| 75 namespace web_intents { | |
| 76 | |
| 77 IconLoader::IconLoader(Profile* profile, | |
| 78 WebIntentPickerModel* model) | |
| 79 : profile_(profile), | |
| 80 model_(model), | |
| 81 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
| 82 } | |
| 83 | |
| 84 IconLoader::~IconLoader() {} | |
| 85 | |
| 86 void IconLoader::LoadFavicon(const GURL& url) { | |
| 87 FaviconService* favicon_service = | |
| 88 FaviconServiceFactory::GetForProfile(profile_, | |
| 89 Profile::EXPLICIT_ACCESS); | |
| 90 | |
| 91 favicon_service->GetFaviconImageForURL( | |
| 92 FaviconService::FaviconForURLParams( | |
| 93 profile_, url, history::FAVICON, gfx::kFaviconSize), | |
| 94 base::Bind( | |
| 95 &IconLoader::OnFaviconDataAvailable, | |
| 96 weak_ptr_factory_.GetWeakPtr(), url), | |
| 97 &cancelable_task_tracker_); | |
| 98 } | |
| 99 | |
| 100 void IconLoader::LoadExtensionIcon(const GURL& url, | |
| 101 const std::string& extension_id) { | |
| 102 | |
| 103 net::URLFetcher* icon_url_fetcher = net::URLFetcher::Create( | |
| 104 0, | |
| 105 url, | |
| 106 net::URLFetcher::GET, | |
| 107 new URLFetcherTrampoline( | |
| 108 base::Bind( | |
| 109 &IconLoader::OnExtensionIconURLFetchComplete, | |
| 110 weak_ptr_factory_.GetWeakPtr(), extension_id))); | |
| 111 | |
| 112 icon_url_fetcher->SetLoadFlags( | |
| 113 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 114 icon_url_fetcher->SetRequestContext(profile_->GetRequestContext()); | |
| 115 icon_url_fetcher->Start(); | |
| 116 } | |
| 117 | |
| 118 void IconLoader::OnFaviconDataAvailable( | |
| 119 const GURL& url, | |
| 120 const history::FaviconImageResult& image_result) { | |
| 121 if (!image_result.image.IsEmpty()) | |
| 122 model_->UpdateFaviconForServiceWithURL(url, image_result.image); | |
| 123 } | |
| 124 | |
| 125 void IconLoader::OnExtensionIconURLFetchComplete( | |
| 126 const std::string& extension_id, const net::URLFetcher* source) { | |
| 127 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 128 if (source->GetResponseCode() != 200) | |
| 129 return; | |
| 130 | |
| 131 scoped_ptr<std::string> response(new std::string); | |
| 132 if (!source->GetResponseAsString(response.get())) | |
| 133 return; | |
| 134 | |
| 135 // Decoding the extension icon needs to happen on a worker thread, not the | |
| 136 // UI thread. However, callbacks to IconLoader need to happen on the UI | |
| 137 // thread, since IconLoader lives on UI thread. (And WeakPtrs must be de- | |
| 138 // referenced on the thread they were created on). | |
| 139 ExtensionIconAvailableCallback available_callback = | |
| 140 base::Bind( | |
| 141 &IconLoader::OnExtensionIconAvailable, | |
| 142 weak_ptr_factory_.GetWeakPtr(), | |
| 143 extension_id); | |
| 144 | |
| 145 // Decode PNG and resize on worker thread. | |
| 146 content::BrowserThread::PostBlockingPoolTask( | |
| 147 FROM_HERE, | |
| 148 base::Bind(&DecodeExtensionIconAndResize, | |
| 149 base::Passed(&response), | |
| 150 available_callback)); | |
| 151 } | |
| 152 | |
| 153 void IconLoader::OnExtensionIconAvailable( | |
| 154 const std::string& extension_id, | |
| 155 const gfx::Image& icon_image) { | |
| 156 model_->SetSuggestedExtensionIconWithId(extension_id, icon_image); | |
| 157 } | |
| 158 | |
| 159 } // namespace web_intents | |
| OLD | NEW |