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 DownloadStateInfo state = download->state_info(); |
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 = IsDangerous(*download, state); |
320 info->is_dangerous_file = download_util::IsDangerous( | |
321 info, profile(), ShouldOpenFileBasedOnExtension(info->suggested_path)); | |
322 } | |
323 | 336 |
324 // We need to move over to the download thread because we don't want to stat | 337 // We need to move over to the download thread because we don't want to stat |
325 // the suggested path on the UI thread. | 338 // the suggested path on the UI thread. |
326 // We can only access preferences on the UI thread, so check the download path | 339 // We can only access preferences on the UI thread, so check the download path |
327 // now and pass the value to the FILE thread. | 340 // now and pass the value to the FILE thread. |
328 BrowserThread::PostTask( | 341 BrowserThread::PostTask( |
329 BrowserThread::FILE, FROM_HERE, | 342 BrowserThread::FILE, FROM_HERE, |
330 NewRunnableMethod( | 343 NewRunnableMethod( |
331 this, | 344 this, |
332 &DownloadManager::CheckIfSuggestedPathExists, | 345 &DownloadManager::CheckIfSuggestedPathExists, |
333 info, | 346 download_id, |
| 347 state, |
334 download_prefs()->download_path())); | 348 download_prefs()->download_path())); |
335 } | 349 } |
336 | 350 |
337 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info, | 351 void DownloadManager::CheckIfSuggestedPathExists(int32 download_id, |
| 352 DownloadStateInfo state, |
338 const FilePath& default_path) { | 353 const FilePath& default_path) { |
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
340 DCHECK(info); | |
341 | 355 |
342 // Make sure the default download directory exists. | 356 // Make sure the default download directory exists. |
343 // TODO(phajdan.jr): only create the directory when we're sure the user | 357 // 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. | 358 // is going to save there and not to another directory of his choice. |
345 file_util::CreateDirectory(default_path); | 359 file_util::CreateDirectory(default_path); |
346 | 360 |
347 // Check writability of the suggested path. If we can't write to it, default | 361 // 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. | 362 // to the user's "My Documents" directory. We'll prompt them in this case. |
349 FilePath dir = info->suggested_path.DirName(); | 363 FilePath dir = state.suggested_path.DirName(); |
350 FilePath filename = info->suggested_path.BaseName(); | 364 FilePath filename = state.suggested_path.BaseName(); |
351 if (!file_util::PathIsWritable(dir)) { | 365 if (!file_util::PathIsWritable(dir)) { |
352 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\""; | 366 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\""; |
353 info->prompt_user_for_save_location = true; | 367 state.prompt_user_for_save_location = true; |
354 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); | 368 PathService::Get(chrome::DIR_USER_DOCUMENTS, &state.suggested_path); |
355 info->suggested_path = info->suggested_path.Append(filename); | 369 state.suggested_path = state.suggested_path.Append(filename); |
356 } | 370 } |
357 | 371 |
358 // If the download is deemed dangerous, we'll use a temporary name for it. | 372 // If the download is deemed dangerous, we'll use a temporary name for it. |
359 if (info->IsDangerous()) { | 373 if (state.IsDangerous()) { |
360 info->original_name = FilePath(info->suggested_path).BaseName(); | 374 state.target_name = FilePath(state.suggested_path).BaseName(); |
361 // Create a temporary file to hold the file until the user approves its | 375 // Create a temporary file to hold the file until the user approves its |
362 // download. | 376 // download. |
363 FilePath::StringType file_name; | 377 FilePath::StringType file_name; |
364 FilePath path; | 378 FilePath path; |
365 #if defined(OS_WIN) | 379 #if defined(OS_WIN) |
366 string16 unconfirmed_prefix = | 380 string16 unconfirmed_prefix = |
367 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | 381 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); |
368 #else | 382 #else |
369 std::string unconfirmed_prefix = | 383 std::string unconfirmed_prefix = |
370 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | 384 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); |
371 #endif | 385 #endif |
372 | 386 |
373 while (path.empty()) { | 387 while (path.empty()) { |
374 base::SStringPrintf( | 388 base::SStringPrintf( |
375 &file_name, | 389 &file_name, |
376 unconfirmed_prefix.append( | 390 unconfirmed_prefix.append( |
377 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), | 391 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), |
378 base::RandInt(0, 100000)); | 392 base::RandInt(0, 100000)); |
379 path = dir.Append(file_name); | 393 path = dir.Append(file_name); |
380 if (file_util::PathExists(path)) | 394 if (file_util::PathExists(path)) |
381 path = FilePath(); | 395 path = FilePath(); |
382 } | 396 } |
383 info->suggested_path = path; | 397 state.suggested_path = path; |
384 } else { | 398 } else { |
385 // Do not add the path uniquifier if we are saving to a specific path as in | 399 // Do not add the path uniquifier if we are saving to a specific path as in |
386 // the drag-out case. | 400 // the drag-out case. |
387 if (info->save_info.file_path.empty()) { | 401 if (state.force_file_name.empty()) { |
388 info->path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( | 402 state.path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( |
389 info->suggested_path); | 403 state.suggested_path); |
390 } | 404 } |
391 // We know the final path, build it if necessary. | 405 // We know the final path, build it if necessary. |
392 if (info->path_uniquifier > 0) { | 406 if (state.path_uniquifier > 0) { |
393 download_util::AppendNumberToPath(&(info->suggested_path), | 407 download_util::AppendNumberToPath(&(state.suggested_path), |
394 info->path_uniquifier); | 408 state.path_uniquifier); |
395 // Setting path_uniquifier to 0 to make sure we don't try to unique it | 409 // Setting path_uniquifier to 0 to make sure we don't try to unique it |
396 // later on. | 410 // later on. |
397 info->path_uniquifier = 0; | 411 state.path_uniquifier = 0; |
398 } else if (info->path_uniquifier == -1) { | 412 } else if (state.path_uniquifier == -1) { |
399 // We failed to find a unique path. We have to prompt the user. | 413 // 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 \"" | 414 VLOG(1) << "Unable to find a unique path for suggested path \"" |
401 << info->suggested_path.value() << "\""; | 415 << state.suggested_path.value() << "\""; |
402 info->prompt_user_for_save_location = true; | 416 state.prompt_user_for_save_location = true; |
403 } | 417 } |
404 } | 418 } |
405 | 419 |
406 // Create an empty file at the suggested path so that we don't allocate the | 420 // Create an empty file at the suggested path so that we don't allocate the |
407 // same "non-existant" path to multiple downloads. | 421 // same "non-existant" path to multiple downloads. |
408 // See: http://code.google.com/p/chromium/issues/detail?id=3662 | 422 // See: http://code.google.com/p/chromium/issues/detail?id=3662 |
409 if (!info->prompt_user_for_save_location && | 423 if (!state.prompt_user_for_save_location && |
410 info->save_info.file_path.empty()) { | 424 state.force_file_name.empty()) { |
411 if (info->IsDangerous()) | 425 if (state.IsDangerous()) |
412 file_util::WriteFile(info->suggested_path, "", 0); | 426 file_util::WriteFile(state.suggested_path, "", 0); |
413 else | 427 else |
414 file_util::WriteFile(download_util::GetCrDownloadPath( | 428 file_util::WriteFile(download_util::GetCrDownloadPath( |
415 info->suggested_path), "", 0); | 429 state.suggested_path), "", 0); |
416 } | 430 } |
417 | 431 |
418 BrowserThread::PostTask( | 432 BrowserThread::PostTask( |
419 BrowserThread::UI, FROM_HERE, | 433 BrowserThread::UI, FROM_HERE, |
420 NewRunnableMethod(this, | 434 NewRunnableMethod(this, |
421 &DownloadManager::OnPathExistenceAvailable, | 435 &DownloadManager::OnPathExistenceAvailable, |
422 info)); | 436 download_id, |
| 437 state)); |
423 } | 438 } |
424 | 439 |
425 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { | 440 void DownloadManager::OnPathExistenceAvailable( |
426 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 441 int32 download_id, DownloadStateInfo new_state) { |
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 442 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
428 DCHECK(info); | |
429 | 443 |
430 if (info->prompt_user_for_save_location) { | 444 DownloadItem* download = GetActiveDownloadItem(download_id); |
| 445 if (!download) |
| 446 return; |
| 447 |
| 448 VLOG(20) << __FUNCTION__ << "()" |
| 449 << " download = " << download->DebugString(true); |
| 450 |
| 451 download->SetFileCheckResults(new_state); |
| 452 |
| 453 FilePath suggested_path = download->suggested_path(); |
| 454 |
| 455 if (download->save_as()) { |
431 // We must ask the user for the place to put the download. | 456 // We must ask the user for the place to put the download. |
432 if (!select_file_dialog_.get()) | 457 if (!select_file_dialog_.get()) |
433 select_file_dialog_ = SelectFileDialog::Create(this); | 458 select_file_dialog_ = SelectFileDialog::Create(this); |
434 | 459 |
435 TabContents* contents = info->process_handle.GetTabContents(); | 460 DownloadProcessHandle process_handle = download->process_handle(); |
| 461 TabContents* contents = process_handle.GetTabContents(); |
436 SelectFileDialog::FileTypeInfo file_type_info; | 462 SelectFileDialog::FileTypeInfo file_type_info; |
437 FilePath::StringType extension = info->suggested_path.Extension(); | 463 FilePath::StringType extension = suggested_path.Extension(); |
438 if (!extension.empty()) { | 464 if (!extension.empty()) { |
439 extension.erase(extension.begin()); // drop the . | 465 extension.erase(extension.begin()); // drop the . |
440 file_type_info.extensions.resize(1); | 466 file_type_info.extensions.resize(1); |
441 file_type_info.extensions[0].push_back(extension); | 467 file_type_info.extensions[0].push_back(extension); |
442 } | 468 } |
443 file_type_info.include_all_files = true; | 469 file_type_info.include_all_files = true; |
444 gfx::NativeWindow owning_window = | 470 gfx::NativeWindow owning_window = |
445 contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL; | 471 contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL; |
| 472 // |id_ptr| will be deleted in either FileSelected() or |
| 473 // FileSelectionCancelled(). |
| 474 int32* id_ptr = new int32; |
| 475 *id_ptr = download_id; |
446 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, | 476 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, |
447 string16(), | 477 string16(), |
448 info->suggested_path, | 478 suggested_path, |
449 &file_type_info, 0, FILE_PATH_LITERAL(""), | 479 &file_type_info, 0, FILE_PATH_LITERAL(""), |
450 contents, owning_window, info); | 480 contents, owning_window, |
| 481 reinterpret_cast<void*>(id_ptr)); |
451 FOR_EACH_OBSERVER(Observer, observers_, | 482 FOR_EACH_OBSERVER(Observer, observers_, |
452 SelectFileDialogDisplayed(info->download_id)); | 483 SelectFileDialogDisplayed(download_id)); |
453 } else { | 484 } else { |
454 // No prompting for download, just continue with the suggested name. | 485 // No prompting for download, just continue with the suggested name. |
455 info->path = info->suggested_path; | 486 ContinueDownloadWithPath(download, suggested_path); |
456 AttachDownloadItem(info); | |
457 } | 487 } |
458 } | 488 } |
459 | 489 |
460 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { | 490 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { |
461 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 491 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
462 | 492 |
463 DownloadItem* download = new DownloadItem(this, *info, | 493 DownloadItem* download = new DownloadItem(this, *info, |
464 profile_->IsOffTheRecord()); | 494 profile_->IsOffTheRecord()); |
465 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 495 int32 download_id = info->download_id; |
466 DCHECK(!ContainsKey(active_downloads_, info->download_id)); | 496 DCHECK(!ContainsKey(in_progress_, download_id)); |
| 497 DCHECK(!ContainsKey(active_downloads_, download_id)); |
467 downloads_.insert(download); | 498 downloads_.insert(download); |
468 active_downloads_[info->download_id] = download; | 499 active_downloads_[download_id] = download; |
469 } | 500 } |
470 | 501 |
471 void DownloadManager::AttachDownloadItem(DownloadCreateInfo* info) { | 502 void DownloadManager::ContinueDownloadWithPath(DownloadItem* download, |
472 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 503 const FilePath& chosen_file) { |
| 504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 505 DCHECK(download); |
473 | 506 |
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 507 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 | 508 |
479 // NOTE(ahendrickson) Eventually |active_downloads_| will replace | 509 // NOTE(ahendrickson) Eventually |active_downloads_| will replace |
480 // |in_progress_|, but we don't want to change the semantics yet. | 510 // |in_progress_|, but we don't want to change the semantics yet. |
481 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 511 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)); | 512 DCHECK(ContainsKey(downloads_, download)); |
| 513 DCHECK(ContainsKey(active_downloads_, download_id)); |
486 | 514 |
487 download->SetFileCheckResults(info->path, | 515 // Make sure the initial file name is set only once. |
488 info->is_dangerous_file, | 516 DCHECK(download->full_path().empty()); |
489 info->is_dangerous_url, | 517 download->OnPathDetermined(chosen_file); |
490 info->path_uniquifier, | 518 download->UpdateTarget(); |
491 info->prompt_user_for_save_location, | 519 |
492 info->is_extension_install, | 520 VLOG(20) << __FUNCTION__ << "()" |
493 info->original_name); | 521 << " download = " << download->DebugString(true); |
494 in_progress_[info->download_id] = download; | 522 |
| 523 in_progress_[download_id] = download; |
495 UpdateAppIcon(); // Reflect entry into in_progress_. | 524 UpdateAppIcon(); // Reflect entry into in_progress_. |
496 | 525 |
497 // Rename to intermediate name. | 526 // Rename to intermediate name. |
498 FilePath download_path; | 527 FilePath download_path; |
499 if (info->IsDangerous()) { | 528 if (download->IsDangerous()) { |
500 // The download is not safe. We can now rename the file to its | 529 // The download is not safe. We can now rename the file to its |
501 // tentative name using RenameInProgressDownloadFile. | 530 // tentative name using RenameInProgressDownloadFile. |
502 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're | 531 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're |
503 // renaming it to the same name. | 532 // renaming it to the same name. |
504 download_path = info->path; | 533 download_path = download->full_path(); |
505 } else { | 534 } else { |
506 // The download is a safe download. We need to | 535 // The download is a safe download. We need to |
507 // rename it to its intermediate '.crdownload' path. The final | 536 // rename it to its intermediate '.crdownload' path. The final |
508 // name after user confirmation will be set from | 537 // name after user confirmation will be set from |
509 // DownloadItem::OnDownloadCompleting. | 538 // DownloadItem::OnDownloadCompleting. |
510 download_path = download_util::GetCrDownloadPath(info->path); | 539 download_path = |
| 540 download_util::GetCrDownloadPath(download->full_path()); |
511 } | 541 } |
512 | 542 |
513 BrowserThread::PostTask( | 543 BrowserThread::PostTask( |
514 BrowserThread::FILE, FROM_HERE, | 544 BrowserThread::FILE, FROM_HERE, |
515 NewRunnableMethod( | 545 NewRunnableMethod( |
516 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile, | 546 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile, |
517 download->id(), download_path)); | 547 download->id(), download_path)); |
518 | 548 |
519 download->Rename(download_path); | 549 download->Rename(download_path); |
520 | 550 |
521 download_history_->AddEntry(*info, download, | 551 download_history_->AddEntry(download, |
522 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); | 552 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); |
523 } | 553 } |
524 | 554 |
525 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { | 555 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { |
526 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
527 DownloadMap::iterator it = active_downloads_.find(download_id); | 557 DownloadMap::iterator it = active_downloads_.find(download_id); |
528 if (it != active_downloads_.end()) { | 558 if (it != active_downloads_.end()) { |
529 DownloadItem* download = it->second; | 559 DownloadItem* download = it->second; |
530 if (download->IsInProgress()) { | 560 if (download->IsInProgress()) { |
531 download->Update(size); | 561 download->Update(size); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 614 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
585 DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id | 615 DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id |
586 << " is dangerous_hash: " << is_dangerous_hash; | 616 << " is dangerous_hash: " << is_dangerous_hash; |
587 | 617 |
588 // If it's not in active_downloads_, that means it was cancelled or | 618 // If it's not in active_downloads_, that means it was cancelled or |
589 // the download already finished. | 619 // the download already finished. |
590 if (active_downloads_.count(download_id) == 0) | 620 if (active_downloads_.count(download_id) == 0) |
591 return; | 621 return; |
592 | 622 |
593 DVLOG(1) << "CheckDownloadHashDone, url: " | 623 DVLOG(1) << "CheckDownloadHashDone, url: " |
594 << active_downloads_[download_id]->url().spec(); | 624 << active_downloads_[download_id]->GetURL().spec(); |
595 } | 625 } |
596 | 626 |
597 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { | 627 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { |
598 // If we don't have all the data, the download is not ready for | 628 // If we don't have all the data, the download is not ready for |
599 // completion. | 629 // completion. |
600 if (!download->all_data_saved()) | 630 if (!download->all_data_saved()) |
601 return false; | 631 return false; |
602 | 632 |
603 // If the download is dangerous, but not yet validated, it's not ready for | 633 // If the download is dangerous, but not yet validated, it's not ready for |
604 // completion. | 634 // completion. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 int os_error) { | 755 int os_error) { |
726 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 756 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
727 DownloadMap::iterator it = active_downloads_.find(download_id); | 757 DownloadMap::iterator it = active_downloads_.find(download_id); |
728 // A cancel at the right time could remove the download from the | 758 // A cancel at the right time could remove the download from the |
729 // |active_downloads_| map before we get here. | 759 // |active_downloads_| map before we get here. |
730 if (it == active_downloads_.end()) | 760 if (it == active_downloads_.end()) |
731 return; | 761 return; |
732 | 762 |
733 DownloadItem* download = it->second; | 763 DownloadItem* download = it->second; |
734 | 764 |
735 VLOG(20) << "Error " << os_error << " at offset " | 765 VLOG(20) << __FUNCTION__ << "()" << " Error " << os_error |
736 << download->received_bytes() << " for download = " | 766 << " at offset " << download->received_bytes() |
737 << download->DebugString(true); | 767 << " for download = " << download->DebugString(true); |
| 768 |
| 769 download->Interrupted(size, os_error); |
738 | 770 |
739 // TODO(ahendrickson) - Remove this when we add resuming of interrupted | 771 // TODO(ahendrickson) - Remove this when we add resuming of interrupted |
740 // downloads, as we will keep the download item around in that case. | 772 // downloads, as we will keep the download item around in that case. |
741 // | 773 // |
742 // Clean up will happen when the history system create callback runs if we | 774 // Clean up will happen when the history system create callback runs if we |
743 // don't have a valid db_handle yet. | 775 // don't have a valid db_handle yet. |
744 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { | 776 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
745 in_progress_.erase(download_id); | 777 in_progress_.erase(download_id); |
746 active_downloads_.erase(download_id); | 778 active_downloads_.erase(download_id); |
747 UpdateAppIcon(); // Reflect removal from in_progress_. | 779 UpdateAppIcon(); // Reflect removal from in_progress_. |
748 download_history_->UpdateEntry(download); | 780 download_history_->UpdateEntry(download); |
749 } | 781 } |
750 | 782 |
751 download->Interrupted(size, os_error); | |
752 | |
753 BrowserThread::PostTask( | 783 BrowserThread::PostTask( |
754 BrowserThread::FILE, FROM_HERE, | 784 BrowserThread::FILE, FROM_HERE, |
755 NewRunnableMethod( | 785 NewRunnableMethod( |
756 file_manager_, &DownloadFileManager::CancelDownload, download_id)); | 786 file_manager_, &DownloadFileManager::CancelDownload, download_id)); |
757 } | 787 } |
758 | 788 |
759 void DownloadManager::PauseDownload(int32 download_id, bool pause) { | 789 void DownloadManager::PauseDownload(int32 download_id, bool pause) { |
760 DownloadMap::iterator it = in_progress_.find(download_id); | 790 DownloadMap::iterator it = in_progress_.find(download_id); |
761 if (it == in_progress_.end()) | 791 if (it == in_progress_.end()) |
762 return; | 792 return; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 int64 total_bytes = 0; | 989 int64 total_bytes = 0; |
960 for (DownloadMap::iterator i = in_progress_.begin(); | 990 for (DownloadMap::iterator i = in_progress_.begin(); |
961 i != in_progress_.end(); ++i) { | 991 i != in_progress_.end(); ++i) { |
962 total_bytes += i->second->total_bytes(); | 992 total_bytes += i->second->total_bytes(); |
963 } | 993 } |
964 return total_bytes; | 994 return total_bytes; |
965 } | 995 } |
966 | 996 |
967 void DownloadManager::FileSelected(const FilePath& path, | 997 void DownloadManager::FileSelected(const FilePath& path, |
968 int index, void* params) { | 998 int index, void* params) { |
969 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 999 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
970 if (info->prompt_user_for_save_location) | 1000 |
| 1001 int32* id_ptr = reinterpret_cast<int32*>(params); |
| 1002 DCHECK(id_ptr != NULL); |
| 1003 int32 download_id = *id_ptr; |
| 1004 delete id_ptr; |
| 1005 |
| 1006 DownloadItem* download = GetActiveDownloadItem(download_id); |
| 1007 if (!download) |
| 1008 return; |
| 1009 VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\"" |
| 1010 << " download = " << download->DebugString(true); |
| 1011 |
| 1012 if (download->save_as()) |
971 last_download_path_ = path.DirName(); | 1013 last_download_path_ = path.DirName(); |
972 | 1014 |
973 info->path = path; | 1015 // Make sure the initial file name is set only once. |
974 AttachDownloadItem(info); | 1016 ContinueDownloadWithPath(download, path); |
975 } | 1017 } |
976 | 1018 |
977 void DownloadManager::FileSelectionCanceled(void* params) { | 1019 void DownloadManager::FileSelectionCanceled(void* params) { |
978 // The user didn't pick a place to save the file, so need to cancel the | 1020 // 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. | 1021 // download that's already in progress to the temporary location. |
980 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1022 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
981 DownloadCancelledInternal(info->download_id, info->process_handle); | 1023 int32* id_ptr = reinterpret_cast<int32*>(params); |
| 1024 DCHECK(id_ptr != NULL); |
| 1025 int32 download_id = *id_ptr; |
| 1026 delete id_ptr; |
| 1027 |
| 1028 DownloadItem* download = GetActiveDownloadItem(download_id); |
| 1029 if (!download) |
| 1030 return; |
| 1031 |
| 1032 VLOG(20) << __FUNCTION__ << "()" |
| 1033 << " download = " << download->DebugString(true); |
| 1034 |
| 1035 DownloadCancelledInternal(download_id, download->process_handle()); |
| 1036 } |
| 1037 |
| 1038 // TODO(phajdan.jr): This is apparently not being exercised in tests. |
| 1039 bool DownloadManager::IsDangerous(const DownloadItem& download, |
| 1040 const DownloadStateInfo& state) { |
| 1041 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1042 |
| 1043 bool auto_open = ShouldOpenFileBasedOnExtension(state.suggested_path); |
| 1044 download_util::DownloadDangerLevel danger_level = |
| 1045 download_util::GetFileDangerLevel(state.suggested_path.BaseName()); |
| 1046 |
| 1047 if (danger_level == download_util::Dangerous) |
| 1048 return !(auto_open && state.has_user_gesture); |
| 1049 |
| 1050 if (danger_level == download_util::AllowOnUserGesture && |
| 1051 !state.has_user_gesture) |
| 1052 return true; |
| 1053 |
| 1054 if (state.is_extension_install) { |
| 1055 // Extensions that are not from the gallery are considered dangerous. |
| 1056 ExtensionService* service = profile()->GetExtensionService(); |
| 1057 if (!service || !service->IsDownloadFromGallery(download.GetURL(), |
| 1058 download.referrer_url())) |
| 1059 return true; |
| 1060 } |
| 1061 return false; |
982 } | 1062 } |
983 | 1063 |
984 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { | 1064 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { |
985 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1065 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
986 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); | 1066 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); |
987 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); | 1067 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); |
988 download->UpdateObservers(); | 1068 download->UpdateObservers(); |
989 | 1069 |
990 MaybeCompleteDownload(download); | 1070 MaybeCompleteDownload(download); |
991 } | 1071 } |
992 | 1072 |
993 // Operations posted to us from the history service ---------------------------- | 1073 // Operations posted to us from the history service ---------------------------- |
994 | 1074 |
995 // The history service has retrieved all download entries. 'entries' contains | 1075 // The history service has retrieved all download entries. 'entries' contains |
996 // 'DownloadCreateInfo's in sorted order (by ascending start_time). | 1076 // 'DownloadHistoryInfo's in sorted order (by ascending start_time). |
997 void DownloadManager::OnQueryDownloadEntriesComplete( | 1077 void DownloadManager::OnQueryDownloadEntriesComplete( |
998 std::vector<DownloadCreateInfo>* entries) { | 1078 std::vector<DownloadHistoryInfo>* entries) { |
999 for (size_t i = 0; i < entries->size(); ++i) { | 1079 for (size_t i = 0; i < entries->size(); ++i) { |
1000 DownloadItem* download = new DownloadItem(this, entries->at(i)); | 1080 DownloadItem* download = new DownloadItem(this, entries->at(i)); |
1001 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); | 1081 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
1002 downloads_.insert(download); | 1082 downloads_.insert(download); |
1003 history_downloads_[download->db_handle()] = download; | 1083 history_downloads_[download->db_handle()] = download; |
1004 VLOG(20) << __FUNCTION__ << "()" << i << ">" | 1084 VLOG(20) << __FUNCTION__ << "()" << i << ">" |
1005 << " download = " << download->DebugString(true); | 1085 << " download = " << download->DebugString(true); |
1006 } | 1086 } |
1007 NotifyModelChanged(); | 1087 NotifyModelChanged(); |
1008 } | 1088 } |
1009 | 1089 |
1010 // Once the new DownloadItem's creation info has been committed to the history | 1090 // 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 | 1091 // service, we associate the DownloadItem with the db handle, update our |
1012 // 'history_downloads_' map and inform observers. | 1092 // 'history_downloads_' map and inform observers. |
1013 void DownloadManager::OnCreateDownloadEntryComplete( | 1093 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, |
1014 DownloadCreateInfo info, | 1094 int64 db_handle) { |
1015 int64 db_handle) { | |
1016 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1095 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1017 DownloadMap::iterator it = in_progress_.find(info.download_id); | 1096 DownloadItem* download = GetActiveDownloadItem(download_id); |
1018 DCHECK(it != in_progress_.end()); | 1097 if (!download) |
| 1098 return; |
1019 | 1099 |
1020 DownloadItem* download = it->second; | |
1021 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle | 1100 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle |
1022 << " download_id = " << info.download_id | 1101 << " download_id = " << download_id |
1023 << " download = " << download->DebugString(true); | 1102 << " download = " << download->DebugString(true); |
1024 | 1103 |
1025 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 1104 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
1026 // call this function with an invalid |db_handle|. For instance, this can | 1105 // call this function with an invalid |db_handle|. For instance, this can |
1027 // happen when the history database is offline. We cannot have multiple | 1106 // 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 | 1107 // DownloadItems with the same invalid db_handle, so we need to assign a |
1029 // unique |db_handle| here. | 1108 // unique |db_handle| here. |
1030 if (db_handle == DownloadHistory::kUninitializedHandle) | 1109 if (db_handle == DownloadHistory::kUninitializedHandle) |
1031 db_handle = download_history_->GetNextFakeDbHandle(); | 1110 db_handle = download_history_->GetNextFakeDbHandle(); |
1032 | 1111 |
1033 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); | 1112 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
1034 download->set_db_handle(db_handle); | 1113 download->set_db_handle(db_handle); |
1035 | 1114 |
1036 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); | 1115 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); |
1037 history_downloads_[download->db_handle()] = download; | 1116 history_downloads_[download->db_handle()] = download; |
1038 | 1117 |
1039 // Show in the appropriate browser UI. | 1118 // Show in the appropriate browser UI. |
1040 // This includes buttons to save or cancel, for a dangerous download. | 1119 // This includes buttons to save or cancel, for a dangerous download. |
1041 ShowDownloadInBrowser(&info.process_handle, download); | 1120 ShowDownloadInBrowser(download); |
1042 | 1121 |
1043 // Inform interested objects about the new download. | 1122 // Inform interested objects about the new download. |
1044 NotifyModelChanged(); | 1123 NotifyModelChanged(); |
1045 | 1124 |
1046 // If the download is still in progress, try to complete it. | 1125 // If the download is still in progress, try to complete it. |
1047 // | 1126 // |
1048 // Otherwise, download has been cancelled or interrupted before we've | 1127 // Otherwise, download has been cancelled or interrupted before we've |
1049 // received the DB handle. We post one final message to the history | 1128 // 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 | 1129 // 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 | 1130 // completion status, and also inform any observers so that they get |
1052 // more than just the start notification. | 1131 // more than just the start notification. |
1053 if (download->IsInProgress()) { | 1132 if (download->IsInProgress()) { |
1054 MaybeCompleteDownload(download); | 1133 MaybeCompleteDownload(download); |
1055 } else { | 1134 } else { |
1056 DCHECK(download->IsCancelled()) | 1135 DCHECK(download->IsCancelled()) |
1057 << " download = " << download->DebugString(true); | 1136 << " download = " << download->DebugString(true); |
1058 in_progress_.erase(it); | 1137 in_progress_.erase(download_id); |
1059 active_downloads_.erase(info.download_id); | 1138 active_downloads_.erase(download_id); |
1060 download_history_->UpdateEntry(download); | 1139 download_history_->UpdateEntry(download); |
1061 download->UpdateObservers(); | 1140 download->UpdateObservers(); |
1062 } | 1141 } |
1063 } | 1142 } |
1064 | 1143 |
1065 void DownloadManager::ShowDownloadInBrowser( | 1144 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) { |
1066 DownloadProcessHandle* process_handle, DownloadItem* download) { | |
1067 if (!process_handle) | |
1068 return; | |
1069 | 1145 |
1070 // The 'contents' may no longer exist if the user closed the tab before we | 1146 // 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 | 1147 // get this start completion event. If it does, tell the origin TabContents |
1072 // to display its download shelf. | 1148 // to display its download shelf. |
1073 TabContents* contents = process_handle->GetTabContents(); | 1149 DownloadProcessHandle process_handle = download->process_handle(); |
| 1150 TabContents* contents = process_handle.GetTabContents(); |
1074 TabContentsWrapper* wrapper = NULL; | 1151 TabContentsWrapper* wrapper = NULL; |
1075 if (contents) | 1152 if (contents) |
1076 wrapper = TabContentsWrapper::GetCurrentWrapperForContents(contents); | 1153 wrapper = TabContentsWrapper::GetCurrentWrapperForContents(contents); |
1077 | 1154 |
1078 // If the contents no longer exists, we start the download in the last active | 1155 // 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 | 1156 // browser. This is not ideal but better than fully hiding the download from |
1080 // the user. | 1157 // the user. |
1081 if (!wrapper) { | 1158 if (!wrapper) { |
1082 Browser* last_active = BrowserList::GetLastActive(); | 1159 Browser* last_active = BrowserList::GetLastActive(); |
1083 if (last_active) | 1160 if (last_active) |
1084 wrapper = last_active->GetSelectedTabContentsWrapper(); | 1161 wrapper = last_active->GetSelectedTabContentsWrapper(); |
1085 } | 1162 } |
1086 | 1163 |
1087 if (!wrapper) | 1164 if (!wrapper) |
1088 return; | 1165 return; |
1089 | 1166 |
1090 wrapper->download_tab_helper()->OnStartDownload(download); | 1167 wrapper->download_tab_helper()->OnStartDownload(download); |
1091 } | 1168 } |
1092 | 1169 |
1093 // Clears the last download path, used to initialize "save as" dialogs. | 1170 // Clears the last download path, used to initialize "save as" dialogs. |
1094 void DownloadManager::ClearLastDownloadPath() { | 1171 void DownloadManager::ClearLastDownloadPath() { |
1095 last_download_path_ = FilePath(); | 1172 last_download_path_ = FilePath(); |
1096 } | 1173 } |
1097 | 1174 |
1098 void DownloadManager::NotifyModelChanged() { | 1175 void DownloadManager::NotifyModelChanged() { |
1099 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged()); | 1176 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged()); |
1100 } | 1177 } |
1101 | 1178 |
1102 DownloadItem* DownloadManager::GetDownloadItem(int id) { | 1179 DownloadItem* DownloadManager::GetDownloadItem(int download_id) { |
| 1180 // The |history_downloads_| map is indexed by the download's db_handle, |
| 1181 // not its id, so we have to iterate. |
1103 for (DownloadMap::iterator it = history_downloads_.begin(); | 1182 for (DownloadMap::iterator it = history_downloads_.begin(); |
1104 it != history_downloads_.end(); ++it) { | 1183 it != history_downloads_.end(); ++it) { |
1105 DownloadItem* item = it->second; | 1184 DownloadItem* item = it->second; |
1106 if (item->id() == id) | 1185 if (item->id() == download_id) |
1107 return item; | 1186 return item; |
1108 } | 1187 } |
1109 return NULL; | 1188 return NULL; |
1110 } | 1189 } |
1111 | 1190 |
| 1191 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) { |
| 1192 DCHECK(ContainsKey(active_downloads_, download_id)); |
| 1193 DownloadItem* download = active_downloads_[download_id]; |
| 1194 DCHECK(download != NULL); |
| 1195 return download; |
| 1196 } |
| 1197 |
1112 // Confirm that everything in all maps is also in |downloads_|, and that | 1198 // Confirm that everything in all maps is also in |downloads_|, and that |
1113 // everything in |downloads_| is also in some other map. | 1199 // everything in |downloads_| is also in some other map. |
1114 void DownloadManager::AssertContainersConsistent() const { | 1200 void DownloadManager::AssertContainersConsistent() const { |
1115 #if !defined(NDEBUG) | 1201 #if !defined(NDEBUG) |
1116 // Turn everything into sets. | 1202 // Turn everything into sets. |
1117 DownloadSet active_set, history_set; | 1203 DownloadSet active_set, history_set; |
1118 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; | 1204 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; |
1119 DownloadSet* local_sets[] = {&active_set, &history_set}; | 1205 DownloadSet* local_sets[] = {&active_set, &history_set}; |
1120 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); | 1206 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); |
1121 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { | 1207 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); | 1261 observed_download_manager_->RemoveObserver(this); |
1176 } | 1262 } |
1177 | 1263 |
1178 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1264 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
1179 observing_download_manager_->NotifyModelChanged(); | 1265 observing_download_manager_->NotifyModelChanged(); |
1180 } | 1266 } |
1181 | 1267 |
1182 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1268 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
1183 observed_download_manager_ = NULL; | 1269 observed_download_manager_ = NULL; |
1184 } | 1270 } |
OLD | NEW |