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/downloads_ui.cc | |
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/downloads_ui.cc')
-rw-r--r-- | chrome/browser/dom_ui/downloads_ui.cc | 369 |
1 files changed, 369 insertions, 0 deletions
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); +} + |