Index: chrome/browser/renderer_host/render_view_host.cc |
=================================================================== |
--- chrome/browser/renderer_host/render_view_host.cc (revision 46794) |
+++ chrome/browser/renderer_host/render_view_host.cc (working copy) |
@@ -15,11 +15,14 @@ |
#include "base/string_util.h" |
#include "base/time.h" |
#include "base/waitable_event.h" |
+#include "chrome/browser/browser_process.h" |
#include "chrome/browser/child_process_security_policy.h" |
#include "chrome/browser/cross_site_request_manager.h" |
+#include "chrome/browser/chrome_thread.h" |
#include "chrome/browser/debugger/devtools_manager.h" |
#include "chrome/browser/dom_operation_notification_details.h" |
#include "chrome/browser/extensions/extension_message_service.h" |
+#include "chrome/browser/icon_manager.h" |
#include "chrome/browser/metrics/user_metrics.h" |
#include "chrome/browser/notifications/desktop_notification_service.h" |
#include "chrome/browser/profile.h" |
@@ -39,6 +42,7 @@ |
#include "chrome/common/thumbnail_score.h" |
#include "chrome/common/translate_errors.h" |
#include "chrome/common/url_constants.h" |
+#include "gfx/codec/png_codec.h" |
#include "gfx/native_widget_types.h" |
#include "net/base/net_util.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
@@ -756,6 +760,7 @@ |
OnMsgGoToEntryAtOffset) |
IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnMsgSetTooltipText) |
IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnMsgRunFileChooser) |
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ChooseIconForFiles, OnMsgChooseIconForFiles) |
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage, |
OnMsgRunJavaScriptMessage) |
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm, |
@@ -1315,6 +1320,115 @@ |
delegate_->RunFileChooser(params); |
} |
+// Manages cancelable icon loading. |
+class IconRequestProvider : public CancelableRequestProvider { |
+ public: |
+ typedef Callback2<int, SkBitmap*>::Type RequestCallbackType; |
+ typedef CancelableRequest<RequestCallbackType> RequestType; |
+ |
+ Handle Start(int request_id, const std::vector<FilePath>& filenames, |
+ CancelableRequestConsumerBase* consumer, |
+ RequestCallbackType* callback); |
+ |
+ private: |
+ CancelableRequestConsumerT<int, 0> consumer_; |
+}; |
+ |
+// Helper for OnMsgChooseIconForFiles(). |
+// This instance runs in the UI thread. |
+class IconRequestBackend : public |
+ base::RefCountedThreadSafe<IconRequestBackend> { |
+ public: |
+ explicit IconRequestBackend( |
+ scoped_refptr<IconRequestProvider::RequestType> request, |
+ CancelableRequestConsumerBase* consumer, |
+ int request_id, |
+ const std::vector<FilePath>& filenames) |
+ : request_(request), |
+ consumer_(consumer), |
+ request_id_(request_id), |
+ filenames_(filenames) { } |
+ |
+ void Run() { |
+ if (request_->canceled()) { |
+ Release(); |
+ return; |
+ } |
+ |
+ IconManager* im = g_browser_process->icon_manager(); |
+ if (filenames_.size() <= 0) { |
+ Reply(NULL); |
+ } else { |
+ // TODO(tkent): Load an icon representing `multiple files' in a case of |
+ // filenames_.size() > 1. |
+ SkBitmap* icon = im->LookupIcon(filenames_[0], IconLoader::NORMAL); |
+ if (icon) { |
+ Reply(icon); |
+ return; |
+ } |
+ im->LoadIcon(filenames_[0], IconLoader::NORMAL, consumer_, |
+ NewCallback(this, &IconRequestBackend::OnIconLoaded)); |
+ } |
+ } |
+ |
+ private: |
+ ~IconRequestBackend() { } |
+ |
+ void Reply(SkBitmap* icon) { |
+ request_->ForwardResult(Tuple2<int, SkBitmap*>(request_id_, icon)); |
+ Release(); |
+ } |
+ |
+ void OnIconLoaded(IconManager::Handle handle, SkBitmap* icon) { |
+ Reply(icon); |
+ } |
+ |
+ scoped_refptr<IconRequestProvider::RequestType> request_; |
+ // CancelableRequestConsumer for IconManager. |
+ CancelableRequestConsumerBase* consumer_; |
+ // Copy of a ViewHostMsg_IconForFiles arguemnt. |
+ int request_id_; |
+ // Copy of a ViewHostMsg_IconForFiles arguemnt. |
+ const std::vector<FilePath> filenames_; |
+ |
+ friend class base::RefCountedThreadSafe<IconRequestBackend>; |
+}; |
+ |
+IconRequestProvider::Handle IconRequestProvider::Start( |
+ int request_id, |
+ const std::vector<FilePath>& filenames, |
+ CancelableRequestConsumerBase* consumer, |
+ RequestCallbackType* callback) { |
+ scoped_refptr<RequestType> request(new RequestType(callback)); |
+ AddRequest(request, consumer); |
+ |
+ IconRequestBackend* backend = |
+ new IconRequestBackend(request, &consumer_, request_id, filenames); |
+ backend->AddRef(); |
+ // We need to switch to the UI thread because IconManager works |
+ // only in the UI thread. |
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(backend, &IconRequestBackend::Run)); |
+ return request->handle(); |
+} |
+ |
+void RenderViewHost::OnIconLoaded(int request_id, SkBitmap* icon) { |
+ std::vector<unsigned char> png_data; |
+ gfx::PNGCodec::EncodeBGRASkBitmap(*icon, false, &png_data); |
+ Send(new ViewMsg_ChooseIconForFilesResponse( |
+ routing_id(), request_id, png_data)); |
+ // No need to delete |icon|. It is owned by IconManager. |
+} |
+ |
+void RenderViewHost::OnMsgChooseIconForFiles( |
+ int request_id, const std::vector<FilePath>& filenames) { |
+ if (icon_request_provider_.get() == NULL) { |
+ icon_request_provider_.reset(new IconRequestProvider()); |
+ } |
+ icon_request_provider_->Start(request_id, filenames, &cancelable_consumer_, |
+ NewCallback(this, &RenderViewHost::OnIconLoaded)); |
+} |
+ |
void RenderViewHost::OnMsgRunJavaScriptMessage( |
const std::wstring& message, |
const std::wstring& default_prompt, |