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

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: favicon->icon Created 8 years, 10 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/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
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
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 =
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();
296 } 337 }
297 338
298 AsyncOperationFinished(); 339 AsyncOperationFinished();
299 } 340 }
300 341
342 void WebIntentPickerController::OnExtensionIconURLFetchComplete(
Greg Billock 2012/02/23 18:38:34 This'll get called by the fetcher thread, right? I
binji 2012/02/23 19:06:13 AFAIK this is called back on the UI thread, so it
343 const string16& extension_id, const content::URLFetcher* source) {
344 if (source->GetResponseCode() != 200)
345 return;
Greg Billock 2012/02/23 18:38:34 Need to AsyncOperationFinished here?
binji 2012/02/23 19:06:13 Done.
346
347 scoped_ptr<std::string> response(new std::string());
Greg Billock 2012/02/23 18:38:34 Can kill inner "()"
binji 2012/02/23 19:06:13 Done.
348 if (source->GetResponseAsString(response.get())) {
349 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
350
351 // Decode PNG and resize on worker thread.
352 content::BrowserThread::PostBlockingPoolTask(
Greg Billock 2012/02/23 18:38:34 These cascades are why the frontends ended up usin
binji 2012/02/23 19:06:13 Agreed. Though I think it's not too hard to follow
353 FROM_HERE,
354 base::Bind(&DecodeExtensionIconAndResize,
355 base::Passed(&response),
356 base::Bind(
357 &WebIntentPickerController::OnExtensionIconAvailable,
358 weak_ptr_factory_.GetWeakPtr(),
359 extension_id),
360 base::Bind(
361 &WebIntentPickerController::OnExtensionIconUnavailable,
362 weak_ptr_factory_.GetWeakPtr(),
363 extension_id)));
364 } else {
365 AsyncOperationFinished();
366 }
367 }
368
369 // static
370 void WebIntentPickerController::DecodeExtensionIconAndResize(
371 scoped_ptr<std::string> icon_response,
372 const ExtensionIconAvailableCallback& callback,
373 const base::Closure& unavailable_callback) {
374 SkBitmap icon_bitmap;
375 if (gfx::PNGCodec::Decode(
376 reinterpret_cast<const unsigned char*>(icon_response->data()),
377 icon_response->length(),
378 &icon_bitmap)) {
379 SkBitmap resized_icon = skia::ImageOperations::Resize(
Greg Billock 2012/02/23 18:38:34 Is this doing an extra image copy?
binji 2012/02/23 19:06:13 Yes, it doesn't resize in-place.
380 icon_bitmap,
381 skia::ImageOperations::RESIZE_BEST,
382 gfx::kFaviconSize, gfx::kFaviconSize);
383 gfx::Image icon_image(new SkBitmap(resized_icon));
384
385 content::BrowserThread::PostTask(
386 content::BrowserThread::UI,
387 FROM_HERE,
388 base::Bind(callback, icon_image));
Greg Billock 2012/02/23 18:38:34 So gfx::Image is pointer-ish and cool to pass like
binji 2012/02/23 19:06:13 Yes, gfx::Image has internal refcounted storage.
389 } else {
390 content::BrowserThread::PostTask(
391 content::BrowserThread::UI,
392 FROM_HERE,
393 unavailable_callback);
394 }
395 }
396
397 void WebIntentPickerController::OnExtensionIconAvailable(
398 const string16& extension_id,
399 const gfx::Image& icon_image) {
400 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image);
401 AsyncOperationFinished();
402 }
403
404 void WebIntentPickerController::OnExtensionIconUnavailable(
405 const string16& extension_id) {
406 AsyncOperationFinished();
407 }
408
301 void WebIntentPickerController::AsyncOperationFinished() { 409 void WebIntentPickerController::AsyncOperationFinished() {
302 if (--pending_async_count_ == 0) { 410 if (--pending_async_count_ == 0) {
Greg Billock 2012/02/23 18:38:34 So we don't need a mutex here because Decode() is
binji 2012/02/23 19:06:13 This callback is only used to notify a test that a
303 picker_->OnPendingAsyncCompleted(); 411 picker_->OnPendingAsyncCompleted();
304 } 412 }
305 } 413 }
306 414
307 void WebIntentPickerController::ClosePicker() { 415 void WebIntentPickerController::ClosePicker() {
308 if (picker_) { 416 if (picker_) {
309 picker_->Close(); 417 picker_->Close();
310 } 418 }
311 } 419 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698