Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/download/download_manager.h" | 5 #include "chrome/browser/download/download_manager.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/i18n/case_conversion.h" | 9 #include "base/i18n/case_conversion.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 13 #include "base/stl_util-inl.h" | 13 #include "base/stl_util-inl.h" |
| 14 #include "base/stringprintf.h" | 14 #include "base/stringprintf.h" |
| 15 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
| 16 #include "base/task.h" | 16 #include "base/task.h" |
| 17 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 19 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/download/download_create_info.h" | |
| 20 #include "chrome/browser/download/download_extensions.h" | 21 #include "chrome/browser/download/download_extensions.h" |
| 21 #include "chrome/browser/download/download_file_manager.h" | 22 #include "chrome/browser/download/download_file_manager.h" |
| 22 #include "chrome/browser/download/download_history.h" | 23 #include "chrome/browser/download/download_history.h" |
| 23 #include "chrome/browser/download/download_item.h" | 24 #include "chrome/browser/download/download_item.h" |
| 24 #include "chrome/browser/download/download_prefs.h" | 25 #include "chrome/browser/download/download_prefs.h" |
| 25 #include "chrome/browser/download/download_process_handle.h" | 26 #include "chrome/browser/download/download_process_handle.h" |
| 26 #include "chrome/browser/download/download_safe_browsing_client.h" | 27 #include "chrome/browser/download/download_safe_browsing_client.h" |
| 27 #include "chrome/browser/download/download_status_updater.h" | 28 #include "chrome/browser/download/download_status_updater.h" |
| 28 #include "chrome/browser/download/download_util.h" | 29 #include "chrome/browser/download/download_util.h" |
| 29 #include "chrome/browser/extensions/extension_service.h" | 30 #include "chrome/browser/extensions/extension_service.h" |
| 30 #include "chrome/browser/history/download_create_info.h" | 31 #include "chrome/browser/history/download_history_info.h" |
| 31 #include "chrome/browser/platform_util.h" | 32 #include "chrome/browser/platform_util.h" |
| 32 #include "chrome/browser/profiles/profile.h" | 33 #include "chrome/browser/profiles/profile.h" |
| 33 #include "chrome/browser/tab_contents/tab_util.h" | 34 #include "chrome/browser/tab_contents/tab_util.h" |
| 34 #include "chrome/browser/ui/browser.h" | 35 #include "chrome/browser/ui/browser.h" |
| 35 #include "chrome/browser/ui/browser_list.h" | 36 #include "chrome/browser/ui/browser_list.h" |
| 36 #include "chrome/browser/ui/download/download_tab_helper.h" | 37 #include "chrome/browser/ui/download/download_tab_helper.h" |
| 37 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 38 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 38 #include "chrome/common/chrome_paths.h" | 39 #include "chrome/common/chrome_paths.h" |
| 39 #include "content/browser/browser_thread.h" | 40 #include "content/browser/browser_thread.h" |
| 40 #include "content/browser/renderer_host/render_process_host.h" | 41 #include "content/browser/renderer_host/render_process_host.h" |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 } | 247 } |
| 247 | 248 |
| 248 // We have received a message from DownloadFileManager about a new download. We | 249 // We have received a message from DownloadFileManager about a new download. We |
| 249 // create a download item and store it in our download map, and inform the | 250 // create a download item and store it in our download map, and inform the |
| 250 // history system of a new download. Since this method can be called while the | 251 // history system of a new download. Since this method can be called while the |
| 251 // history service thread is still reading the persistent state, we do not | 252 // history service thread is still reading the persistent state, we do not |
| 252 // insert the new DownloadItem into 'history_downloads_' or inform our | 253 // insert the new DownloadItem into 'history_downloads_' or inform our |
| 253 // observers at this point. OnCreateDownloadEntryComplete() handles that | 254 // observers at this point. OnCreateDownloadEntryComplete() handles that |
| 254 // finalization of the the download creation as a callback from the | 255 // finalization of the the download creation as a callback from the |
| 255 // history thread. | 256 // history thread. |
| 256 void DownloadManager::StartDownload(DownloadCreateInfo* info) { | 257 void DownloadManager::StartDownload(int32 download_id) { |
| 257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 258 | 259 |
| 260 DownloadItem* download = GetActiveDownloadItem(download_id); | |
| 261 if (!download) | |
| 262 return; | |
| 263 | |
| 259 // Create a client to verify download URL with safebrowsing. | 264 // Create a client to verify download URL with safebrowsing. |
| 260 // It deletes itself after the callback. | 265 // It deletes itself after the callback. |
| 261 scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient( | 266 scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient( |
| 262 info->download_id, info->url_chain, info->referrer_url); | 267 download_id, download->url_chain(), download->referrer_url()); |
| 263 sb_client->CheckDownloadUrl( | 268 sb_client->CheckDownloadUrl( |
| 264 info, NewCallback(this, &DownloadManager::CheckDownloadUrlDone)); | 269 NewCallback(this, &DownloadManager::CheckDownloadUrlDone)); |
| 265 } | 270 } |
| 266 | 271 |
| 267 void DownloadManager::CheckDownloadUrlDone(DownloadCreateInfo* info, | 272 void DownloadManager::CheckDownloadUrlDone(int32 download_id, |
| 268 bool is_dangerous_url) { | 273 bool is_dangerous_url) { |
| 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 270 DCHECK(info); | |
| 271 | 275 |
| 272 info->is_dangerous_url = is_dangerous_url; | 276 DownloadItem* download = GetActiveDownloadItem(download_id); |
| 277 if (!download) | |
| 278 return; | |
| 279 | |
| 280 if (is_dangerous_url) | |
| 281 download->MarkUrlDangerous(); | |
| 282 | |
| 283 DownloadItem::DownloadStateInfo state = download->manager_state(); | |
| 273 | 284 |
| 274 // Check whether this download is for an extension install or not. | 285 // Check whether this download is for an extension install or not. |
| 275 // Allow extensions to be explicitly saved. | 286 // Allow extensions to be explicitly saved. |
| 276 if (!info->prompt_user_for_save_location) { | 287 if (!state.prompt_user_for_save_location) { |
| 277 if (UserScript::IsURLUserScript(info->url(), info->mime_type) || | 288 if (UserScript::IsURLUserScript(download->GetUrl(), |
| 278 info->mime_type == Extension::kMimeType) { | 289 download->mime_type()) || |
| 279 info->is_extension_install = true; | 290 (download->mime_type() == Extension::kMimeType)) { |
| 291 state.is_extension_install = true; | |
| 280 } | 292 } |
| 281 } | 293 } |
| 282 | 294 |
| 283 if (info->save_info.file_path.empty()) { | 295 if (state.force_file_name.empty()) { |
| 284 FilePath generated_name; | 296 FilePath generated_name; |
| 285 download_util::GenerateFileNameFromInfo(info, &generated_name); | 297 download_util::GenerateFileNameFromRequest(download->GetUrl(), |
| 298 download->content_disposition(), | |
| 299 download->referrer_charset(), | |
| 300 download->mime_type(), | |
| 301 &generated_name); | |
| 286 | 302 |
| 287 // Freeze the user's preference for showing a Save As dialog. We're going | 303 // Freeze the user's preference for showing a Save As dialog. We're going |
| 288 // to bounce around a bunch of threads and we don't want to worry about race | 304 // to bounce around a bunch of threads and we don't want to worry about race |
| 289 // conditions where the user changes this pref out from under us. | 305 // conditions where the user changes this pref out from under us. |
| 290 if (download_prefs_->PromptForDownload()) { | 306 if (download_prefs_->PromptForDownload()) { |
| 291 // But ignore the user's preference for the following scenarios: | 307 // But ignore the user's preference for the following scenarios: |
| 292 // 1) Extension installation. Note that we only care here about the case | 308 // 1) Extension installation. Note that we only care here about the case |
| 293 // where an extension is installed, not when one is downloaded with | 309 // where an extension is installed, not when one is downloaded with |
| 294 // "save as...". | 310 // "save as...". |
| 295 // 2) Filetypes marked "always open." If the user just wants this file | 311 // 2) Filetypes marked "always open." If the user just wants this file |
| 296 // opened, don't bother asking where to keep it. | 312 // opened, don't bother asking where to keep it. |
| 297 if (!info->is_extension_install && | 313 if (!state.is_extension_install && |
| 298 !ShouldOpenFileBasedOnExtension(generated_name)) | 314 !ShouldOpenFileBasedOnExtension(generated_name)) |
| 299 info->prompt_user_for_save_location = true; | 315 state.prompt_user_for_save_location = true; |
| 300 } | 316 } |
| 301 if (download_prefs_->IsDownloadPathManaged()) { | 317 if (download_prefs_->IsDownloadPathManaged()) { |
| 302 info->prompt_user_for_save_location = false; | 318 state.prompt_user_for_save_location = false; |
| 303 } | 319 } |
| 304 | 320 |
| 305 // Determine the proper path for a download, by either one of the following: | 321 // Determine the proper path for a download, by either one of the following: |
| 306 // 1) using the default download directory. | 322 // 1) using the default download directory. |
| 307 // 2) prompting the user. | 323 // 2) prompting the user. |
| 308 if (info->prompt_user_for_save_location && !last_download_path_.empty()) { | 324 if (state.prompt_user_for_save_location && !last_download_path_.empty()) { |
| 309 info->suggested_path = last_download_path_; | 325 state.suggested_path = last_download_path_; |
| 310 } else { | 326 } else { |
| 311 info->suggested_path = download_prefs_->download_path(); | 327 state.suggested_path = download_prefs_->download_path(); |
| 312 } | 328 } |
| 313 info->suggested_path = info->suggested_path.Append(generated_name); | 329 state.suggested_path = state.suggested_path.Append(generated_name); |
| 314 } else { | 330 } else { |
| 315 info->suggested_path = info->save_info.file_path; | 331 state.suggested_path = state.force_file_name; |
| 316 } | 332 } |
| 317 | 333 |
| 318 if (!info->prompt_user_for_save_location && | 334 if (!state.prompt_user_for_save_location && state.force_file_name.empty()) { |
| 319 info->save_info.file_path.empty()) { | 335 state.is_dangerous_file = download_util::IsDangerous( |
| 320 info->is_dangerous_file = download_util::IsDangerous( | 336 download->GetUrl(), |
| 321 info, profile(), ShouldOpenFileBasedOnExtension(info->suggested_path)); | 337 download->referrer_url(), |
| 338 state.suggested_path, | |
| 339 state.has_user_gesture, | |
| 340 state.is_extension_install, | |
| 341 profile(), | |
| 342 ShouldOpenFileBasedOnExtension(state.suggested_path)); | |
| 322 } | 343 } |
| 323 | 344 |
| 324 // We need to move over to the download thread because we don't want to stat | 345 // We need to move over to the download thread because we don't want to stat |
| 325 // the suggested path on the UI thread. | 346 // the suggested path on the UI thread. |
| 326 // We can only access preferences on the UI thread, so check the download path | 347 // We can only access preferences on the UI thread, so check the download path |
| 327 // now and pass the value to the FILE thread. | 348 // now and pass the value to the FILE thread. |
| 328 BrowserThread::PostTask( | 349 BrowserThread::PostTask( |
| 329 BrowserThread::FILE, FROM_HERE, | 350 BrowserThread::FILE, FROM_HERE, |
| 330 NewRunnableMethod( | 351 NewRunnableMethod( |
| 331 this, | 352 this, |
| 332 &DownloadManager::CheckIfSuggestedPathExists, | 353 &DownloadManager::CheckIfSuggestedPathExists, |
| 333 info, | 354 download_id, |
| 355 state, | |
| 334 download_prefs()->download_path())); | 356 download_prefs()->download_path())); |
| 335 } | 357 } |
| 336 | 358 |
| 337 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info, | 359 void DownloadManager::CheckIfSuggestedPathExists( |
| 338 const FilePath& default_path) { | 360 int32 download_id, |
| 361 DownloadItem::DownloadStateInfo state, | |
| 362 const FilePath& default_path) { | |
| 339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 340 DCHECK(info); | |
| 341 | 364 |
| 342 // Make sure the default download directory exists. | 365 // Make sure the default download directory exists. |
| 343 // TODO(phajdan.jr): only create the directory when we're sure the user | 366 // TODO(phajdan.jr): only create the directory when we're sure the user |
| 344 // is going to save there and not to another directory of his choice. | 367 // is going to save there and not to another directory of his choice. |
| 345 file_util::CreateDirectory(default_path); | 368 file_util::CreateDirectory(default_path); |
| 346 | 369 |
| 347 // Check writability of the suggested path. If we can't write to it, default | 370 // Check writability of the suggested path. If we can't write to it, default |
| 348 // to the user's "My Documents" directory. We'll prompt them in this case. | 371 // to the user's "My Documents" directory. We'll prompt them in this case. |
| 349 FilePath dir = info->suggested_path.DirName(); | 372 FilePath dir = state.suggested_path.DirName(); |
| 350 FilePath filename = info->suggested_path.BaseName(); | 373 FilePath filename = state.suggested_path.BaseName(); |
| 351 if (!file_util::PathIsWritable(dir)) { | 374 if (!file_util::PathIsWritable(dir)) { |
| 352 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\""; | 375 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\""; |
| 353 info->prompt_user_for_save_location = true; | 376 state.prompt_user_for_save_location = true; |
| 354 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); | 377 PathService::Get(chrome::DIR_USER_DOCUMENTS, &state.suggested_path); |
| 355 info->suggested_path = info->suggested_path.Append(filename); | 378 state.suggested_path = state.suggested_path.Append(filename); |
| 356 } | 379 } |
| 357 | 380 |
| 358 // If the download is deemed dangerous, we'll use a temporary name for it. | 381 // If the download is deemed dangerous, we'll use a temporary name for it. |
| 359 if (info->IsDangerous()) { | 382 if (state.IsDangerous()) { |
| 360 info->original_name = FilePath(info->suggested_path).BaseName(); | 383 state.target_name = FilePath(state.suggested_path).BaseName(); |
| 361 // Create a temporary file to hold the file until the user approves its | 384 // Create a temporary file to hold the file until the user approves its |
| 362 // download. | 385 // download. |
| 363 FilePath::StringType file_name; | 386 FilePath::StringType file_name; |
| 364 FilePath path; | 387 FilePath path; |
| 365 #if defined(OS_WIN) | 388 #if defined(OS_WIN) |
| 366 string16 unconfirmed_prefix = | 389 string16 unconfirmed_prefix = |
| 367 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | 390 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); |
| 368 #else | 391 #else |
| 369 std::string unconfirmed_prefix = | 392 std::string unconfirmed_prefix = |
| 370 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | 393 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); |
| 371 #endif | 394 #endif |
| 372 | 395 |
| 373 while (path.empty()) { | 396 while (path.empty()) { |
| 374 base::SStringPrintf( | 397 base::SStringPrintf( |
| 375 &file_name, | 398 &file_name, |
| 376 unconfirmed_prefix.append( | 399 unconfirmed_prefix.append( |
| 377 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), | 400 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), |
| 378 base::RandInt(0, 100000)); | 401 base::RandInt(0, 100000)); |
| 379 path = dir.Append(file_name); | 402 path = dir.Append(file_name); |
| 380 if (file_util::PathExists(path)) | 403 if (file_util::PathExists(path)) |
| 381 path = FilePath(); | 404 path = FilePath(); |
| 382 } | 405 } |
| 383 info->suggested_path = path; | 406 state.suggested_path = path; |
| 384 } else { | 407 } else { |
| 385 // Do not add the path uniquifier if we are saving to a specific path as in | 408 // Do not add the path uniquifier if we are saving to a specific path as in |
| 386 // the drag-out case. | 409 // the drag-out case. |
| 387 if (info->save_info.file_path.empty()) { | 410 if (state.force_file_name.empty()) { |
| 388 info->path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( | 411 state.path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( |
| 389 info->suggested_path); | 412 state.suggested_path); |
| 390 } | 413 } |
| 391 // We know the final path, build it if necessary. | 414 // We know the final path, build it if necessary. |
| 392 if (info->path_uniquifier > 0) { | 415 if (state.path_uniquifier > 0) { |
| 393 download_util::AppendNumberToPath(&(info->suggested_path), | 416 download_util::AppendNumberToPath(&(state.suggested_path), |
| 394 info->path_uniquifier); | 417 state.path_uniquifier); |
| 395 // Setting path_uniquifier to 0 to make sure we don't try to unique it | 418 // Setting path_uniquifier to 0 to make sure we don't try to unique it |
| 396 // later on. | 419 // later on. |
| 397 info->path_uniquifier = 0; | 420 state.path_uniquifier = 0; |
| 398 } else if (info->path_uniquifier == -1) { | 421 } else if (state.path_uniquifier == -1) { |
| 399 // We failed to find a unique path. We have to prompt the user. | 422 // We failed to find a unique path. We have to prompt the user. |
| 400 VLOG(1) << "Unable to find a unique path for suggested path \"" | 423 VLOG(1) << "Unable to find a unique path for suggested path \"" |
| 401 << info->suggested_path.value() << "\""; | 424 << state.suggested_path.value() << "\""; |
| 402 info->prompt_user_for_save_location = true; | 425 state.prompt_user_for_save_location = true; |
| 403 } | 426 } |
| 404 } | 427 } |
| 405 | 428 |
| 406 // Create an empty file at the suggested path so that we don't allocate the | 429 // Create an empty file at the suggested path so that we don't allocate the |
| 407 // same "non-existant" path to multiple downloads. | 430 // same "non-existant" path to multiple downloads. |
| 408 // See: http://code.google.com/p/chromium/issues/detail?id=3662 | 431 // See: http://code.google.com/p/chromium/issues/detail?id=3662 |
| 409 if (!info->prompt_user_for_save_location && | 432 if (!state.prompt_user_for_save_location && |
| 410 info->save_info.file_path.empty()) { | 433 state.force_file_name.empty()) { |
| 411 if (info->IsDangerous()) | 434 if (state.IsDangerous()) |
| 412 file_util::WriteFile(info->suggested_path, "", 0); | 435 file_util::WriteFile(state.suggested_path, "", 0); |
| 413 else | 436 else |
| 414 file_util::WriteFile(download_util::GetCrDownloadPath( | 437 file_util::WriteFile(download_util::GetCrDownloadPath( |
| 415 info->suggested_path), "", 0); | 438 state.suggested_path), "", 0); |
| 416 } | 439 } |
| 417 | 440 |
| 418 BrowserThread::PostTask( | 441 BrowserThread::PostTask( |
| 419 BrowserThread::UI, FROM_HERE, | 442 BrowserThread::UI, FROM_HERE, |
| 420 NewRunnableMethod(this, | 443 NewRunnableMethod(this, |
| 421 &DownloadManager::OnPathExistenceAvailable, | 444 &DownloadManager::OnPathExistenceAvailable, |
| 422 info)); | 445 download_id, |
| 446 state)); | |
| 423 } | 447 } |
| 424 | 448 |
| 425 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { | 449 void DownloadManager::OnPathExistenceAvailable( |
| 426 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 450 int32 download_id, DownloadItem::DownloadStateInfo new_state) { |
| 427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 451 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 428 DCHECK(info); | |
| 429 | 452 |
| 430 if (info->prompt_user_for_save_location) { | 453 DownloadItem* download = GetActiveDownloadItem(download_id); |
| 454 if (!download) | |
| 455 return; | |
| 456 | |
| 457 VLOG(20) << __FUNCTION__ << "()" | |
| 458 << " download = " << download->DebugString(true); | |
| 459 | |
| 460 download->SetFileCheckResults(new_state); | |
| 461 | |
| 462 FilePath suggested_path = download->suggested_path(); | |
| 463 | |
| 464 if (download->save_as()) { | |
| 431 // We must ask the user for the place to put the download. | 465 // We must ask the user for the place to put the download. |
| 432 if (!select_file_dialog_.get()) | 466 if (!select_file_dialog_.get()) |
| 433 select_file_dialog_ = SelectFileDialog::Create(this); | 467 select_file_dialog_ = SelectFileDialog::Create(this); |
| 434 | 468 |
| 435 TabContents* contents = info->process_handle.GetTabContents(); | 469 DownloadProcessHandle process_handle = download->process_handle(); |
| 470 TabContents* contents = process_handle.GetTabContents(); | |
| 436 SelectFileDialog::FileTypeInfo file_type_info; | 471 SelectFileDialog::FileTypeInfo file_type_info; |
| 437 FilePath::StringType extension = info->suggested_path.Extension(); | 472 FilePath::StringType extension = suggested_path.Extension(); |
| 438 if (!extension.empty()) { | 473 if (!extension.empty()) { |
| 439 extension.erase(extension.begin()); // drop the . | 474 extension.erase(extension.begin()); // drop the . |
| 440 file_type_info.extensions.resize(1); | 475 file_type_info.extensions.resize(1); |
| 441 file_type_info.extensions[0].push_back(extension); | 476 file_type_info.extensions[0].push_back(extension); |
| 442 } | 477 } |
| 443 file_type_info.include_all_files = true; | 478 file_type_info.include_all_files = true; |
| 444 gfx::NativeWindow owning_window = | 479 gfx::NativeWindow owning_window = |
| 445 contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL; | 480 contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL; |
| 481 // |id_ptr| will be deleted in either FileSelected() or | |
| 482 // FileSelectionCancelled(). | |
| 483 int32* id_ptr = new int32; | |
| 484 *id_ptr = download_id; | |
| 446 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, | 485 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, |
| 447 string16(), | 486 string16(), |
| 448 info->suggested_path, | 487 suggested_path, |
| 449 &file_type_info, 0, FILE_PATH_LITERAL(""), | 488 &file_type_info, 0, FILE_PATH_LITERAL(""), |
| 450 contents, owning_window, info); | 489 contents, owning_window, |
| 490 reinterpret_cast<void *>(id_ptr)); | |
|
Paweł Hajdan Jr.
2011/05/20 09:04:42
nit: Is it really "void *" and not "void*"? I thin
ahendrickson
2011/05/20 18:31:25
Done.
| |
| 451 FOR_EACH_OBSERVER(Observer, observers_, | 491 FOR_EACH_OBSERVER(Observer, observers_, |
| 452 SelectFileDialogDisplayed(info->download_id)); | 492 SelectFileDialogDisplayed(download_id)); |
| 453 } else { | 493 } else { |
| 454 // No prompting for download, just continue with the suggested name. | 494 // No prompting for download, just continue with the suggested name. |
| 455 info->path = info->suggested_path; | 495 ContinueDownloadWithPath(download, suggested_path); |
| 456 AttachDownloadItem(info); | |
| 457 } | 496 } |
| 458 } | 497 } |
| 459 | 498 |
| 460 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { | 499 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { |
| 461 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 462 | 501 |
| 463 DownloadItem* download = new DownloadItem(this, *info, | 502 DownloadItem* download = new DownloadItem(this, *info, |
| 464 profile_->IsOffTheRecord()); | 503 profile_->IsOffTheRecord()); |
| 465 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 504 int32 download_id = info->download_id; |
| 466 DCHECK(!ContainsKey(active_downloads_, info->download_id)); | 505 DCHECK(!ContainsKey(in_progress_, download_id)); |
| 506 DCHECK(!ContainsKey(active_downloads_, download_id)); | |
| 467 downloads_.insert(download); | 507 downloads_.insert(download); |
| 468 active_downloads_[info->download_id] = download; | 508 active_downloads_[download_id] = download; |
| 469 } | 509 } |
| 470 | 510 |
| 471 void DownloadManager::AttachDownloadItem(DownloadCreateInfo* info) { | 511 void DownloadManager::ContinueDownloadWithPath(DownloadItem* download, |
| 472 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 512 const FilePath& chosen_file) { |
| 513 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 514 DCHECK(download); | |
| 473 | 515 |
| 474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 516 int32 download_id = download->id(); |
| 475 | |
| 476 // Life of |info| ends here. No more references to it after this method. | |
| 477 scoped_ptr<DownloadCreateInfo> infop(info); | |
| 478 | 517 |
| 479 // NOTE(ahendrickson) Eventually |active_downloads_| will replace | 518 // NOTE(ahendrickson) Eventually |active_downloads_| will replace |
| 480 // |in_progress_|, but we don't want to change the semantics yet. | 519 // |in_progress_|, but we don't want to change the semantics yet. |
| 481 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 520 DCHECK(!ContainsKey(in_progress_, download_id)); |
| 482 DCHECK(ContainsKey(active_downloads_, info->download_id)); | |
| 483 DownloadItem* download = active_downloads_[info->download_id]; | |
| 484 DCHECK(download != NULL); | |
| 485 DCHECK(ContainsKey(downloads_, download)); | 521 DCHECK(ContainsKey(downloads_, download)); |
| 522 if (!ContainsKey(active_downloads_, download_id)) | |
| 523 return; | |
| 486 | 524 |
| 487 download->SetFileCheckResults(info->path, | 525 // Make sure the initial file name is set only once. |
| 488 info->is_dangerous_file, | 526 DCHECK(download->full_path().empty()); |
| 489 info->is_dangerous_url, | 527 download->OnPathDetermined(chosen_file); |
| 490 info->path_uniquifier, | 528 download->UpdateTarget(); |
| 491 info->prompt_user_for_save_location, | 529 |
| 492 info->is_extension_install, | 530 VLOG(20) << __FUNCTION__ << "()" |
| 493 info->original_name); | 531 << " download = " << download->DebugString(true); |
| 494 in_progress_[info->download_id] = download; | 532 |
| 533 in_progress_[download_id] = download; | |
| 495 UpdateAppIcon(); // Reflect entry into in_progress_. | 534 UpdateAppIcon(); // Reflect entry into in_progress_. |
| 496 | 535 |
| 497 // Rename to intermediate name. | 536 // Rename to intermediate name. |
| 498 FilePath download_path; | 537 FilePath download_path; |
| 499 if (info->IsDangerous()) { | 538 if (download->IsDangerous()) { |
| 500 // The download is not safe. We can now rename the file to its | 539 // The download is not safe. We can now rename the file to its |
| 501 // tentative name using RenameInProgressDownloadFile. | 540 // tentative name using RenameInProgressDownloadFile. |
| 502 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're | 541 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're |
| 503 // renaming it to the same name. | 542 // renaming it to the same name. |
| 504 download_path = info->path; | 543 download_path = download->full_path(); |
| 505 } else { | 544 } else { |
| 506 // The download is a safe download. We need to | 545 // The download is a safe download. We need to |
| 507 // rename it to its intermediate '.crdownload' path. The final | 546 // rename it to its intermediate '.crdownload' path. The final |
| 508 // name after user confirmation will be set from | 547 // name after user confirmation will be set from |
| 509 // DownloadItem::OnDownloadCompleting. | 548 // DownloadItem::OnDownloadCompleting. |
| 510 download_path = download_util::GetCrDownloadPath(info->path); | 549 download_path = |
| 550 download_util::GetCrDownloadPath(download->full_path()); | |
| 511 } | 551 } |
| 512 | 552 |
| 513 BrowserThread::PostTask( | 553 BrowserThread::PostTask( |
| 514 BrowserThread::FILE, FROM_HERE, | 554 BrowserThread::FILE, FROM_HERE, |
| 515 NewRunnableMethod( | 555 NewRunnableMethod( |
| 516 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile, | 556 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile, |
| 517 download->id(), download_path)); | 557 download->id(), download_path)); |
| 518 | 558 |
| 519 download->Rename(download_path); | 559 download->Rename(download_path); |
| 520 | 560 |
| 521 download_history_->AddEntry(*info, download, | 561 download_history_->AddEntry(download, |
| 522 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); | 562 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); |
| 523 } | 563 } |
| 524 | 564 |
| 525 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { | 565 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { |
| 526 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 527 DownloadMap::iterator it = active_downloads_.find(download_id); | 567 DownloadMap::iterator it = active_downloads_.find(download_id); |
| 528 if (it != active_downloads_.end()) { | 568 if (it != active_downloads_.end()) { |
| 529 DownloadItem* download = it->second; | 569 DownloadItem* download = it->second; |
| 530 if (download->IsInProgress()) { | 570 if (download->IsInProgress()) { |
| 531 download->Update(size); | 571 download->Update(size); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 584 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 624 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 585 DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id | 625 DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id |
| 586 << " is dangerous_hash: " << is_dangerous_hash; | 626 << " is dangerous_hash: " << is_dangerous_hash; |
| 587 | 627 |
| 588 // If it's not in active_downloads_, that means it was cancelled or | 628 // If it's not in active_downloads_, that means it was cancelled or |
| 589 // the download already finished. | 629 // the download already finished. |
| 590 if (active_downloads_.count(download_id) == 0) | 630 if (active_downloads_.count(download_id) == 0) |
| 591 return; | 631 return; |
| 592 | 632 |
| 593 DVLOG(1) << "CheckDownloadHashDone, url: " | 633 DVLOG(1) << "CheckDownloadHashDone, url: " |
| 594 << active_downloads_[download_id]->url().spec(); | 634 << active_downloads_[download_id]->GetUrl().spec(); |
| 595 } | 635 } |
| 596 | 636 |
| 597 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { | 637 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { |
| 598 // If we don't have all the data, the download is not ready for | 638 // If we don't have all the data, the download is not ready for |
| 599 // completion. | 639 // completion. |
| 600 if (!download->all_data_saved()) | 640 if (!download->all_data_saved()) |
| 601 return false; | 641 return false; |
| 602 | 642 |
| 603 // If the download is dangerous, but not yet validated, it's not ready for | 643 // If the download is dangerous, but not yet validated, it's not ready for |
| 604 // completion. | 644 // completion. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 int os_error) { | 765 int os_error) { |
| 726 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 766 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 727 DownloadMap::iterator it = active_downloads_.find(download_id); | 767 DownloadMap::iterator it = active_downloads_.find(download_id); |
| 728 // A cancel at the right time could remove the download from the | 768 // A cancel at the right time could remove the download from the |
| 729 // |active_downloads_| map before we get here. | 769 // |active_downloads_| map before we get here. |
| 730 if (it == active_downloads_.end()) | 770 if (it == active_downloads_.end()) |
| 731 return; | 771 return; |
| 732 | 772 |
| 733 DownloadItem* download = it->second; | 773 DownloadItem* download = it->second; |
| 734 | 774 |
| 735 VLOG(20) << "Error " << os_error << " at offset " | 775 VLOG(20) << __FUNCTION__ << "()" << " Error " << os_error |
| 736 << download->received_bytes() << " for download = " | 776 << " at offset " << download->received_bytes() |
| 737 << download->DebugString(true); | 777 << " for download = " << download->DebugString(true); |
| 778 | |
| 779 download->Interrupted(size, os_error); | |
| 738 | 780 |
| 739 // TODO(ahendrickson) - Remove this when we add resuming of interrupted | 781 // TODO(ahendrickson) - Remove this when we add resuming of interrupted |
| 740 // downloads, as we will keep the download item around in that case. | 782 // downloads, as we will keep the download item around in that case. |
| 741 // | 783 // |
| 742 // Clean up will happen when the history system create callback runs if we | 784 // Clean up will happen when the history system create callback runs if we |
| 743 // don't have a valid db_handle yet. | 785 // don't have a valid db_handle yet. |
| 744 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { | 786 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
| 745 in_progress_.erase(download_id); | 787 in_progress_.erase(download_id); |
| 746 active_downloads_.erase(download_id); | 788 active_downloads_.erase(download_id); |
| 747 UpdateAppIcon(); // Reflect removal from in_progress_. | 789 UpdateAppIcon(); // Reflect removal from in_progress_. |
| 748 download_history_->UpdateEntry(download); | 790 download_history_->UpdateEntry(download); |
| 749 } | 791 } |
| 750 | 792 |
| 751 download->Interrupted(size, os_error); | |
| 752 | |
| 753 BrowserThread::PostTask( | 793 BrowserThread::PostTask( |
| 754 BrowserThread::FILE, FROM_HERE, | 794 BrowserThread::FILE, FROM_HERE, |
| 755 NewRunnableMethod( | 795 NewRunnableMethod( |
| 756 file_manager_, &DownloadFileManager::CancelDownload, download_id)); | 796 file_manager_, &DownloadFileManager::CancelDownload, download_id)); |
| 757 } | 797 } |
| 758 | 798 |
| 759 void DownloadManager::PauseDownload(int32 download_id, bool pause) { | 799 void DownloadManager::PauseDownload(int32 download_id, bool pause) { |
| 760 DownloadMap::iterator it = in_progress_.find(download_id); | 800 DownloadMap::iterator it = in_progress_.find(download_id); |
| 761 if (it == in_progress_.end()) | 801 if (it == in_progress_.end()) |
| 762 return; | 802 return; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 959 int64 total_bytes = 0; | 999 int64 total_bytes = 0; |
| 960 for (DownloadMap::iterator i = in_progress_.begin(); | 1000 for (DownloadMap::iterator i = in_progress_.begin(); |
| 961 i != in_progress_.end(); ++i) { | 1001 i != in_progress_.end(); ++i) { |
| 962 total_bytes += i->second->total_bytes(); | 1002 total_bytes += i->second->total_bytes(); |
| 963 } | 1003 } |
| 964 return total_bytes; | 1004 return total_bytes; |
| 965 } | 1005 } |
| 966 | 1006 |
| 967 void DownloadManager::FileSelected(const FilePath& path, | 1007 void DownloadManager::FileSelected(const FilePath& path, |
| 968 int index, void* params) { | 1008 int index, void* params) { |
| 969 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1009 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 970 if (info->prompt_user_for_save_location) | 1010 |
| 1011 int32* id_ptr = reinterpret_cast<int32 *>(params); | |
|
Paweł Hajdan Jr.
2011/05/20 09:04:42
nit: Is it really "int32 *" and not "int32*"? I th
ahendrickson
2011/05/20 18:31:25
Done.
| |
| 1012 DCHECK(id_ptr != NULL); | |
| 1013 int32 download_id = *id_ptr; | |
| 1014 delete id_ptr; | |
| 1015 | |
| 1016 DownloadItem* download = GetActiveDownloadItem(download_id); | |
| 1017 if (!download) | |
| 1018 return; | |
| 1019 VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\"" | |
| 1020 << " download = " << download->DebugString(true); | |
| 1021 | |
| 1022 if (download->save_as()) | |
| 971 last_download_path_ = path.DirName(); | 1023 last_download_path_ = path.DirName(); |
| 972 | 1024 |
| 973 info->path = path; | 1025 // Make sure the initial file name is set only once. |
| 974 AttachDownloadItem(info); | 1026 ContinueDownloadWithPath(download, path); |
| 975 } | 1027 } |
| 976 | 1028 |
| 977 void DownloadManager::FileSelectionCanceled(void* params) { | 1029 void DownloadManager::FileSelectionCanceled(void* params) { |
| 978 // The user didn't pick a place to save the file, so need to cancel the | 1030 // The user didn't pick a place to save the file, so need to cancel the |
| 979 // download that's already in progress to the temporary location. | 1031 // download that's already in progress to the temporary location. |
| 980 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1032 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 981 DownloadCancelledInternal(info->download_id, info->process_handle); | 1033 int32* id_ptr = reinterpret_cast<int32 *>(params); |
|
Paweł Hajdan Jr.
2011/05/20 09:04:42
nit: Is it really "int32 *" and not "int32*"? I th
ahendrickson
2011/05/20 18:31:25
Done.
| |
| 1034 DCHECK(id_ptr != NULL); | |
| 1035 int32 download_id = *id_ptr; | |
| 1036 delete id_ptr; | |
| 1037 | |
| 1038 DownloadItem* download = GetActiveDownloadItem(download_id); | |
| 1039 if (!download) | |
| 1040 return; | |
| 1041 | |
| 1042 VLOG(20) << __FUNCTION__ << "()" | |
| 1043 << " download = " << download->DebugString(true); | |
| 1044 | |
| 1045 DownloadCancelledInternal(download_id, download->process_handle()); | |
| 982 } | 1046 } |
| 983 | 1047 |
| 984 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { | 1048 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { |
| 985 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1049 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 986 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); | 1050 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); |
| 987 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); | 1051 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); |
| 988 download->UpdateObservers(); | 1052 download->UpdateObservers(); |
| 989 | 1053 |
| 990 MaybeCompleteDownload(download); | 1054 MaybeCompleteDownload(download); |
| 991 } | 1055 } |
| 992 | 1056 |
| 993 // Operations posted to us from the history service ---------------------------- | 1057 // Operations posted to us from the history service ---------------------------- |
| 994 | 1058 |
| 995 // The history service has retrieved all download entries. 'entries' contains | 1059 // The history service has retrieved all download entries. 'entries' contains |
| 996 // 'DownloadCreateInfo's in sorted order (by ascending start_time). | 1060 // 'DownloadHistoryInfo's in sorted order (by ascending start_time). |
| 997 void DownloadManager::OnQueryDownloadEntriesComplete( | 1061 void DownloadManager::OnQueryDownloadEntriesComplete( |
| 998 std::vector<DownloadCreateInfo>* entries) { | 1062 std::vector<DownloadHistoryInfo>* entries) { |
| 999 for (size_t i = 0; i < entries->size(); ++i) { | 1063 for (size_t i = 0; i < entries->size(); ++i) { |
| 1000 DownloadItem* download = new DownloadItem(this, entries->at(i)); | 1064 DownloadItem* download = new DownloadItem(this, entries->at(i)); |
| 1001 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); | 1065 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
| 1002 downloads_.insert(download); | 1066 downloads_.insert(download); |
| 1003 history_downloads_[download->db_handle()] = download; | 1067 history_downloads_[download->db_handle()] = download; |
| 1004 VLOG(20) << __FUNCTION__ << "()" << i << ">" | 1068 VLOG(20) << __FUNCTION__ << "()" << i << ">" |
| 1005 << " download = " << download->DebugString(true); | 1069 << " download = " << download->DebugString(true); |
| 1006 } | 1070 } |
| 1007 NotifyModelChanged(); | 1071 NotifyModelChanged(); |
| 1008 } | 1072 } |
| 1009 | 1073 |
| 1010 // Once the new DownloadItem's creation info has been committed to the history | 1074 // Once the new DownloadItem's creation info has been committed to the history |
| 1011 // service, we associate the DownloadItem with the db handle, update our | 1075 // service, we associate the DownloadItem with the db handle, update our |
| 1012 // 'history_downloads_' map and inform observers. | 1076 // 'history_downloads_' map and inform observers. |
| 1013 void DownloadManager::OnCreateDownloadEntryComplete( | 1077 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, |
| 1014 DownloadCreateInfo info, | 1078 int64 db_handle) { |
| 1015 int64 db_handle) { | |
| 1016 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1079 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1017 DownloadMap::iterator it = in_progress_.find(info.download_id); | 1080 DownloadItem* download = GetActiveDownloadItem(download_id); |
| 1018 DCHECK(it != in_progress_.end()); | 1081 if (!download) |
| 1082 return; | |
| 1019 | 1083 |
| 1020 DownloadItem* download = it->second; | |
| 1021 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle | 1084 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle |
| 1022 << " download_id = " << info.download_id | 1085 << " download_id = " << download_id |
| 1023 << " download = " << download->DebugString(true); | 1086 << " download = " << download->DebugString(true); |
| 1024 | 1087 |
| 1025 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 1088 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
| 1026 // call this function with an invalid |db_handle|. For instance, this can | 1089 // call this function with an invalid |db_handle|. For instance, this can |
| 1027 // happen when the history database is offline. We cannot have multiple | 1090 // happen when the history database is offline. We cannot have multiple |
| 1028 // DownloadItems with the same invalid db_handle, so we need to assign a | 1091 // DownloadItems with the same invalid db_handle, so we need to assign a |
| 1029 // unique |db_handle| here. | 1092 // unique |db_handle| here. |
| 1030 if (db_handle == DownloadHistory::kUninitializedHandle) | 1093 if (db_handle == DownloadHistory::kUninitializedHandle) |
| 1031 db_handle = download_history_->GetNextFakeDbHandle(); | 1094 db_handle = download_history_->GetNextFakeDbHandle(); |
| 1032 | 1095 |
| 1033 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); | 1096 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
| 1034 download->set_db_handle(db_handle); | 1097 download->set_db_handle(db_handle); |
| 1035 | 1098 |
| 1036 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); | 1099 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
| 1037 history_downloads_[download->db_handle()] = download; | 1100 history_downloads_[download->db_handle()] = download; |
| 1038 | 1101 |
| 1039 // Show in the appropriate browser UI. | 1102 // Show in the appropriate browser UI. |
| 1040 // This includes buttons to save or cancel, for a dangerous download. | 1103 // This includes buttons to save or cancel, for a dangerous download. |
| 1041 ShowDownloadInBrowser(&info.process_handle, download); | 1104 ShowDownloadInBrowser(download); |
| 1042 | 1105 |
| 1043 // Inform interested objects about the new download. | 1106 // Inform interested objects about the new download. |
| 1044 NotifyModelChanged(); | 1107 NotifyModelChanged(); |
| 1045 | 1108 |
| 1046 // If the download is still in progress, try to complete it. | 1109 // If the download is still in progress, try to complete it. |
| 1047 // | 1110 // |
| 1048 // Otherwise, download has been cancelled or interrupted before we've | 1111 // Otherwise, download has been cancelled or interrupted before we've |
| 1049 // received the DB handle. We post one final message to the history | 1112 // received the DB handle. We post one final message to the history |
| 1050 // service so that it can be properly in sync with the DownloadItem's | 1113 // service so that it can be properly in sync with the DownloadItem's |
| 1051 // completion status, and also inform any observers so that they get | 1114 // completion status, and also inform any observers so that they get |
| 1052 // more than just the start notification. | 1115 // more than just the start notification. |
| 1053 if (download->IsInProgress()) { | 1116 if (download->IsInProgress()) { |
| 1054 MaybeCompleteDownload(download); | 1117 MaybeCompleteDownload(download); |
| 1055 } else { | 1118 } else { |
| 1056 DCHECK(download->IsCancelled()) | 1119 DCHECK(download->IsCancelled()) |
| 1057 << " download = " << download->DebugString(true); | 1120 << " download = " << download->DebugString(true); |
| 1058 in_progress_.erase(it); | 1121 in_progress_.erase(download_id); |
| 1059 active_downloads_.erase(info.download_id); | 1122 active_downloads_.erase(download_id); |
| 1060 download_history_->UpdateEntry(download); | 1123 download_history_->UpdateEntry(download); |
| 1061 download->UpdateObservers(); | 1124 download->UpdateObservers(); |
| 1062 } | 1125 } |
| 1063 } | 1126 } |
| 1064 | 1127 |
| 1065 void DownloadManager::ShowDownloadInBrowser( | 1128 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) { |
| 1066 DownloadProcessHandle* process_handle, DownloadItem* download) { | |
| 1067 if (!process_handle) | |
| 1068 return; | |
| 1069 | 1129 |
| 1070 // The 'contents' may no longer exist if the user closed the tab before we | 1130 // The 'contents' may no longer exist if the user closed the tab before we |
| 1071 // get this start completion event. If it does, tell the origin TabContents | 1131 // get this start completion event. If it does, tell the origin TabContents |
| 1072 // to display its download shelf. | 1132 // to display its download shelf. |
| 1073 TabContents* contents = process_handle->GetTabContents(); | 1133 DownloadProcessHandle process_handle = download->process_handle(); |
| 1134 TabContents* contents = process_handle.GetTabContents(); | |
| 1074 TabContentsWrapper* wrapper = NULL; | 1135 TabContentsWrapper* wrapper = NULL; |
| 1075 if (contents) | 1136 if (contents) |
| 1076 wrapper = TabContentsWrapper::GetCurrentWrapperForContents(contents); | 1137 wrapper = TabContentsWrapper::GetCurrentWrapperForContents(contents); |
| 1077 | 1138 |
| 1078 // If the contents no longer exists, we start the download in the last active | 1139 // If the contents no longer exists, we start the download in the last active |
| 1079 // browser. This is not ideal but better than fully hiding the download from | 1140 // browser. This is not ideal but better than fully hiding the download from |
| 1080 // the user. | 1141 // the user. |
| 1081 if (!wrapper) { | 1142 if (!wrapper) { |
| 1082 Browser* last_active = BrowserList::GetLastActive(); | 1143 Browser* last_active = BrowserList::GetLastActive(); |
| 1083 if (last_active) | 1144 if (last_active) |
| 1084 wrapper = last_active->GetSelectedTabContentsWrapper(); | 1145 wrapper = last_active->GetSelectedTabContentsWrapper(); |
| 1085 } | 1146 } |
| 1086 | 1147 |
| 1087 if (!wrapper) | 1148 if (!wrapper) |
| 1088 return; | 1149 return; |
| 1089 | 1150 |
| 1090 wrapper->download_tab_helper()->OnStartDownload(download); | 1151 wrapper->download_tab_helper()->OnStartDownload(download); |
| 1091 } | 1152 } |
| 1092 | 1153 |
| 1093 // Clears the last download path, used to initialize "save as" dialogs. | 1154 // Clears the last download path, used to initialize "save as" dialogs. |
| 1094 void DownloadManager::ClearLastDownloadPath() { | 1155 void DownloadManager::ClearLastDownloadPath() { |
| 1095 last_download_path_ = FilePath(); | 1156 last_download_path_ = FilePath(); |
| 1096 } | 1157 } |
| 1097 | 1158 |
| 1098 void DownloadManager::NotifyModelChanged() { | 1159 void DownloadManager::NotifyModelChanged() { |
| 1099 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged()); | 1160 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged()); |
| 1100 } | 1161 } |
| 1101 | 1162 |
| 1102 DownloadItem* DownloadManager::GetDownloadItem(int id) { | 1163 DownloadItem* DownloadManager::GetDownloadItem(int download_id) { |
| 1103 for (DownloadMap::iterator it = history_downloads_.begin(); | 1164 for (DownloadMap::iterator it = history_downloads_.begin(); |
| 1104 it != history_downloads_.end(); ++it) { | 1165 it != history_downloads_.end(); ++it) { |
| 1105 DownloadItem* item = it->second; | 1166 DownloadItem* item = it->second; |
| 1106 if (item->id() == id) | 1167 if (item->id() == download_id) |
| 1107 return item; | 1168 return item; |
| 1108 } | 1169 } |
| 1109 return NULL; | 1170 return NULL; |
| 1110 } | 1171 } |
| 1111 | 1172 |
| 1173 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) { | |
| 1174 DCHECK(ContainsKey(active_downloads_, download_id)); | |
| 1175 DownloadItem* download = active_downloads_[download_id]; | |
| 1176 DCHECK(download != NULL); | |
| 1177 return download; | |
| 1178 } | |
| 1179 | |
| 1112 // Confirm that everything in all maps is also in |downloads_|, and that | 1180 // Confirm that everything in all maps is also in |downloads_|, and that |
| 1113 // everything in |downloads_| is also in some other map. | 1181 // everything in |downloads_| is also in some other map. |
| 1114 void DownloadManager::AssertContainersConsistent() const { | 1182 void DownloadManager::AssertContainersConsistent() const { |
| 1115 #if !defined(NDEBUG) | 1183 #if !defined(NDEBUG) |
| 1116 // Turn everything into sets. | 1184 // Turn everything into sets. |
| 1117 DownloadSet active_set, history_set; | 1185 DownloadSet active_set, history_set; |
| 1118 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; | 1186 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; |
| 1119 DownloadSet* local_sets[] = {&active_set, &history_set}; | 1187 DownloadSet* local_sets[] = {&active_set, &history_set}; |
| 1120 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); | 1188 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); |
| 1121 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { | 1189 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1175 observed_download_manager_->RemoveObserver(this); | 1243 observed_download_manager_->RemoveObserver(this); |
| 1176 } | 1244 } |
| 1177 | 1245 |
| 1178 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1246 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
| 1179 observing_download_manager_->NotifyModelChanged(); | 1247 observing_download_manager_->NotifyModelChanged(); |
| 1180 } | 1248 } |
| 1181 | 1249 |
| 1182 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1250 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1183 observed_download_manager_ = NULL; | 1251 observed_download_manager_ = NULL; |
| 1184 } | 1252 } |
| OLD | NEW |