Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
| 12 #include "chrome/browser/favicon/favicon_service.h" | 12 #include "chrome/browser/favicon/favicon_service.h" |
| 13 #include "chrome/browser/intents/web_intents_registry_factory.h" | 13 #include "chrome/browser/intents/web_intents_registry_factory.h" |
| 14 #include "chrome/browser/intents/cws_intents_registry_factory.h" | 14 #include "chrome/browser/intents/cws_intents_registry_factory.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/tab_contents/tab_util.h" | 16 #include "chrome/browser/tab_contents/tab_util.h" |
| 17 #include "chrome/browser/tabs/tab_strip_model.h" | 17 #include "chrome/browser/tabs/tab_strip_model.h" |
| 18 #include "chrome/browser/ui/browser_list.h" | 18 #include "chrome/browser/ui/browser_list.h" |
| 19 #include "chrome/browser/ui/browser_navigator.h" | 19 #include "chrome/browser/ui/browser_navigator.h" |
| 20 #include "chrome/browser/ui/intents/web_intent_picker.h" | 20 #include "chrome/browser/ui/intents/web_intent_picker.h" |
| 21 #include "chrome/browser/ui/intents/web_intent_picker_model.h" | 21 #include "chrome/browser/ui/intents/web_intent_picker_model.h" |
| 22 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 22 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 23 #include "chrome/browser/webdata/web_data_service.h" | 23 #include "chrome/browser/webdata/web_data_service.h" |
| 24 #include "chrome/common/chrome_notification_types.h" | 24 #include "chrome/common/chrome_notification_types.h" |
| 25 #include "content/browser/intents/intent_injector.h" | 25 #include "content/browser/intents/intent_injector.h" |
| 26 #include "content/public/browser/browser_thread.h" | |
| 26 #include "content/public/browser/notification_source.h" | 27 #include "content/public/browser/notification_source.h" |
| 27 #include "content/public/browser/web_contents.h" | 28 #include "content/public/browser/web_contents.h" |
| 28 #include "content/public/browser/web_intents_dispatcher.h" | 29 #include "content/public/browser/web_intents_dispatcher.h" |
| 30 #include "content/public/common/url_fetcher.h" | |
| 31 #include "content/public/common/url_fetcher_delegate.h" | |
| 32 #include "net/base/load_flags.h" | |
| 33 #include "skia/ext/image_operations.h" | |
| 29 #include "ui/gfx/codec/png_codec.h" | 34 #include "ui/gfx/codec/png_codec.h" |
| 35 #include "ui/gfx/favicon_size.h" | |
| 30 #include "ui/gfx/image/image.h" | 36 #include "ui/gfx/image/image.h" |
| 31 #include "webkit/glue/web_intent_service_data.h" | 37 #include "webkit/glue/web_intent_service_data.h" |
| 32 | 38 |
| 33 namespace { | 39 namespace { |
| 34 | 40 |
| 35 // Gets the favicon service for the profile in |tab_contents|. | 41 // Gets the favicon service for the profile in |tab_contents|. |
| 36 FaviconService* GetFaviconService(TabContentsWrapper* wrapper) { | 42 FaviconService* GetFaviconService(TabContentsWrapper* wrapper) { |
| 37 return wrapper->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); | 43 return wrapper->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); |
| 38 } | 44 } |
| 39 | 45 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 53 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE: | 59 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE: |
| 54 return WebIntentPickerModel::DISPOSITION_INLINE; | 60 return WebIntentPickerModel::DISPOSITION_INLINE; |
| 55 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW: | 61 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW: |
| 56 return WebIntentPickerModel::DISPOSITION_WINDOW; | 62 return WebIntentPickerModel::DISPOSITION_WINDOW; |
| 57 default: | 63 default: |
| 58 NOTREACHED(); | 64 NOTREACHED(); |
| 59 return WebIntentPickerModel::DISPOSITION_WINDOW; | 65 return WebIntentPickerModel::DISPOSITION_WINDOW; |
| 60 } | 66 } |
| 61 } | 67 } |
| 62 | 68 |
| 69 class URLFetcherTrampoline : public content::URLFetcherDelegate { | |
| 70 public: | |
| 71 typedef base::Callback<void(const content::URLFetcher* source)> Callback; | |
| 72 | |
| 73 explicit URLFetcherTrampoline(const Callback& callback) | |
| 74 : callback_(callback) {} | |
| 75 ~URLFetcherTrampoline() {} | |
| 76 | |
| 77 // content::URLFetcherDelegate implementation. | |
| 78 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE { | |
| 79 callback_.Run(source); | |
| 80 delete source; | |
| 81 delete this; | |
| 82 } | |
| 83 | |
| 84 private: | |
| 85 Callback callback_; | |
| 86 }; | |
| 87 | |
| 63 } // namespace | 88 } // namespace |
| 64 | 89 |
| 65 WebIntentPickerController::WebIntentPickerController( | 90 WebIntentPickerController::WebIntentPickerController( |
| 66 TabContentsWrapper* wrapper) | 91 TabContentsWrapper* wrapper) |
| 67 : wrapper_(wrapper), | 92 : wrapper_(wrapper), |
| 68 picker_(NULL), | 93 picker_(NULL), |
| 69 picker_model_(new WebIntentPickerModel()), | 94 picker_model_(new WebIntentPickerModel()), |
| 70 pending_async_count_(0), | 95 pending_async_count_(0), |
| 71 picker_shown_(false), | 96 picker_shown_(false), |
| 72 intents_dispatcher_(NULL), | 97 intents_dispatcher_(NULL), |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 picker_model_->UpdateFaviconAt(index, icon_image); | 303 picker_model_->UpdateFaviconAt(index, icon_image); |
| 279 return; | 304 return; |
| 280 } | 305 } |
| 281 } | 306 } |
| 282 | 307 |
| 283 AsyncOperationFinished(); | 308 AsyncOperationFinished(); |
| 284 } | 309 } |
| 285 | 310 |
| 286 void WebIntentPickerController::OnCWSIntentServicesAvailable( | 311 void WebIntentPickerController::OnCWSIntentServicesAvailable( |
| 287 const CWSIntentsRegistry::IntentExtensionList& extensions) { | 312 const CWSIntentsRegistry::IntentExtensionList& extensions) { |
| 313 net::URLRequestContextGetter* context = | |
|
Greg Billock
2012/02/23 22:15:50
It looks like this can just move down to SetReques
binji
2012/02/23 22:33:41
Done.
| |
| 314 wrapper_->profile()->GetRequestContext(); | |
| 315 | |
| 288 for (size_t i = 0; i < extensions.size(); ++i) { | 316 for (size_t i = 0; i < extensions.size(); ++i) { |
| 289 const CWSIntentsRegistry::IntentExtensionInfo& info = extensions[i]; | 317 const CWSIntentsRegistry::IntentExtensionInfo& info = extensions[i]; |
| 290 picker_model_->AddSuggestedExtension( | 318 picker_model_->AddSuggestedExtension( |
| 291 info.name, | 319 info.name, |
| 292 info.id, | 320 info.id, |
| 293 info.average_rating); | 321 info.average_rating); |
| 294 | 322 |
| 295 // TODO(binji): Fetch extension icon. | 323 pending_async_count_++; |
| 324 content::URLFetcher* icon_url_fetcher = content::URLFetcher::Create( | |
| 325 0, | |
| 326 info.icon_url, | |
| 327 content::URLFetcher::GET, | |
| 328 new URLFetcherTrampoline( | |
| 329 base::Bind( | |
| 330 &WebIntentPickerController::OnExtensionIconURLFetchComplete, | |
| 331 weak_ptr_factory_.GetWeakPtr(), info.id))); | |
| 332 | |
| 333 icon_url_fetcher->SetLoadFlags( | |
| 334 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 335 icon_url_fetcher->SetRequestContext(context); | |
| 336 icon_url_fetcher->Start(); | |
|
Greg Billock
2012/02/23 22:15:50
So the URLFetcher always delegates the callback to
binji
2012/02/23 22:33:41
I wasn't 100% on this, so I took a look. It looks
| |
| 296 } | 337 } |
| 297 | 338 |
| 298 AsyncOperationFinished(); | 339 AsyncOperationFinished(); |
| 299 } | 340 } |
| 300 | 341 |
| 342 void WebIntentPickerController::OnExtensionIconURLFetchComplete( | |
| 343 const string16& extension_id, const content::URLFetcher* source) { | |
| 344 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 345 if (source->GetResponseCode() != 200) { | |
| 346 AsyncOperationFinished(); | |
| 347 return; | |
| 348 } | |
| 349 | |
| 350 scoped_ptr<std::string> response(new std::string); | |
| 351 if (source->GetResponseAsString(response.get())) { | |
|
Greg Billock
2012/02/23 22:15:50
How about if (!...) { AsyncOpFinished; return; }
binji
2012/02/23 22:33:41
Done.
| |
| 352 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
|
Greg Billock
2012/02/23 22:15:50
Can take this out (you have it above now).
binji
2012/02/23 22:33:41
Oh, right. :-)
| |
| 353 | |
| 354 // Decode PNG and resize on worker thread. | |
| 355 content::BrowserThread::PostBlockingPoolTask( | |
| 356 FROM_HERE, | |
| 357 base::Bind(&DecodeExtensionIconAndResize, | |
| 358 base::Passed(&response), | |
| 359 base::Bind( | |
|
Greg Billock
2012/02/23 22:15:50
I think it'd read easier to extract these two call
binji
2012/02/23 22:33:41
Done.
| |
| 360 &WebIntentPickerController::OnExtensionIconAvailable, | |
| 361 weak_ptr_factory_.GetWeakPtr(), | |
| 362 extension_id), | |
| 363 base::Bind( | |
| 364 &WebIntentPickerController::OnExtensionIconUnavailable, | |
| 365 weak_ptr_factory_.GetWeakPtr(), | |
| 366 extension_id))); | |
| 367 } else { | |
| 368 AsyncOperationFinished(); | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 // static | |
| 373 void WebIntentPickerController::DecodeExtensionIconAndResize( | |
| 374 scoped_ptr<std::string> icon_response, | |
| 375 const ExtensionIconAvailableCallback& callback, | |
| 376 const base::Closure& unavailable_callback) { | |
| 377 SkBitmap icon_bitmap; | |
| 378 if (gfx::PNGCodec::Decode( | |
| 379 reinterpret_cast<const unsigned char*>(icon_response->data()), | |
| 380 icon_response->length(), | |
| 381 &icon_bitmap)) { | |
| 382 SkBitmap resized_icon = skia::ImageOperations::Resize( | |
| 383 icon_bitmap, | |
| 384 skia::ImageOperations::RESIZE_BEST, | |
| 385 gfx::kFaviconSize, gfx::kFaviconSize); | |
| 386 gfx::Image icon_image(new SkBitmap(resized_icon)); | |
| 387 | |
| 388 content::BrowserThread::PostTask( | |
| 389 content::BrowserThread::UI, | |
| 390 FROM_HERE, | |
| 391 base::Bind(callback, icon_image)); | |
|
Greg Billock
2012/02/23 22:15:50
It might be easier to get a WebIntentPickerControl
binji
2012/02/23 22:33:41
This was the original way I wrote it, but it didn'
Greg Billock
2012/02/23 22:51:30
You want to put some of these threading constraint
binji
2012/02/23 23:34:48
Done.
| |
| 392 } else { | |
| 393 content::BrowserThread::PostTask( | |
| 394 content::BrowserThread::UI, | |
| 395 FROM_HERE, | |
| 396 unavailable_callback); | |
| 397 } | |
| 398 } | |
| 399 | |
| 400 void WebIntentPickerController::OnExtensionIconAvailable( | |
| 401 const string16& extension_id, | |
| 402 const gfx::Image& icon_image) { | |
| 403 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image); | |
| 404 AsyncOperationFinished(); | |
| 405 } | |
| 406 | |
| 407 void WebIntentPickerController::OnExtensionIconUnavailable( | |
| 408 const string16& extension_id) { | |
| 409 AsyncOperationFinished(); | |
| 410 } | |
| 411 | |
| 301 void WebIntentPickerController::AsyncOperationFinished() { | 412 void WebIntentPickerController::AsyncOperationFinished() { |
| 413 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 302 if (--pending_async_count_ == 0) { | 414 if (--pending_async_count_ == 0) { |
| 303 picker_->OnPendingAsyncCompleted(); | 415 picker_->OnPendingAsyncCompleted(); |
| 304 } | 416 } |
| 305 } | 417 } |
| 306 | 418 |
| 307 void WebIntentPickerController::ClosePicker() { | 419 void WebIntentPickerController::ClosePicker() { |
| 308 if (picker_) { | 420 if (picker_) { |
| 309 picker_->Close(); | 421 picker_->Close(); |
| 310 } | 422 } |
| 311 } | 423 } |
| OLD | NEW |