diff options
author | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 22:25:22 +0000 |
---|---|---|
committer | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 22:25:22 +0000 |
commit | 12e14fcf977c5a4be6dd8e2778ac13382e2bf08a (patch) | |
tree | cba94d23134369e2db9174b152a635272450e0eb /chrome/browser/dom_ui | |
parent | 0603139039825ae34f1c9f659827eb78dada2728 (diff) | |
download | chromium_src-12e14fcf977c5a4be6dd8e2778ac13382e2bf08a.zip chromium_src-12e14fcf977c5a4be6dd8e2778ac13382e2bf08a.tar.gz chromium_src-12e14fcf977c5a4be6dd8e2778ac13382e2bf08a.tar.bz2 |
Initial checkin of the HTML downloads UI. It's not yet complete (lacking interface polish). But is enough for us to begin removing the native UI.ojan, please review downloads.htmlpaul, please review everything else
Review URL: http://codereview.chromium.org/20110
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10050 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/dom_ui')
-rw-r--r-- | chrome/browser/dom_ui/dom_ui.cc | 46 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui.h | 7 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_contents.cc | 5 | ||||
-rw-r--r-- | chrome/browser/dom_ui/downloads_ui.cc | 369 | ||||
-rw-r--r-- | chrome/browser/dom_ui/downloads_ui.h | 123 | ||||
-rw-r--r-- | chrome/browser/dom_ui/fileicon_source.cc | 63 | ||||
-rw-r--r-- | chrome/browser/dom_ui/fileicon_source.h | 45 |
7 files changed, 656 insertions, 2 deletions
diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc index 1fe8d99..94116b3 100644 --- a/chrome/browser/dom_ui/dom_ui.cc +++ b/chrome/browser/dom_ui/dom_ui.cc @@ -48,6 +48,11 @@ void DOMUI::ProcessDOMUIMessage(const std::string& message, callback->second->Run(value.get()); } +void DOMUI::CallJavascriptFunction(const std::wstring& function_name) { + std::wstring javascript = function_name + L"();"; + ExecuteJavascript(javascript); +} + void DOMUI::CallJavascriptFunction(const std::wstring& function_name, const Value& arg) { std::string json; @@ -123,4 +128,43 @@ void DOMMessageHandler::SetURLAndTitle(DictionaryValue* dictionary, } } dictionary->SetString(L"title", title_to_set); -}
\ No newline at end of file +} + +bool DOMMessageHandler::ExtractIntegerValue(const Value* value, int* out_int) { + if (value && value->GetType() == Value::TYPE_LIST) { + const ListValue* list_value = static_cast<const ListValue*>(value); + Value* list_member; + + // Get id. + if (list_value->Get(0, &list_member) && + list_member->GetType() == Value::TYPE_STRING) { + const StringValue* string_value = + static_cast<const StringValue*>(list_member); + std::wstring wstring_value; + string_value->GetAsString(&wstring_value); + *out_int = StringToInt(wstring_value); + return true; + } + } + + return false; +} + +std::wstring DOMMessageHandler::ExtractStringValue(const Value* value) { + if (value && value->GetType() == Value::TYPE_LIST) { + const ListValue* list_value = static_cast<const ListValue*>(value); + Value* list_member; + + // Get id. + if (list_value->Get(0, &list_member) && + list_member->GetType() == Value::TYPE_STRING) { + const StringValue* string_value = + static_cast<const StringValue*>(list_member); + std::wstring wstring_value; + string_value->GetAsString(&wstring_value); + return wstring_value; + } + } + return std::wstring(); +} + diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h index 8b0286b..ff0f96f 100644 --- a/chrome/browser/dom_ui/dom_ui.h +++ b/chrome/browser/dom_ui/dom_ui.h @@ -35,6 +35,7 @@ class DOMUI { // of the call, and should be thought of more like sending a message to // the page. // There are two function variants for one-arg and two-arg calls. + void CallJavascriptFunction(const std::wstring& function_name); void CallJavascriptFunction(const std::wstring& function_name, const Value& arg); void CallJavascriptFunction(const std::wstring& function_name, @@ -77,6 +78,12 @@ class DOMMessageHandler { std::wstring title, const GURL& gurl); + // Extract an integer value from a Value. + bool ExtractIntegerValue(const Value* value, int* out_int); + + // Extract a string value from a Value. + std::wstring ExtractStringValue(const Value* value); + DOMUI* const dom_ui_; private: diff --git a/chrome/browser/dom_ui/dom_ui_contents.cc b/chrome/browser/dom_ui/dom_ui_contents.cc index 4e0a3f2..89c35f2 100644 --- a/chrome/browser/dom_ui/dom_ui_contents.cc +++ b/chrome/browser/dom_ui/dom_ui_contents.cc @@ -6,6 +6,7 @@ #include "chrome/browser/dom_ui/dom_ui.h" #include "chrome/browser/dom_ui/history_ui.h" +#include "chrome/browser/dom_ui/downloads_ui.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/common/resource_bundle.h" @@ -192,7 +193,9 @@ bool DOMUIContents::NavigateToPendingEntry(bool reload) { DOMUI* DOMUIContents::GetDOMUIForURL(const GURL &url) { if (url.host() == HistoryUI::GetBaseURL().host()) return new HistoryUI(this); - + else if (url.host() == DownloadsUI::GetBaseURL().host()) + return new DownloadsUI(this); + return NULL; } diff --git a/chrome/browser/dom_ui/downloads_ui.cc b/chrome/browser/dom_ui/downloads_ui.cc new file mode 100644 index 0000000..49a6726 --- /dev/null +++ b/chrome/browser/dom_ui/downloads_ui.cc @@ -0,0 +1,369 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/dom_ui/downloads_ui.h" + +#include "base/gfx/png_encoder.h" +#include "base/string_piece.h" +#include "base/thread.h" +#include "base/time.h" +#include "base/time_format.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/dom_ui/fileicon_source.h" +#include "chrome/browser/download/download_util.h" +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/profile.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/time_format.h" + +// Generated by GRIT +#include "browser_resources.h" +#include "generated_resources.h" + +using base::Time; + +// DownloadsUI is accessible from chrome-ui://downloads. +static const char kDownloadsHost[] = "downloads"; + +/////////////////////////////////////////////////////////////////////////////// +// +// DownloadsHTMLSource +// +/////////////////////////////////////////////////////////////////////////////// + +DownloadsUIHTMLSource::DownloadsUIHTMLSource() + : DataSource(kDownloadsHost, MessageLoop::current()) { +} + +void DownloadsUIHTMLSource::StartDataRequest(const std::string& path, + int request_id) { + DictionaryValue localized_strings; + localized_strings.SetString(L"title", + l10n_util::GetString(IDS_DOWNLOAD_TITLE)); + localized_strings.SetString(L"searchbutton", + l10n_util::GetString(IDS_DOWNLOAD_SEARCH_BUTTON)); + localized_strings.SetString(L"no_results", + l10n_util::GetString(IDS_DOWNLOAD_SEARCH_BUTTON)); + localized_strings.SetString(L"searchresultsfor", + l10n_util::GetString(IDS_DOWNLOAD_SEARCHRESULTSFOR)); + localized_strings.SetString(L"downloads", + l10n_util::GetString(IDS_DOWNLOAD_TITLE)); + + // Status. + localized_strings.SetString(L"status_cancelled", + l10n_util::GetString(IDS_DOWNLOAD_TAB_CANCELLED)); + localized_strings.SetString(L"status_paused", + l10n_util::GetString(IDS_DOWNLOAD_PROGRESS_PAUSED)); + + // Dangerous file. + localized_strings.SetString(L"danger_desc", + l10n_util::GetStringF(IDS_PROMPT_DANGEROUS_DOWNLOAD, L"%s")); + localized_strings.SetString(L"danger_save", + l10n_util::GetString(IDS_SAVE_DOWNLOAD)); + localized_strings.SetString(L"danger_discard", + l10n_util::GetString(IDS_DISCARD_DOWNLOAD)); + + // Controls. + localized_strings.SetString(L"control_pause", + l10n_util::GetString(IDS_DOWNLOAD_LINK_PAUSE)); + localized_strings.SetString(L"control_showinfolder", + l10n_util::GetString(IDS_DOWNLOAD_LINK_SHOW)); + localized_strings.SetString(L"control_cancel", + l10n_util::GetString(IDS_DOWNLOAD_LINK_CANCEL)); + localized_strings.SetString(L"control_resume", + l10n_util::GetString(IDS_DOWNLOAD_LINK_RESUME)); + + static const StringPiece downloads_html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_DOWNLOADS_HTML)); + const std::string full_html = jstemplate_builder::GetTemplateHtml( + downloads_html, &localized_strings, "t"); + + scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); + html_bytes->data.resize(full_html.size()); + std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); + + SendResponse(request_id, html_bytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// DownloadsDOMHandler +// +/////////////////////////////////////////////////////////////////////////////// + +// Sort DownloadItems into descending order by their start time. +class DownloadItemSorter : public std::binary_function<DownloadItem*, + DownloadItem*, + bool> { + public: + bool operator()(const DownloadItem* lhs, const DownloadItem* rhs) { + return lhs->start_time() > rhs->start_time(); + } +}; + +DownloadsDOMHandler::DownloadsDOMHandler(DOMUI* dom_ui, DownloadManager* dlm) + : DOMMessageHandler(dom_ui), + download_manager_(dlm), + search_text_() { + dom_ui_->RegisterMessageCallback("getDownloads", + NewCallback(this, &DownloadsDOMHandler::HandleGetDownloads)); + dom_ui_->RegisterMessageCallback("openFile", + NewCallback(this, &DownloadsDOMHandler::HandleOpenFile)); + + dom_ui_->RegisterMessageCallback("drag", + NewCallback(this, &DownloadsDOMHandler::HandleDrag)); + + dom_ui_->RegisterMessageCallback("saveDangerous", + NewCallback(this, &DownloadsDOMHandler::HandleSaveDangerous)); + dom_ui_->RegisterMessageCallback("discardDangerous", + NewCallback(this, &DownloadsDOMHandler::HandleDiscardDangerous)); + dom_ui_->RegisterMessageCallback("show", + NewCallback(this, &DownloadsDOMHandler::HandleShow)); + dom_ui_->RegisterMessageCallback("pause", + NewCallback(this, &DownloadsDOMHandler::HandlePause)); + dom_ui_->RegisterMessageCallback("cancel", + NewCallback(this, &DownloadsDOMHandler::HandleCancel)); + + // Create our fileicon data source. + g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(&chrome_url_data_manager, + &ChromeURLDataManager::AddDataSource, + new FileIconSource())); +} + +DownloadsDOMHandler::~DownloadsDOMHandler() { + ClearDownloadItems(); + download_manager_->RemoveObserver(this); +} + +// DownloadsDOMHandler, public: ----------------------------------------------- + +void DownloadsDOMHandler::Init() { + download_manager_->AddObserver(this); +} + +void DownloadsDOMHandler::OnDownloadUpdated(DownloadItem* download) { + // Get the id for the download. Our downloads are sorted latest to first, + // and the id is the index into that list. We should be careful of sync + // errors between the UI and the download_items_ list (we may wish to use + // something other than 'id'). + OrderedDownloads::iterator it = find(download_items_.begin(), + download_items_.end(), + download); + if (it == download_items_.end()) + return; + const int id = static_cast<int>(it - download_items_.begin()); + + ListValue results_value; + results_value.Append(CreateDownloadItemValue(download, id)); + dom_ui_->CallJavascriptFunction(L"downloadUpdated", results_value); +} + +// A download has started or been deleted. Query our DownloadManager for the +// current set of downloads, which will call us back in SetDownloads once it +// has retrieved them. +void DownloadsDOMHandler::ModelChanged() { + ClearDownloadItems(); + download_manager_->GetDownloads(this, search_text_); +} + +void DownloadsDOMHandler::SetDownloads( + std::vector<DownloadItem*>& downloads) { + ClearDownloadItems(); + + // Swap new downloads in. + download_items_.swap(downloads); + sort(download_items_.begin(), download_items_.end(), DownloadItemSorter()); + + // Scan for any in progress downloads and add ourself to them as an observer. + for (OrderedDownloads::iterator it = download_items_.begin(); + it != download_items_.end(); ++it) { + DownloadItem* download = *it; + if (download->state() == DownloadItem::IN_PROGRESS) { + // We want to know what happens as the download progresses. + download->AddObserver(this); + } else if (download->safety_state() == DownloadItem::DANGEROUS) { + // We need to be notified when the user validates the dangerous download. + download->AddObserver(this); + } + } + + SendCurrentDownloads(); +} + +void DownloadsDOMHandler::HandleGetDownloads(const Value* value) { + std::wstring new_search = ExtractStringValue(value); + if (search_text_.compare(new_search) != 0) { + search_text_ = new_search; + ClearDownloadItems(); + download_manager_->GetDownloads(this, search_text_); + } else { + SendCurrentDownloads(); + } +} + +void DownloadsDOMHandler::HandleOpenFile(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) + download_manager_->OpenDownloadInShell(file, NULL); +} + +void DownloadsDOMHandler::HandleDrag(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) { + IconManager* im = g_browser_process->icon_manager(); + SkBitmap* icon = im->LookupIcon(file->full_path().ToWStringHack(), + IconLoader::NORMAL); + download_util::DragDownload(file, icon); + } +} + +void DownloadsDOMHandler::HandleSaveDangerous(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) + download_manager_->DangerousDownloadValidated(file); +} + +void DownloadsDOMHandler::HandleDiscardDangerous(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) + file->Remove(true); +} + +void DownloadsDOMHandler::HandleShow(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) + download_manager_->ShowDownloadInShell(file); +} + +void DownloadsDOMHandler::HandlePause(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) + file->TogglePause(); +} + +void DownloadsDOMHandler::HandleCancel(const Value* value) { + DownloadItem* file = GetDownloadByValue(value); + if (file) + file->Cancel(true); +} + +// DownloadsDOMHandler, private: ---------------------------------------------- + +void DownloadsDOMHandler::SendCurrentDownloads() { + ListValue results_value; + + for (OrderedDownloads::iterator it = download_items_.begin(); + it != download_items_.end(); ++it) { + results_value.Append(CreateDownloadItemValue(*it, + static_cast<int>(it - download_items_.begin()))); + } + + dom_ui_->CallJavascriptFunction(L"downloadsList", results_value); +} + +DictionaryValue* DownloadsDOMHandler::CreateDownloadItemValue( + DownloadItem* download, int id) { + DictionaryValue* file_value = new DictionaryValue(); + + file_value->SetInteger(L"time", + static_cast<int>(download->start_time().ToTimeT())); + file_value->SetInteger(L"id", id); + file_value->SetString(L"file_path", download->full_path().ToWStringHack()); + file_value->SetString(L"file_name", download->GetFileName().ToWStringHack()); + file_value->SetString(L"url", download->url().spec()); + + if (download->state() == DownloadItem::IN_PROGRESS) { + if (download->safety_state() == DownloadItem::DANGEROUS) { + file_value->SetString(L"state", L"DANGEROUS"); + } else if (download->is_paused()) { + file_value->SetString(L"state", L"PAUSED"); + } else { + file_value->SetString(L"state", L"IN_PROGRESS"); + } + file_value->SetInteger(L"speed", + static_cast<int>(download->CurrentSpeed())); + file_value->SetInteger(L"percent", + static_cast<int>(download->PercentComplete())); + file_value->SetInteger(L"received", + static_cast<int>(download->received_bytes())); + } else if (download->state() == DownloadItem::CANCELLED) { + file_value->SetString(L"state", L"CANCELLED"); + } else if (download->state() == DownloadItem::COMPLETE) { + if (download->safety_state() == DownloadItem::DANGEROUS) { + file_value->SetString(L"state", L"DANGEROUS"); + } else { + file_value->SetString(L"state", L"COMPLETE"); + } + } + + file_value->SetInteger(L"total", + static_cast<int>(download->total_bytes())); + + return file_value; +} + +void DownloadsDOMHandler::ClearDownloadItems() { + // Clear out old state and remove self as observer for each download. + for (OrderedDownloads::iterator it = download_items_.begin(); + it != download_items_.end(); ++it) { + (*it)->RemoveObserver(this); + } + download_items_.clear(); +} + +DownloadItem* DownloadsDOMHandler::GetDownloadById(int id) { + for (OrderedDownloads::iterator it = download_items_.begin(); + it != download_items_.end(); ++it) { + if (static_cast<int>(it - download_items_.begin() == id)) { + return (*it); + } + } + + return NULL; +} + +DownloadItem* DownloadsDOMHandler::GetDownloadByValue(const Value* value) { + int id; + if (ExtractIntegerValue(value, &id)) { + return GetDownloadById(id); + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// DownloadsUI +// +/////////////////////////////////////////////////////////////////////////////// + +DownloadsUI::DownloadsUI(DOMUIContents* contents) : DOMUI(contents) { +} + +void DownloadsUI::Init() { + DownloadManager* dlm = get_profile()->GetDownloadManager(); + + DownloadsDOMHandler* handler = new DownloadsDOMHandler(this, dlm); + AddMessageHandler(handler); + handler->Init(); + + DownloadsUIHTMLSource* html_source = new DownloadsUIHTMLSource(); + + // Set up the chrome-ui://downloads/ source. + g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(&chrome_url_data_manager, + &ChromeURLDataManager::AddDataSource, + html_source)); +} + +// static +GURL DownloadsUI::GetBaseURL() { + std::string url = DOMUIContents::GetScheme(); + url += "://"; + url += kDownloadsHost; + return GURL(url); +} + diff --git a/chrome/browser/dom_ui/downloads_ui.h b/chrome/browser/dom_ui/downloads_ui.h new file mode 100644 index 0000000..9209000 --- /dev/null +++ b/chrome/browser/dom_ui/downloads_ui.h @@ -0,0 +1,123 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DOM_UI_DOWNLOADS_UI_H_ +#define CHROME_BROWSER_DOM_UI_DOWNLOADS_UI_H_ + +#include "chrome/browser/dom_ui/chrome_url_data_manager.h" +#include "chrome/browser/dom_ui/dom_ui.h" +#include "chrome/browser/dom_ui/dom_ui_contents.h" +#include "chrome/browser/download/download_manager.h" + +class GURL; + +class DownloadsUIHTMLSource : public ChromeURLDataManager::DataSource { + public: + DownloadsUIHTMLSource(); + + // Called when the network layer has requested a resource underneath + // the path we registered. + virtual void StartDataRequest(const std::string& path, int request_id); + virtual std::string GetMimeType(const std::string&) const { + return "text/html"; + } + + private: + DISALLOW_COPY_AND_ASSIGN(DownloadsUIHTMLSource); +}; + +// The handler for Javascript messages related to the "downloads" view, +// also observes changes to the download manager. +class DownloadsDOMHandler : public DOMMessageHandler, + public DownloadManager::Observer, + public DownloadItem::Observer { + public: + explicit DownloadsDOMHandler(DOMUI* dom_ui, DownloadManager* dlm); + virtual ~DownloadsDOMHandler(); + + void Init(); + + // DownloadItem::Observer interface + virtual void OnDownloadUpdated(DownloadItem* download); + + // DownloadManager::Observer interface + virtual void ModelChanged(); + virtual void SetDownloads(std::vector<DownloadItem*>& downloads); + + // Callback for the "getDownloads" message. + void HandleGetDownloads(const Value* value); + + // Callback for the "openFile" message - opens the file in the shell. + void HandleOpenFile(const Value* value); + + // Callback for the "drag" message - initiates a file object drag. + void HandleDrag(const Value* value); + + // Callback for the "saveDangerous" message - specifies that the user + // wishes to save a dangerous file. + void HandleSaveDangerous(const Value* value); + + // Callback for the "discardDangerous" message - specifies that the user + // wishes to discard (remove) a dangerous file. + void HandleDiscardDangerous(const Value* value); + + // Callback for the "show" message - shows the file in explorer. + void HandleShow(const Value* value); + + // Callback for the "pause" message - pauses the file download. + void HandlePause(const Value* value); + + // Callback for the "cancel" message - cancels the download. + void HandleCancel(const Value* value); + + private: + // Send the current list of downloads to the page. + void SendCurrentDownloads(); + + // Creates a representation of a download in a format that the downloads + // HTML page can understand. + DictionaryValue* CreateDownloadItemValue(DownloadItem* download, int id); + + // Clear all download items and their observers. + void ClearDownloadItems(); + + // Return the download that corresponds to a given id. + DownloadItem* GetDownloadById(int id); + + // Return the download that is referred to in a given value. + DownloadItem* GetDownloadByValue(const Value* value); + + // Current search text. + std::wstring search_text_; + + // Our model + DownloadManager* download_manager_; + + // The current set of visible DownloadItems for this view received from the + // DownloadManager. DownloadManager owns the DownloadItems. The vector is + // kept in order, sorted by ascending start time. + typedef std::vector<DownloadItem*> OrderedDownloads; + OrderedDownloads download_items_; + + DISALLOW_COPY_AND_ASSIGN(DownloadsDOMHandler); +}; + +class DownloadsUI : public DOMUI { + public: + explicit DownloadsUI(DOMUIContents* contents); + + // Return the URL for the front page of this UI. + static GURL GetBaseURL(); + + // DOMUI Implementation + virtual void Init(); + + private: + DOMUIContents* contents_; + + DISALLOW_COPY_AND_ASSIGN(DownloadsUI); +}; + +#endif // CHROME_BROWSER_DOM_UI_DOWNLOADS_UI_H_ + diff --git a/chrome/browser/dom_ui/fileicon_source.cc b/chrome/browser/dom_ui/fileicon_source.cc new file mode 100644 index 0000000..36fb30f --- /dev/null +++ b/chrome/browser/dom_ui/fileicon_source.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/dom_ui/fileicon_source.h" + +#include "base/gfx/png_encoder.h" +#include "base/string_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/time_format.h" + +#include "generated_resources.h" + +// The path used in internal URLs to file icon data. +static const char kFileIconPath[] = "fileicon"; + +FileIconSource::FileIconSource() + : DataSource(kFileIconPath, MessageLoop::current()) {} + +FileIconSource::~FileIconSource() { + cancelable_consumer_.CancelAllRequests(); +} + +void FileIconSource::StartDataRequest(const std::string& path, + int request_id) { + IconManager* im = g_browser_process->icon_manager(); + + // Fast look up. + SkBitmap* icon = im->LookupIcon(UTF8ToWide(path), IconLoader::NORMAL); + + if (icon) { + std::vector<unsigned char> png_bytes; + PNGEncoder::EncodeBGRASkBitmap(*icon, false, &png_bytes); + + scoped_refptr<RefCountedBytes> icon_data = new RefCountedBytes(png_bytes); + SendResponse(request_id, icon_data); + } else { + // Icon was not in cache, go fetch it slowly. + IconManager::Handle h = im->LoadIcon(UTF8ToWide(path), IconLoader::NORMAL, + &cancelable_consumer_, + NewCallback(this, &FileIconSource::OnFileIconDataAvailable)); + + // Attach the ChromeURLDataManager request ID to the history request. + cancelable_consumer_.SetClientData(im, h, request_id); + } +} + +void FileIconSource::OnFileIconDataAvailable(IconManager::Handle handle, + SkBitmap* icon) { + IconManager* im = g_browser_process->icon_manager(); + int request_id = cancelable_consumer_.GetClientData(im, handle); + + if (icon) { + std::vector<unsigned char> png_bytes; + PNGEncoder::EncodeBGRASkBitmap(*icon, false, &png_bytes); + + scoped_refptr<RefCountedBytes> icon_data = new RefCountedBytes(png_bytes); + SendResponse(request_id, icon_data); + } else { + // TODO(glen): send a dummy icon. + SendResponse(request_id, NULL); + } +}
\ No newline at end of file diff --git a/chrome/browser/dom_ui/fileicon_source.h b/chrome/browser/dom_ui/fileicon_source.h new file mode 100644 index 0000000..e56996c --- /dev/null +++ b/chrome/browser/dom_ui/fileicon_source.h @@ -0,0 +1,45 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DOM_UI_FILEICON_SOURCE_H_ +#define CHROME_BROWSER_DOM_UI_FILEICON_SOURCE_H_ + +#include "chrome/browser/dom_ui/chrome_url_data_manager.h" +#include "chrome/browser/icon_manager.h" +#include "chrome/common/resource_bundle.h" + +class GURL; + +// FileIconSource is the gateway between network-level chrome: +// requests for favicons and the history backend that serves these. +class FileIconSource : public ChromeURLDataManager::DataSource { + public: + explicit FileIconSource(); + virtual ~FileIconSource(); + + // Called when the network layer has requested a resource underneath + // the path we registered. + virtual void StartDataRequest(const std::string& path, int request_id); + + virtual std::string GetMimeType(const std::string&) const { + // Rely on image decoder inferring the correct type. + return std::string(); + } + + // Called when favicon data is available from the history backend. + void OnFileIconDataAvailable( + IconManager::Handle request_handle, + SkBitmap* icon); + + private: + CancelableRequestConsumerT<int, 0> cancelable_consumer_; + + // Raw PNG representation of the favicon to show when the favicon + // database doesn't have a favicon for a webpage. + scoped_refptr<RefCountedBytes> default_favicon_; + + DISALLOW_COPY_AND_ASSIGN(FileIconSource); +}; +#endif // CHROME_BROWSER_DOM_UI_FILEICON_SOURCE_H_ + |