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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/intents/web_intent_picker_controller.cc
diff --git a/chrome/browser/ui/intents/web_intent_picker_controller.cc b/chrome/browser/ui/intents/web_intent_picker_controller.cc
index f6e53f2d72ef3a941ca6a1c0fd16a37db4d14681..de7832ab4566d7c798c0af57fa79d77884a40396 100644
--- a/chrome/browser/ui/intents/web_intent_picker_controller.cc
+++ b/chrome/browser/ui/intents/web_intent_picker_controller.cc
@@ -22,10 +22,16 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_intents_dispatcher.h"
+#include "content/public/common/url_fetcher.h"
+#include "content/public/common/url_fetcher_delegate.h"
+#include "net/base/load_flags.h"
+#include "skia/ext/image_operations.h"
#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image.h"
#include "webkit/glue/web_intent_service_data.h"
@@ -59,6 +65,25 @@ WebIntentPickerModel::Disposition ConvertDisposition(
}
}
+class URLFetcherTrampoline : public content::URLFetcherDelegate {
+ public:
+ typedef base::Callback<void(const content::URLFetcher* source)> Callback;
+
+ explicit URLFetcherTrampoline(const Callback& callback)
+ : callback_(callback) {}
+ ~URLFetcherTrampoline() {}
+
+ // content::URLFetcherDelegate implementation.
+ virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE {
+ callback_.Run(source);
+ delete source;
+ delete this;
+ }
+
+ private:
+ Callback callback_;
+};
+
} // namespace
WebIntentPickerController::WebIntentPickerController(
@@ -291,13 +316,113 @@ void WebIntentPickerController::OnCWSIntentServicesAvailable(
info.id,
info.average_rating);
- // TODO(binji): Fetch extension icon.
+ pending_async_count_++;
+ content::URLFetcher* icon_url_fetcher = content::URLFetcher::Create(
+ 0,
+ info.icon_url,
+ content::URLFetcher::GET,
+ new URLFetcherTrampoline(
+ base::Bind(
+ &WebIntentPickerController::OnExtensionIconURLFetchComplete,
+ weak_ptr_factory_.GetWeakPtr(), info.id)));
+
+ icon_url_fetcher->SetLoadFlags(
+ net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
+ icon_url_fetcher->SetRequestContext(
+ wrapper_->profile()->GetRequestContext());
+ icon_url_fetcher->Start();
+ }
+
+ AsyncOperationFinished();
+}
+
+void WebIntentPickerController::OnExtensionIconURLFetchComplete(
+ const string16& extension_id, const content::URLFetcher* source) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (source->GetResponseCode() != 200) {
+ AsyncOperationFinished();
+ return;
+ }
+
+ scoped_ptr<std::string> response(new std::string);
+ if (!source->GetResponseAsString(response.get())) {
+ AsyncOperationFinished();
+ return;
+ }
+
+ // I'd like to have the worker thread post a task directly to the UI thread
+ // to call OnExtensionIcon[Un]Available, but this doesn't work: To do so
+ // would require DecodeExtensionIconAndResize to be a member function (so it
+ // has access to |this|) but a weak pointer cannot be dereferenced on a
+ // thread other than the thread where the WeakPtrFactory was created. Since
+ // the stored |this| pointer is weak, DecodeExtensionIconAndResize asserts
+ // before it even starts.
+ //
+ // Instead, I package up the callbacks that I want the worker thread to call,
+ // and make DecodeExtensionIconAndResize static. The stored weak |this|
+ // pointers are not dereferenced until invocation (on the UI thread).
+ ExtensionIconAvailableCallback available_callback =
+ base::Bind(
+ &WebIntentPickerController::OnExtensionIconAvailable,
+ weak_ptr_factory_.GetWeakPtr(),
+ extension_id);
+ base::Closure unavailable_callback =
+ base::Bind(
+ &WebIntentPickerController::OnExtensionIconUnavailable,
+ weak_ptr_factory_.GetWeakPtr(),
+ extension_id);
+
+ // Decode PNG and resize on worker thread.
+ content::BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(&DecodeExtensionIconAndResize,
+ base::Passed(&response),
+ available_callback,
+ unavailable_callback));
+}
+
+// static
+void WebIntentPickerController::DecodeExtensionIconAndResize(
+ scoped_ptr<std::string> icon_response,
+ const ExtensionIconAvailableCallback& callback,
+ const base::Closure& unavailable_callback) {
+ SkBitmap icon_bitmap;
+ if (gfx::PNGCodec::Decode(
+ reinterpret_cast<const unsigned char*>(icon_response->data()),
+ icon_response->length(),
+ &icon_bitmap)) {
+ SkBitmap resized_icon = skia::ImageOperations::Resize(
+ icon_bitmap,
+ skia::ImageOperations::RESIZE_BEST,
+ gfx::kFaviconSize, gfx::kFaviconSize);
+ gfx::Image icon_image(new SkBitmap(resized_icon));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(callback, icon_image));
+ } else {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ unavailable_callback);
}
+}
+
+void WebIntentPickerController::OnExtensionIconAvailable(
+ const string16& extension_id,
+ const gfx::Image& icon_image) {
+ picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image);
+ AsyncOperationFinished();
+}
+void WebIntentPickerController::OnExtensionIconUnavailable(
+ const string16& extension_id) {
AsyncOperationFinished();
}
void WebIntentPickerController::AsyncOperationFinished() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (--pending_async_count_ == 0) {
picker_->OnPendingAsyncCompleted();
}

Powered by Google App Engine
This is Rietveld 408576698