OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/dom_ui/downloads_ui.h" |
| 6 |
| 7 #include "base/gfx/png_encoder.h" |
| 8 #include "base/string_piece.h" |
| 9 #include "base/thread.h" |
| 10 #include "base/time.h" |
| 11 #include "base/time_format.h" |
| 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/dom_ui/fileicon_source.h" |
| 14 #include "chrome/browser/download/download_util.h" |
| 15 #include "chrome/browser/metrics/user_metrics.h" |
| 16 #include "chrome/browser/profile.h" |
| 17 #include "chrome/common/jstemplate_builder.h" |
| 18 #include "chrome/common/l10n_util.h" |
| 19 #include "chrome/common/time_format.h" |
| 20 |
| 21 // Generated by GRIT |
| 22 #include "browser_resources.h" |
| 23 #include "generated_resources.h" |
| 24 |
| 25 using base::Time; |
| 26 |
| 27 // DownloadsUI is accessible from chrome-ui://downloads. |
| 28 static const char kDownloadsHost[] = "downloads"; |
| 29 |
| 30 /////////////////////////////////////////////////////////////////////////////// |
| 31 // |
| 32 // DownloadsHTMLSource |
| 33 // |
| 34 /////////////////////////////////////////////////////////////////////////////// |
| 35 |
| 36 DownloadsUIHTMLSource::DownloadsUIHTMLSource() |
| 37 : DataSource(kDownloadsHost, MessageLoop::current()) { |
| 38 } |
| 39 |
| 40 void DownloadsUIHTMLSource::StartDataRequest(const std::string& path, |
| 41 int request_id) { |
| 42 DictionaryValue localized_strings; |
| 43 localized_strings.SetString(L"title", |
| 44 l10n_util::GetString(IDS_DOWNLOAD_TITLE)); |
| 45 localized_strings.SetString(L"searchbutton", |
| 46 l10n_util::GetString(IDS_DOWNLOAD_SEARCH_BUTTON)); |
| 47 localized_strings.SetString(L"no_results", |
| 48 l10n_util::GetString(IDS_DOWNLOAD_SEARCH_BUTTON)); |
| 49 localized_strings.SetString(L"searchresultsfor", |
| 50 l10n_util::GetString(IDS_DOWNLOAD_SEARCHRESULTSFOR)); |
| 51 localized_strings.SetString(L"downloads", |
| 52 l10n_util::GetString(IDS_DOWNLOAD_TITLE)); |
| 53 |
| 54 // Status. |
| 55 localized_strings.SetString(L"status_cancelled", |
| 56 l10n_util::GetString(IDS_DOWNLOAD_TAB_CANCELLED)); |
| 57 localized_strings.SetString(L"status_paused", |
| 58 l10n_util::GetString(IDS_DOWNLOAD_PROGRESS_PAUSED)); |
| 59 |
| 60 // Dangerous file. |
| 61 localized_strings.SetString(L"danger_desc", |
| 62 l10n_util::GetStringF(IDS_PROMPT_DANGEROUS_DOWNLOAD, L"%s")); |
| 63 localized_strings.SetString(L"danger_save", |
| 64 l10n_util::GetString(IDS_SAVE_DOWNLOAD)); |
| 65 localized_strings.SetString(L"danger_discard", |
| 66 l10n_util::GetString(IDS_DISCARD_DOWNLOAD)); |
| 67 |
| 68 // Controls. |
| 69 localized_strings.SetString(L"control_pause", |
| 70 l10n_util::GetString(IDS_DOWNLOAD_LINK_PAUSE)); |
| 71 localized_strings.SetString(L"control_showinfolder", |
| 72 l10n_util::GetString(IDS_DOWNLOAD_LINK_SHOW)); |
| 73 localized_strings.SetString(L"control_cancel", |
| 74 l10n_util::GetString(IDS_DOWNLOAD_LINK_CANCEL)); |
| 75 localized_strings.SetString(L"control_resume", |
| 76 l10n_util::GetString(IDS_DOWNLOAD_LINK_RESUME)); |
| 77 |
| 78 static const StringPiece downloads_html( |
| 79 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 80 IDR_DOWNLOADS_HTML)); |
| 81 const std::string full_html = jstemplate_builder::GetTemplateHtml( |
| 82 downloads_html, &localized_strings, "t"); |
| 83 |
| 84 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); |
| 85 html_bytes->data.resize(full_html.size()); |
| 86 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); |
| 87 |
| 88 SendResponse(request_id, html_bytes); |
| 89 } |
| 90 |
| 91 /////////////////////////////////////////////////////////////////////////////// |
| 92 // |
| 93 // DownloadsDOMHandler |
| 94 // |
| 95 /////////////////////////////////////////////////////////////////////////////// |
| 96 |
| 97 // Sort DownloadItems into descending order by their start time. |
| 98 class DownloadItemSorter : public std::binary_function<DownloadItem*, |
| 99 DownloadItem*, |
| 100 bool> { |
| 101 public: |
| 102 bool operator()(const DownloadItem* lhs, const DownloadItem* rhs) { |
| 103 return lhs->start_time() > rhs->start_time(); |
| 104 } |
| 105 }; |
| 106 |
| 107 DownloadsDOMHandler::DownloadsDOMHandler(DOMUI* dom_ui, DownloadManager* dlm) |
| 108 : DOMMessageHandler(dom_ui), |
| 109 download_manager_(dlm), |
| 110 search_text_() { |
| 111 dom_ui_->RegisterMessageCallback("getDownloads", |
| 112 NewCallback(this, &DownloadsDOMHandler::HandleGetDownloads)); |
| 113 dom_ui_->RegisterMessageCallback("openFile", |
| 114 NewCallback(this, &DownloadsDOMHandler::HandleOpenFile)); |
| 115 |
| 116 dom_ui_->RegisterMessageCallback("drag", |
| 117 NewCallback(this, &DownloadsDOMHandler::HandleDrag)); |
| 118 |
| 119 dom_ui_->RegisterMessageCallback("saveDangerous", |
| 120 NewCallback(this, &DownloadsDOMHandler::HandleSaveDangerous)); |
| 121 dom_ui_->RegisterMessageCallback("discardDangerous", |
| 122 NewCallback(this, &DownloadsDOMHandler::HandleDiscardDangerous)); |
| 123 dom_ui_->RegisterMessageCallback("show", |
| 124 NewCallback(this, &DownloadsDOMHandler::HandleShow)); |
| 125 dom_ui_->RegisterMessageCallback("pause", |
| 126 NewCallback(this, &DownloadsDOMHandler::HandlePause)); |
| 127 dom_ui_->RegisterMessageCallback("cancel", |
| 128 NewCallback(this, &DownloadsDOMHandler::HandleCancel)); |
| 129 |
| 130 // Create our fileicon data source. |
| 131 g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, |
| 132 NewRunnableMethod(&chrome_url_data_manager, |
| 133 &ChromeURLDataManager::AddDataSource, |
| 134 new FileIconSource())); |
| 135 } |
| 136 |
| 137 DownloadsDOMHandler::~DownloadsDOMHandler() { |
| 138 ClearDownloadItems(); |
| 139 download_manager_->RemoveObserver(this); |
| 140 } |
| 141 |
| 142 // DownloadsDOMHandler, public: ----------------------------------------------- |
| 143 |
| 144 void DownloadsDOMHandler::Init() { |
| 145 download_manager_->AddObserver(this); |
| 146 } |
| 147 |
| 148 void DownloadsDOMHandler::OnDownloadUpdated(DownloadItem* download) { |
| 149 // Get the id for the download. Our downloads are sorted latest to first, |
| 150 // and the id is the index into that list. We should be careful of sync |
| 151 // errors between the UI and the download_items_ list (we may wish to use |
| 152 // something other than 'id'). |
| 153 OrderedDownloads::iterator it = find(download_items_.begin(), |
| 154 download_items_.end(), |
| 155 download); |
| 156 if (it == download_items_.end()) |
| 157 return; |
| 158 const int id = static_cast<int>(it - download_items_.begin()); |
| 159 |
| 160 ListValue results_value; |
| 161 results_value.Append(CreateDownloadItemValue(download, id)); |
| 162 dom_ui_->CallJavascriptFunction(L"downloadUpdated", results_value); |
| 163 } |
| 164 |
| 165 // A download has started or been deleted. Query our DownloadManager for the |
| 166 // current set of downloads, which will call us back in SetDownloads once it |
| 167 // has retrieved them. |
| 168 void DownloadsDOMHandler::ModelChanged() { |
| 169 ClearDownloadItems(); |
| 170 download_manager_->GetDownloads(this, search_text_); |
| 171 } |
| 172 |
| 173 void DownloadsDOMHandler::SetDownloads( |
| 174 std::vector<DownloadItem*>& downloads) { |
| 175 ClearDownloadItems(); |
| 176 |
| 177 // Swap new downloads in. |
| 178 download_items_.swap(downloads); |
| 179 sort(download_items_.begin(), download_items_.end(), DownloadItemSorter()); |
| 180 |
| 181 // Scan for any in progress downloads and add ourself to them as an observer. |
| 182 for (OrderedDownloads::iterator it = download_items_.begin(); |
| 183 it != download_items_.end(); ++it) { |
| 184 DownloadItem* download = *it; |
| 185 if (download->state() == DownloadItem::IN_PROGRESS) { |
| 186 // We want to know what happens as the download progresses. |
| 187 download->AddObserver(this); |
| 188 } else if (download->safety_state() == DownloadItem::DANGEROUS) { |
| 189 // We need to be notified when the user validates the dangerous download. |
| 190 download->AddObserver(this); |
| 191 } |
| 192 } |
| 193 |
| 194 SendCurrentDownloads(); |
| 195 } |
| 196 |
| 197 void DownloadsDOMHandler::HandleGetDownloads(const Value* value) { |
| 198 std::wstring new_search = ExtractStringValue(value); |
| 199 if (search_text_.compare(new_search) != 0) { |
| 200 search_text_ = new_search; |
| 201 ClearDownloadItems(); |
| 202 download_manager_->GetDownloads(this, search_text_); |
| 203 } else { |
| 204 SendCurrentDownloads(); |
| 205 } |
| 206 } |
| 207 |
| 208 void DownloadsDOMHandler::HandleOpenFile(const Value* value) { |
| 209 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 210 if (file) |
| 211 download_manager_->OpenDownloadInShell(file, NULL); |
| 212 } |
| 213 |
| 214 void DownloadsDOMHandler::HandleDrag(const Value* value) { |
| 215 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 216 if (file) { |
| 217 IconManager* im = g_browser_process->icon_manager(); |
| 218 SkBitmap* icon = im->LookupIcon(file->full_path().ToWStringHack(), |
| 219 IconLoader::NORMAL); |
| 220 download_util::DragDownload(file, icon); |
| 221 } |
| 222 } |
| 223 |
| 224 void DownloadsDOMHandler::HandleSaveDangerous(const Value* value) { |
| 225 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 226 if (file) |
| 227 download_manager_->DangerousDownloadValidated(file); |
| 228 } |
| 229 |
| 230 void DownloadsDOMHandler::HandleDiscardDangerous(const Value* value) { |
| 231 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 232 if (file) |
| 233 file->Remove(true); |
| 234 } |
| 235 |
| 236 void DownloadsDOMHandler::HandleShow(const Value* value) { |
| 237 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 238 if (file) |
| 239 download_manager_->ShowDownloadInShell(file); |
| 240 } |
| 241 |
| 242 void DownloadsDOMHandler::HandlePause(const Value* value) { |
| 243 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 244 if (file) |
| 245 file->TogglePause(); |
| 246 } |
| 247 |
| 248 void DownloadsDOMHandler::HandleCancel(const Value* value) { |
| 249 DownloadItem* file = GetDownloadById(ExtractIntegerValue(value)); |
| 250 if (file) |
| 251 file->Cancel(true); |
| 252 } |
| 253 |
| 254 // DownloadsDOMHandler, private: ---------------------------------------------- |
| 255 |
| 256 void DownloadsDOMHandler::SendCurrentDownloads() { |
| 257 ListValue results_value; |
| 258 |
| 259 for (OrderedDownloads::iterator it = download_items_.begin(); |
| 260 it != download_items_.end(); ++it) { |
| 261 results_value.Append(CreateDownloadItemValue(*it, |
| 262 static_cast<int>(it - download_items_.begin()))); |
| 263 } |
| 264 |
| 265 dom_ui_->CallJavascriptFunction(L"downloadsList", results_value); |
| 266 } |
| 267 |
| 268 DictionaryValue* DownloadsDOMHandler::CreateDownloadItemValue( |
| 269 DownloadItem* download, int id) { |
| 270 DictionaryValue* file_value = new DictionaryValue(); |
| 271 |
| 272 file_value->SetInteger(L"time", |
| 273 static_cast<int>(download->start_time().ToTimeT())); |
| 274 file_value->SetInteger(L"id", id); |
| 275 file_value->SetString(L"file_path", download->full_path().ToWStringHack()); |
| 276 file_value->SetString(L"file_name", download->GetFileName().ToWStringHack()); |
| 277 file_value->SetString(L"url", download->url().spec()); |
| 278 |
| 279 if (download->state() == DownloadItem::IN_PROGRESS) { |
| 280 if (download->safety_state() == DownloadItem::DANGEROUS) { |
| 281 file_value->SetString(L"state", L"DANGEROUS"); |
| 282 } else if (download->is_paused()) { |
| 283 file_value->SetString(L"state", L"PAUSED"); |
| 284 } else { |
| 285 file_value->SetString(L"state", L"IN_PROGRESS"); |
| 286 } |
| 287 file_value->SetInteger(L"speed", |
| 288 static_cast<int>(download->CurrentSpeed())); |
| 289 file_value->SetInteger(L"percent", |
| 290 static_cast<int>(download->PercentComplete())); |
| 291 file_value->SetInteger(L"received", |
| 292 static_cast<int>(download->received_bytes())); |
| 293 } else if (download->state() == DownloadItem::CANCELLED) { |
| 294 file_value->SetString(L"state", L"CANCELLED"); |
| 295 } else if (download->state() == DownloadItem::COMPLETE) { |
| 296 if (download->safety_state() == DownloadItem::DANGEROUS) { |
| 297 file_value->SetString(L"state", L"DANGEROUS"); |
| 298 } else { |
| 299 file_value->SetString(L"state", L"COMPLETE"); |
| 300 } |
| 301 } |
| 302 |
| 303 file_value->SetInteger(L"total", |
| 304 static_cast<int>(download->total_bytes())); |
| 305 |
| 306 return file_value; |
| 307 } |
| 308 |
| 309 void DownloadsDOMHandler::ClearDownloadItems() { |
| 310 // Clear out old state and remove self as observer for each download. |
| 311 for (OrderedDownloads::iterator it = download_items_.begin(); |
| 312 it != download_items_.end(); ++it) { |
| 313 (*it)->RemoveObserver(this); |
| 314 } |
| 315 download_items_.clear(); |
| 316 } |
| 317 |
| 318 DownloadItem* DownloadsDOMHandler::GetDownloadById(int id) { |
| 319 for (OrderedDownloads::iterator it = download_items_.begin(); |
| 320 it != download_items_.end(); ++it) { |
| 321 if (static_cast<int>(it - download_items_.begin() == id)) { |
| 322 return (*it); |
| 323 } |
| 324 } |
| 325 |
| 326 return NULL; |
| 327 } |
| 328 |
| 329 /////////////////////////////////////////////////////////////////////////////// |
| 330 // |
| 331 // DownloadsUI |
| 332 // |
| 333 /////////////////////////////////////////////////////////////////////////////// |
| 334 |
| 335 DownloadsUI::DownloadsUI(DOMUIContents* contents) : DOMUI(contents) { |
| 336 } |
| 337 |
| 338 void DownloadsUI::Init() { |
| 339 DownloadManager* dlm = get_profile()->GetDownloadManager(); |
| 340 |
| 341 DownloadsDOMHandler* handler = new DownloadsDOMHandler(this, dlm); |
| 342 AddMessageHandler(handler); |
| 343 handler->Init(); |
| 344 |
| 345 DownloadsUIHTMLSource* html_source = new DownloadsUIHTMLSource(); |
| 346 |
| 347 // Set up the chrome-ui://downloads/ source. |
| 348 g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, |
| 349 NewRunnableMethod(&chrome_url_data_manager, |
| 350 &ChromeURLDataManager::AddDataSource, |
| 351 html_source)); |
| 352 } |
| 353 |
| 354 // static |
| 355 GURL DownloadsUI::GetBaseURL() { |
| 356 std::string url = DOMUIContents::GetScheme(); |
| 357 url += "://"; |
| 358 url += kDownloadsHost; |
| 359 return GURL(url); |
| 360 } |
| 361 |
OLD | NEW |