Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1497)

Side by Side Diff: chrome/browser/ui/intents/web_intent_picker_controller.cc

Issue 9430025: [Web Intents] WebIntentsPickerController will now fetch icon for suggested extensions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/public/browser/browser_thread.h"
25 #include "content/public/browser/notification_source.h" 26 #include "content/public/browser/notification_source.h"
26 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_intents_dispatcher.h" 28 #include "content/public/browser/web_intents_dispatcher.h"
29 #include "content/public/common/url_fetcher.h"
30 #include "content/public/common/url_fetcher_delegate.h"
31 #include "net/base/load_flags.h"
32 #include "skia/ext/image_operations.h"
28 #include "ui/gfx/codec/png_codec.h" 33 #include "ui/gfx/codec/png_codec.h"
34 #include "ui/gfx/favicon_size.h"
29 #include "ui/gfx/image/image.h" 35 #include "ui/gfx/image/image.h"
30 #include "webkit/glue/web_intent_service_data.h" 36 #include "webkit/glue/web_intent_service_data.h"
31 37
32 namespace { 38 namespace {
33 39
34 // Gets the favicon service for the profile in |tab_contents|. 40 // Gets the favicon service for the profile in |tab_contents|.
35 FaviconService* GetFaviconService(TabContentsWrapper* wrapper) { 41 FaviconService* GetFaviconService(TabContentsWrapper* wrapper) {
36 return wrapper->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); 42 return wrapper->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS);
37 } 43 }
38 44
(...skipping 13 matching lines...) Expand all
52 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE: 58 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE:
53 return WebIntentPickerModel::DISPOSITION_INLINE; 59 return WebIntentPickerModel::DISPOSITION_INLINE;
54 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW: 60 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW:
55 return WebIntentPickerModel::DISPOSITION_WINDOW; 61 return WebIntentPickerModel::DISPOSITION_WINDOW;
56 default: 62 default:
57 NOTREACHED(); 63 NOTREACHED();
58 return WebIntentPickerModel::DISPOSITION_WINDOW; 64 return WebIntentPickerModel::DISPOSITION_WINDOW;
59 } 65 }
60 } 66 }
61 67
68 class URLFetcherTrampoline : public content::URLFetcherDelegate {
69 public:
70 typedef base::Callback<void(const content::URLFetcher* source)> Callback;
71
72 explicit URLFetcherTrampoline(const Callback& callback)
73 : callback_(callback) {}
74 ~URLFetcherTrampoline() {}
75
76 // content::URLFetcherDelegate implementation.
77 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE {
78 callback_.Run(source);
79 delete source;
80 delete this;
81 }
82
83 private:
84 Callback callback_;
85 };
86
62 } // namespace 87 } // namespace
63 88
64 WebIntentPickerController::WebIntentPickerController( 89 WebIntentPickerController::WebIntentPickerController(
65 TabContentsWrapper* wrapper) 90 TabContentsWrapper* wrapper)
66 : wrapper_(wrapper), 91 : wrapper_(wrapper),
67 picker_(NULL), 92 picker_(NULL),
68 picker_model_(new WebIntentPickerModel()), 93 picker_model_(new WebIntentPickerModel()),
69 pending_async_count_(0), 94 pending_async_count_(0),
70 picker_shown_(false), 95 picker_shown_(false),
71 intents_dispatcher_(NULL), 96 intents_dispatcher_(NULL),
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 309
285 void WebIntentPickerController::OnCWSIntentServicesAvailable( 310 void WebIntentPickerController::OnCWSIntentServicesAvailable(
286 const CWSIntentsRegistry::IntentExtensionList& extensions) { 311 const CWSIntentsRegistry::IntentExtensionList& extensions) {
287 for (size_t i = 0; i < extensions.size(); ++i) { 312 for (size_t i = 0; i < extensions.size(); ++i) {
288 const CWSIntentsRegistry::IntentExtensionInfo& info = extensions[i]; 313 const CWSIntentsRegistry::IntentExtensionInfo& info = extensions[i];
289 picker_model_->AddSuggestedExtension( 314 picker_model_->AddSuggestedExtension(
290 info.name, 315 info.name,
291 info.id, 316 info.id,
292 info.average_rating); 317 info.average_rating);
293 318
294 // TODO(binji): Fetch extension icon. 319 pending_async_count_++;
320 content::URLFetcher* icon_url_fetcher = content::URLFetcher::Create(
321 0,
322 info.icon_url,
323 content::URLFetcher::GET,
324 new URLFetcherTrampoline(
325 base::Bind(
326 &WebIntentPickerController::OnExtensionIconURLFetchComplete,
327 weak_ptr_factory_.GetWeakPtr(), info.id)));
328
329 icon_url_fetcher->SetLoadFlags(
330 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
331 icon_url_fetcher->SetRequestContext(
332 wrapper_->profile()->GetRequestContext());
333 icon_url_fetcher->Start();
295 } 334 }
296 335
297 AsyncOperationFinished(); 336 AsyncOperationFinished();
298 } 337 }
299 338
339 void WebIntentPickerController::OnExtensionIconURLFetchComplete(
340 const string16& extension_id, const content::URLFetcher* source) {
341 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
342 if (source->GetResponseCode() != 200) {
343 AsyncOperationFinished();
344 return;
345 }
346
347 scoped_ptr<std::string> response(new std::string);
348 if (!source->GetResponseAsString(response.get())) {
349 AsyncOperationFinished();
350 return;
351 }
352
353 // I'd like to have the worker thread post a task directly to the UI thread
354 // to call OnExtensionIcon[Un]Available, but this doesn't work: To do so
355 // would require DecodeExtensionIconAndResize to be a member function (so it
356 // has access to |this|) but a weak pointer cannot be dereferenced on a
357 // thread other than the thread where the WeakPtrFactory was created. Since
358 // the stored |this| pointer is weak, DecodeExtensionIconAndResize asserts
359 // before it even starts.
360 //
361 // Instead, I package up the callbacks that I want the worker thread to call,
362 // and make DecodeExtensionIconAndResize static. The stored weak |this|
363 // pointers are not dereferenced until invocation (on the UI thread).
364 ExtensionIconAvailableCallback available_callback =
365 base::Bind(
366 &WebIntentPickerController::OnExtensionIconAvailable,
367 weak_ptr_factory_.GetWeakPtr(),
368 extension_id);
369 base::Closure unavailable_callback =
370 base::Bind(
371 &WebIntentPickerController::OnExtensionIconUnavailable,
372 weak_ptr_factory_.GetWeakPtr(),
373 extension_id);
374
375 // Decode PNG and resize on worker thread.
376 content::BrowserThread::PostBlockingPoolTask(
377 FROM_HERE,
378 base::Bind(&DecodeExtensionIconAndResize,
379 base::Passed(&response),
380 available_callback,
381 unavailable_callback));
382 }
383
384 // static
385 void WebIntentPickerController::DecodeExtensionIconAndResize(
386 scoped_ptr<std::string> icon_response,
387 const ExtensionIconAvailableCallback& callback,
388 const base::Closure& unavailable_callback) {
389 SkBitmap icon_bitmap;
390 if (gfx::PNGCodec::Decode(
391 reinterpret_cast<const unsigned char*>(icon_response->data()),
392 icon_response->length(),
393 &icon_bitmap)) {
394 SkBitmap resized_icon = skia::ImageOperations::Resize(
395 icon_bitmap,
396 skia::ImageOperations::RESIZE_BEST,
397 gfx::kFaviconSize, gfx::kFaviconSize);
398 gfx::Image icon_image(new SkBitmap(resized_icon));
399
400 content::BrowserThread::PostTask(
401 content::BrowserThread::UI,
402 FROM_HERE,
403 base::Bind(callback, icon_image));
404 } else {
405 content::BrowserThread::PostTask(
406 content::BrowserThread::UI,
407 FROM_HERE,
408 unavailable_callback);
409 }
410 }
411
412 void WebIntentPickerController::OnExtensionIconAvailable(
413 const string16& extension_id,
414 const gfx::Image& icon_image) {
415 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image);
416 AsyncOperationFinished();
417 }
418
419 void WebIntentPickerController::OnExtensionIconUnavailable(
420 const string16& extension_id) {
421 AsyncOperationFinished();
422 }
423
300 void WebIntentPickerController::AsyncOperationFinished() { 424 void WebIntentPickerController::AsyncOperationFinished() {
425 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
301 if (--pending_async_count_ == 0) { 426 if (--pending_async_count_ == 0) {
302 picker_->OnPendingAsyncCompleted(); 427 picker_->OnPendingAsyncCompleted();
303 } 428 }
304 } 429 }
305 430
306 void WebIntentPickerController::ClosePicker() { 431 void WebIntentPickerController::ClosePicker() {
307 if (picker_) { 432 if (picker_) {
308 picker_->Close(); 433 picker_->Close();
309 } 434 }
310 } 435 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698