OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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_picker_controller.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "chrome/browser/favicon/favicon_service.h" |
| 10 #include "chrome/browser/intents/web_intent_data.h" |
| 11 #include "chrome/browser/intents/web_intents_registry.h" |
| 12 #include "chrome/browser/intents/web_intents_registry_factory.h" |
| 13 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/browser/ui/intents/web_intent_picker.h" |
| 15 #include "chrome/browser/ui/intents/web_intent_picker_factory.h" |
| 16 #include "chrome/browser/webdata/web_data_service.h" |
| 17 #include "content/browser/tab_contents/tab_contents.h" |
| 18 #include "content/common/notification_source.h" |
| 19 #include "ui/gfx/codec/png_codec.h" |
| 20 |
| 21 namespace { |
| 22 |
| 23 // Gets the favicon service for the profile in |tab_contents|. |
| 24 FaviconService* GetFaviconService(TabContents* tab_contents) { |
| 25 Profile* profile = Profile::FromBrowserContext( |
| 26 tab_contents->browser_context()); |
| 27 return profile->GetFaviconService(Profile::EXPLICIT_ACCESS); |
| 28 } |
| 29 |
| 30 // Gets the web intents registry for the profile in |tab_contents|. |
| 31 WebIntentsRegistry* GetWebIntentsRegistry(TabContents* tab_contents) { |
| 32 Profile* profile = Profile::FromBrowserContext( |
| 33 tab_contents->browser_context()); |
| 34 return WebIntentsRegistryFactory::GetForProfile(profile); |
| 35 } |
| 36 |
| 37 } // namespace |
| 38 |
| 39 // A class that asynchronously fetches web intent data from the web intents |
| 40 // registry. |
| 41 class WebIntentPickerController::WebIntentDataFetcher |
| 42 : public WebIntentsRegistry::Consumer { |
| 43 public: |
| 44 WebIntentDataFetcher(WebIntentPickerController* controller, |
| 45 WebIntentsRegistry* web_intents_registry); |
| 46 ~WebIntentDataFetcher(); |
| 47 |
| 48 // Asynchronously fetches WebIntentData for the given |action| |type| pair. |
| 49 void Fetch(const string16& action, const string16& type); |
| 50 |
| 51 // Cancels the WebDataService request. |
| 52 void Cancel(); |
| 53 |
| 54 private: |
| 55 // WebIntentsRegistry::Consumer implementation. |
| 56 virtual void OnIntentsQueryDone( |
| 57 WebIntentsRegistry::QueryID, |
| 58 const std::vector<WebIntentData>& intents) OVERRIDE; |
| 59 |
| 60 // A weak pointer to the picker controller. |
| 61 WebIntentPickerController* controller_; |
| 62 |
| 63 // A weak pointer to the web intents registry. |
| 64 WebIntentsRegistry* web_intents_registry_; |
| 65 |
| 66 // The ID of the current web intents request. The value will be -1 if |
| 67 // there is no request in flight. |
| 68 WebIntentsRegistry::QueryID query_id_; |
| 69 }; |
| 70 |
| 71 // A class that asynchronously fetches favicons for a vector of URLs. |
| 72 class WebIntentPickerController::FaviconFetcher { |
| 73 public: |
| 74 FaviconFetcher(WebIntentPickerController* controller, |
| 75 FaviconService *favicon_service); |
| 76 ~FaviconFetcher(); |
| 77 |
| 78 // Asynchronously fetches favicons for the each URL in |urls|. |
| 79 void Fetch(const std::vector<GURL>& urls); |
| 80 |
| 81 // Cancels all favicon requests. |
| 82 void Cancel(); |
| 83 |
| 84 private: |
| 85 // Callback called when a favicon is received. |
| 86 void OnFaviconDataAvailable(FaviconService::Handle handle, |
| 87 history::FaviconData favicon_data); |
| 88 |
| 89 // A weak pointer to the picker controller. |
| 90 WebIntentPickerController* controller_; |
| 91 |
| 92 // A weak pointer to the favicon service. |
| 93 FaviconService* favicon_service_; |
| 94 |
| 95 // The Consumer to handle asynchronous favicon requests. |
| 96 CancelableRequestConsumerTSimple<size_t> load_consumer_; |
| 97 |
| 98 DISALLOW_COPY_AND_ASSIGN(FaviconFetcher); |
| 99 }; |
| 100 |
| 101 WebIntentPickerController::WebIntentPickerController( |
| 102 TabContents* tab_contents, |
| 103 WebIntentPickerFactory* factory) |
| 104 : tab_contents_(tab_contents), |
| 105 picker_factory_(factory), |
| 106 web_intent_data_fetcher_( |
| 107 new WebIntentDataFetcher(this, |
| 108 GetWebIntentsRegistry(tab_contents))), |
| 109 favicon_fetcher_( |
| 110 new FaviconFetcher(this, GetFaviconService(tab_contents))), |
| 111 picker_(NULL), |
| 112 pending_async_count_(0) { |
| 113 NavigationController* controller = &tab_contents->controller(); |
| 114 registrar_.Add(this, content::NOTIFICATION_LOAD_START, |
| 115 Source<NavigationController>(controller)); |
| 116 registrar_.Add(this, content::NOTIFICATION_TAB_CLOSING, |
| 117 Source<NavigationController>(controller)); |
| 118 } |
| 119 |
| 120 WebIntentPickerController::~WebIntentPickerController() { |
| 121 } |
| 122 |
| 123 void WebIntentPickerController::ShowDialog(const string16& action, |
| 124 const string16& type) { |
| 125 if (picker_ != NULL) |
| 126 return; |
| 127 |
| 128 picker_ = picker_factory_->Create(tab_contents_, this); |
| 129 |
| 130 // TODO(binji) Remove this check when there are implementations of the picker |
| 131 // for windows and mac. |
| 132 if (picker_ == NULL) |
| 133 return; |
| 134 |
| 135 web_intent_data_fetcher_->Fetch(action, type); |
| 136 } |
| 137 |
| 138 void WebIntentPickerController::Observe(int type, |
| 139 const NotificationSource& source, |
| 140 const NotificationDetails& details) { |
| 141 DCHECK(type == content::NOTIFICATION_LOAD_START || |
| 142 type == content::NOTIFICATION_TAB_CLOSING); |
| 143 ClosePicker(); |
| 144 } |
| 145 |
| 146 void WebIntentPickerController::OnServiceChosen(size_t index) { |
| 147 DCHECK(index < urls_.size()); |
| 148 |
| 149 // TODO(binji) Send the chosen service back to the renderer. |
| 150 LOG(INFO) << "Chose index: " << index << " url: " << urls_[index]; |
| 151 ClosePicker(); |
| 152 } |
| 153 |
| 154 void WebIntentPickerController::OnCancelled() { |
| 155 // TODO(binji) Tell the renderer that the intent was cancelled. |
| 156 ClosePicker(); |
| 157 } |
| 158 |
| 159 void WebIntentPickerController::OnWebIntentDataAvailable( |
| 160 const std::vector<WebIntentData>& intent_data) { |
| 161 urls_.clear(); |
| 162 for (size_t i = 0; i < intent_data.size(); ++i) { |
| 163 urls_.push_back(intent_data[i].service_url); |
| 164 } |
| 165 |
| 166 // Tell the picker to initialize N urls to the default favicon |
| 167 picker_->SetServiceURLs(urls_); |
| 168 favicon_fetcher_->Fetch(urls_); |
| 169 pending_async_count_--; |
| 170 } |
| 171 |
| 172 void WebIntentPickerController::OnFaviconDataAvailable( |
| 173 size_t index, |
| 174 const SkBitmap& icon_bitmap) { |
| 175 picker_->SetServiceIcon(index, icon_bitmap); |
| 176 pending_async_count_--; |
| 177 } |
| 178 |
| 179 void WebIntentPickerController::OnFaviconDataUnavailable(size_t index) { |
| 180 picker_->SetDefaultServiceIcon(index); |
| 181 pending_async_count_--; |
| 182 } |
| 183 |
| 184 void WebIntentPickerController::ClosePicker() { |
| 185 if (picker_) { |
| 186 picker_factory_->ClosePicker(picker_); |
| 187 picker_ = NULL; |
| 188 } |
| 189 } |
| 190 |
| 191 WebIntentPickerController::WebIntentDataFetcher::WebIntentDataFetcher( |
| 192 WebIntentPickerController* controller, |
| 193 WebIntentsRegistry* web_intents_registry) |
| 194 : controller_(controller), |
| 195 web_intents_registry_(web_intents_registry), |
| 196 query_id_(-1) { |
| 197 } |
| 198 |
| 199 WebIntentPickerController::WebIntentDataFetcher::~WebIntentDataFetcher() { |
| 200 } |
| 201 |
| 202 void WebIntentPickerController::WebIntentDataFetcher::Fetch( |
| 203 const string16& action, |
| 204 const string16& type) { |
| 205 DCHECK(query_id_ == -1) << "Fetch already in process."; |
| 206 controller_->pending_async_count_++; |
| 207 query_id_ = web_intents_registry_->GetIntentProviders(action, this); |
| 208 } |
| 209 |
| 210 void WebIntentPickerController::WebIntentDataFetcher::OnIntentsQueryDone( |
| 211 WebIntentsRegistry::QueryID, |
| 212 const std::vector<WebIntentData>& intents) { |
| 213 controller_->OnWebIntentDataAvailable(intents); |
| 214 query_id_ = -1; |
| 215 } |
| 216 |
| 217 WebIntentPickerController::FaviconFetcher::FaviconFetcher( |
| 218 WebIntentPickerController* controller, |
| 219 FaviconService* favicon_service) |
| 220 : controller_(controller), |
| 221 favicon_service_(favicon_service) { |
| 222 } |
| 223 |
| 224 WebIntentPickerController::FaviconFetcher::~FaviconFetcher() { |
| 225 } |
| 226 |
| 227 void WebIntentPickerController::FaviconFetcher::Fetch( |
| 228 const std::vector<GURL>& urls) { |
| 229 if (!favicon_service_) |
| 230 return; |
| 231 |
| 232 for (size_t index = 0; index < urls.size(); ++index) { |
| 233 controller_->pending_async_count_++; |
| 234 FaviconService::Handle handle = favicon_service_->GetFaviconForURL( |
| 235 urls[index], |
| 236 history::FAVICON, |
| 237 &load_consumer_, |
| 238 NewCallback(this, &WebIntentPickerController::FaviconFetcher:: |
| 239 OnFaviconDataAvailable)); |
| 240 load_consumer_.SetClientData(favicon_service_, handle, index); |
| 241 } |
| 242 } |
| 243 |
| 244 void WebIntentPickerController::FaviconFetcher::Cancel() { |
| 245 load_consumer_.CancelAllRequests(); |
| 246 } |
| 247 |
| 248 void WebIntentPickerController::FaviconFetcher::OnFaviconDataAvailable( |
| 249 FaviconService::Handle handle, |
| 250 history::FaviconData favicon_data) { |
| 251 size_t index = load_consumer_.GetClientDataForCurrentRequest(); |
| 252 if (favicon_data.is_valid()) { |
| 253 SkBitmap icon_bitmap; |
| 254 |
| 255 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), |
| 256 favicon_data.image_data->size(), |
| 257 &icon_bitmap)) { |
| 258 controller_->OnFaviconDataAvailable(index, icon_bitmap); |
| 259 return; |
| 260 } |
| 261 } |
| 262 |
| 263 controller_->OnFaviconDataUnavailable(index); |
| 264 } |
OLD | NEW |