Commit message: None
CVE: CVE-2018-6033
CWE: CWE-20
Vulnerability description: Insufficient data validation in Downloads in Google Chrome prior to 64.0.3282.119 allowed a remote attacker to potentially run arbitrary code outside sandbox via a crafted Chrome Extension.

Project: Chrome

ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
  return std::string(chrome::kApplicationClientIDStringForAVScanning);
}

Project: Chrome

void CheckCanDownload(
    const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
    const GURL& url,
    const std::string& request_method,
    CanDownloadCallback can_download_cb) {
  DownloadRequestLimiter* limiter =
      g_browser_process->download_request_limiter();
  if (limiter) {
    DownloadRequestLimiter::Callback cb =
        base::Bind(&CheckDownloadComplete, base::Passed(&can_download_cb));
    limiter->CanDownload(web_contents_getter, url, request_method, cb);
  }
}

Project: Chrome

void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
    uint32_t download_id,
    safe_browsing::DownloadCheckResult result) {
  DownloadItem* item = download_manager_->GetDownload(download_id);
  if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
    return;

  DVLOG(2) << __func__ << "() download = " << item->DebugString(false)
           << " verdict = " << static_cast<int>(result);
  if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
      item->GetDangerType() ==
      content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) {
    content::DownloadDangerType danger_type =
        content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
    switch (result) {
      case safe_browsing::DownloadCheckResult::UNKNOWN:
        if (DownloadItemModel(item).GetDangerLevel() !=
            DownloadFileType::NOT_DANGEROUS) {
          danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
          UMA_HISTOGRAM_ENUMERATION("Download.DangerousFile.Reason",
                                    SB_RETURNS_UNKOWN,
                                    DANGEROUS_FILE_REASON_MAX);
        }
        break;
      case safe_browsing::DownloadCheckResult::SAFE:
        if (DownloadItemModel(item).GetDangerLevel() ==
            DownloadFileType::DANGEROUS) {
          danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
          UMA_HISTOGRAM_ENUMERATION("Download.DangerousFile.Reason",
                                    SB_RETURNS_SAFE, DANGEROUS_FILE_REASON_MAX);
        }
        break;
      case safe_browsing::DownloadCheckResult::DANGEROUS:
        danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
        break;
      case safe_browsing::DownloadCheckResult::UNCOMMON:
        danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
        break;
      case safe_browsing::DownloadCheckResult::DANGEROUS_HOST:
        danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
        break;
      case safe_browsing::DownloadCheckResult::POTENTIALLY_UNWANTED:
        danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
        break;
    }
    DCHECK_NE(danger_type,
              content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT);

    if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
      if (ShouldBlockFile(danger_type)) {
        item->OnContentCheckCompleted(
            content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED);
      } else {
        item->OnContentCheckCompleted(danger_type,
                                      content::DOWNLOAD_INTERRUPT_REASON_NONE);
      }
    }
  }

  SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
      item->GetUserData(&kSafeBrowsingUserDataKey));
  state->CompleteDownload();
}

Project: Chrome

void ChromeDownloadManagerDelegate::CheckDownloadAllowed(
    const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
    const GURL& url,
    const std::string& request_method,
    content::CheckDownloadAllowedCallback check_download_allowed_cb) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  CanDownloadCallback cb = base::BindOnce(
      &ChromeDownloadManagerDelegate::OnCheckDownloadAllowedComplete,
      weak_ptr_factory_.GetWeakPtr(), std::move(check_download_allowed_cb));
#if defined(OS_ANDROID)
  DownloadControllerBase::Get()->AcquireFileAccessPermission(
      web_contents_getter,
      base::Bind(&OnAcquireFileAccessPermissionDone, web_contents_getter, url,
                 request_method, base::Passed(&cb)));
#else
  CheckCanDownload(web_contents_getter, url, request_method, std::move(cb));
#endif
}

Project: Chrome

void CheckDownloadComplete(CanDownloadCallback can_download_cb, bool allow) {
  std::move(can_download_cb).Run(true, allow);
}

Project: Chrome

void ChromeDownloadManagerDelegate::CheckDownloadUrl(
    DownloadItem* download,
    const base::FilePath& suggested_path,
    const CheckDownloadUrlCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

#if defined(FULL_SAFE_BROWSING)
  safe_browsing::DownloadProtectionService* service =
      GetDownloadProtectionService();
  if (service) {
    bool is_content_check_supported =
        service->IsSupportedDownload(*download, suggested_path);
    DVLOG(2) << __func__ << "() Start SB URL check for download = "
             << download->DebugString(false);
    service->CheckDownloadUrl(download,
                              base::Bind(&CheckDownloadUrlDone, callback,
                                         is_content_check_supported));
    return;
  }
#endif
  callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
}

Project: Chrome

void CheckDownloadUrlDone(
    const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback,
    bool is_content_check_supported,
    safe_browsing::DownloadCheckResult result) {
  content::DownloadDangerType danger_type;
  if (result == safe_browsing::DownloadCheckResult::SAFE ||
      result == safe_browsing::DownloadCheckResult::UNKNOWN) {
    if (is_content_check_supported)
      danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
    else
      danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
  } else {
    danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
  }
  callback.Run(danger_type);
}

Project: Chrome

void ChromeDownloadManagerDelegate::CheckForFileExistence(
    DownloadItem* download,
    content::CheckForFileExistenceCallback callback) {
#if defined(OS_CHROMEOS)
  drive::DownloadHandler* drive_download_handler =
      drive::DownloadHandler::GetForProfile(profile_);
  if (drive_download_handler &&
      drive_download_handler->IsDriveDownload(download)) {
    drive_download_handler->CheckForFileExistence(download,
                                                  std::move(callback));
    return;
  }
#endif
  base::PostTaskAndReplyWithResult(
      disk_access_task_runner_.get(), FROM_HERE,
      base::BindOnce(&base::PathExists, download->GetTargetFilePath()),
      std::move(callback));
}

Project: Chrome

void ChromeDownloadManagerDelegate::ChooseSavePath(
    content::WebContents* web_contents,
    const base::FilePath& suggested_path,
    const base::FilePath::StringType& default_extension,
    bool can_save_as_complete,
    const content::SavePackagePathPickedCallback& callback) {
  new SavePackageFilePicker(
      web_contents,
      suggested_path,
      default_extension,
      can_save_as_complete,
      download_prefs_.get(),
      callback);
}

Project: Chrome

ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile)
    : profile_(profile),
      next_download_id_(content::DownloadItem::kInvalidId),
      download_prefs_(new DownloadPrefs(profile)),
      disk_access_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
          {base::MayBlock(), base::TaskPriority::BACKGROUND,
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),

Project: Chrome

void ContinueCheckingForFileExistence(
    content::CheckForFileExistenceCallback callback) {
  std::move(callback).Run(false);
}

Project: Chrome

void ChromeDownloadManagerDelegate::DetermineLocalPath(
    DownloadItem* download,
    const base::FilePath& virtual_path,
    const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(OS_CHROMEOS)
  drive::DownloadHandler* drive_download_handler =
      drive::DownloadHandler::GetForProfile(profile_);
  if (drive_download_handler) {
    drive_download_handler->SubstituteDriveDownloadPath(
        virtual_path, download, callback);
    return;
  }
#endif
  callback.Run(virtual_path);
}

Project: Chrome

ChromeDownloadManagerDelegate::GetDownloadIdReceiverCallback() {
  return base::Bind(&ChromeDownloadManagerDelegate::SetNextId,
                    weak_ptr_factory_.GetWeakPtr());
}

Project: Chrome

    ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(FULL_SAFE_BROWSING)
  safe_browsing::SafeBrowsingService* sb_service =
      g_browser_process->safe_browsing_service();
  if (sb_service && sb_service->download_protection_service() &&
      profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
    return sb_service->download_protection_service();
  }
#endif
  return NULL;
}

Project: Chrome

void ChromeDownloadManagerDelegate::GetFileMimeType(
    const base::FilePath& path,
    const GetFileMimeTypeCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE, {base::MayBlock()}, base::Bind(&GetMimeType, path), callback);
}

Project: Chrome

download::InProgressCache* ChromeDownloadManagerDelegate::GetInProgressCache() {
  DCHECK(download_metadata_cache_ != nullptr);
  return download_metadata_cache_.get();
}

Project: Chrome

std::string GetMimeType(const base::FilePath& path) {
  std::string mime_type;
  net::GetMimeTypeFromFile(path, &mime_type);
  return mime_type;
}

Project: Chrome

void ChromeDownloadManagerDelegate::GetNextId(
    const content::DownloadIdCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (profile_->IsOffTheRecord()) {
    content::BrowserContext::GetDownloadManager(
        profile_->GetOriginalProfile())->GetDelegate()->GetNextId(callback);
    return;
  }
  if (next_download_id_ == content::DownloadItem::kInvalidId) {
    id_callbacks_.push_back(callback);
    return;
  }
  ReturnNextId(callback);
}

Project: Chrome

base::FilePath GetPlatformDownloadPath(Profile* profile,
                                       const DownloadItem* download,
                                       PlatformDownloadPathType path_type) {
#if defined(OS_CHROMEOS)
  drive::DownloadHandler* drive_download_handler =
      drive::DownloadHandler::GetForProfile(profile);
  if (drive_download_handler &&
      drive_download_handler->IsDriveDownload(download))
    return drive_download_handler->GetTargetPath(download);
#endif

  if (path_type == PLATFORM_TARGET_PATH)
    return download->GetTargetFilePath();
  return download->GetFullPath();
}

Project: Chrome

void ChromeDownloadManagerDelegate::GetSaveDir(
    content::BrowserContext* browser_context,
    base::FilePath* website_save_dir,
    base::FilePath* download_save_dir,
    bool* skip_dir_check) {
  *website_save_dir = download_prefs_->SaveFilePath();
  DCHECK(!website_save_dir->empty());
  *download_save_dir = download_prefs_->DownloadPath();
  *skip_dir_check = false;
#if defined(OS_CHROMEOS)
  *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir);
#endif
}

Project: Chrome

bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion(
    DownloadItem* item,
    const base::Closure& internal_complete_callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(FULL_SAFE_BROWSING)
  if (!download_prefs_->safebrowsing_for_trusted_sources_enabled() &&
      download_prefs_->IsFromTrustedSource(*item)) {
    return true;
  }

  SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
      item->GetUserData(&kSafeBrowsingUserDataKey));
  if (!state) {
    DownloadProtectionService* service = GetDownloadProtectionService();
    if (service) {
      DVLOG(2) << __func__ << "() Start SB download check for download = "
               << item->DebugString(false);
      state = new SafeBrowsingState();
      state->set_callback(internal_complete_callback);
      item->SetUserData(&kSafeBrowsingUserDataKey, base::WrapUnique(state));
      service->CheckClientDownload(
          item,
          base::Bind(&ChromeDownloadManagerDelegate::CheckClientDownloadDone,
                     weak_ptr_factory_.GetWeakPtr(),
                     item->GetId()));
      return false;
    }

    content::DownloadDangerType danger_type = item->GetDangerType();
    if (DownloadItemModel(item).GetDangerLevel() !=
            DownloadFileType::NOT_DANGEROUS &&
        (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
         danger_type ==
             content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)) {
      DVLOG(2) << __func__
               << "() SB service disabled. Marking download as DANGEROUS FILE";
      if (ShouldBlockFile(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE)) {
        item->OnContentCheckCompleted(
            content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED);
      } else {
        item->OnContentCheckCompleted(
            content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
            content::DOWNLOAD_INTERRUPT_REASON_NONE);
      }
      UMA_HISTOGRAM_ENUMERATION("Download.DangerousFile.Reason",
                                SB_NOT_AVAILABLE, DANGEROUS_FILE_REASON_MAX);
      content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
                                       internal_complete_callback);
      return false;
    }
  } else if (!state->is_complete()) {
    state->set_callback(internal_complete_callback);
    return false;
  }

#endif
  return true;
}

Project: Chrome

bool ChromeDownloadManagerDelegate::IsOpenInBrowserPreferreredForFile(
    const base::FilePath& path) {
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX)
  if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf"))) {
    return !download_prefs_->ShouldOpenPdfInSystemReader();
  }
#endif

#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_PLUGINS)
  if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".htm")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".html")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".svg")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".xht")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".xsl")) ||
      path.MatchesExtension(FILE_PATH_LITERAL(".xslt"))) {
    return true;
  }
#endif
  return false;
}

Project: Chrome

void ChromeDownloadManagerDelegate::MaybeSendDangerousDownloadOpenedReport(
    DownloadItem* download,
    bool show_download_in_folder) {
#if defined(FULL_SAFE_BROWSING)
  safe_browsing::DownloadProtectionService* service =
      GetDownloadProtectionService();
  if (service) {
    service->MaybeSendDangerousDownloadOpenedReport(download,
                                                    show_download_in_folder);
  }
#endif
}

Project: Chrome

void ChromeDownloadManagerDelegate::NotifyExtensions(
    DownloadItem* download,
    const base::FilePath& virtual_path,
    const NotifyExtensionsCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!download->IsTransient());

#if BUILDFLAG(ENABLE_EXTENSIONS)
  extensions::ExtensionDownloadsEventRouter* router =
      DownloadCoreServiceFactory::GetForBrowserContext(profile_)
          ->GetExtensionEventRouter();
  if (router) {
    base::Closure original_path_callback =
        base::Bind(callback, base::FilePath(),
                   DownloadPathReservationTracker::UNIQUIFY);
    router->OnDeterminingFilename(download, virtual_path.BaseName(),
                                  original_path_callback,
                                  callback);
    return;
  }
#endif
  callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
}

Project: Chrome

void ChromeDownloadManagerDelegate::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
  DCHECK_EQ(extensions::NOTIFICATION_CRX_INSTALLER_DONE, type);

  registrar_.Remove(this, extensions::NOTIFICATION_CRX_INSTALLER_DONE, source);

  scoped_refptr<extensions::CrxInstaller> installer =
      content::Source<extensions::CrxInstaller>(source).ptr();
  content::DownloadOpenDelayedCallback callback =
      crx_installers_[installer.get()];
  crx_installers_.erase(installer.get());
  callback.Run(installer->did_handle_successfully());
#endif
}

Project: Chrome

void ChromeDownloadManagerDelegate::OnCheckDownloadAllowedComplete(
    content::CheckDownloadAllowedCallback check_download_allowed_cb,
    bool storage_permission_granted,
    bool allow) {
  if (!storage_permission_granted) {
  } else if (allow) {
    RecordDownloadSource(DOWNLOAD_INITIATED_BY_NAVIGATION);
  } else {
    RecordDownloadCount(CHROME_DOWNLOAD_COUNT_BLOCKED_BY_THROTTLING);
  }

  std::move(check_download_allowed_cb).Run(allow);
}

Project: Chrome

void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined(
    int32_t download_id,
    const content::DownloadTargetCallback& callback,
    std::unique_ptr<DownloadTargetInfo> target_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DownloadItem* item = download_manager_->GetDownload(download_id);
  if (item) {
    if (!target_info->target_path.empty() &&
        IsOpenInBrowserPreferreredForFile(target_info->target_path) &&
        target_info->is_filetype_handled_safely)
      DownloadItemModel(item).SetShouldPreferOpeningInBrowser(true);

#if defined(OS_LINUX)
    if (item->GetOriginalMimeType() == "application/x-x509-user-cert")
      DownloadItemModel(item).SetShouldPreferOpeningInBrowser(true);
#endif

    DownloadItemModel(item).SetDangerLevel(target_info->danger_level);
  }
  if (ShouldBlockFile(target_info->danger_type)) {
    target_info->result = content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED;
    target_info->danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
  }

  callback.Run(target_info->target_path, target_info->target_disposition,
               target_info->danger_type, target_info->intermediate_path,
               target_info->result);
}

Project: Chrome

void ChromeDownloadManagerDelegate::RequestConfirmation(
    DownloadItem* download,
    const base::FilePath& suggested_path,
    DownloadConfirmationReason reason,
    const DownloadTargetDeterminerDelegate::ConfirmationCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!download->IsTransient());

#if defined(OS_ANDROID)
  switch (reason) {
    case DownloadConfirmationReason::NONE:
      NOTREACHED();
      return;

    case DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE:
      DownloadManagerService::OnDownloadCanceled(
          download, DownloadController::CANCEL_REASON_NO_EXTERNAL_STORAGE);
      callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
      return;

    case DownloadConfirmationReason::NAME_TOO_LONG:
    case DownloadConfirmationReason::TARGET_NO_SPACE:

    case DownloadConfirmationReason::SAVE_AS:
    case DownloadConfirmationReason::PREFERENCE:
      callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
                   suggested_path);
      return;

    case DownloadConfirmationReason::TARGET_CONFLICT:
      if (download->GetWebContents()) {
        android::ChromeDuplicateDownloadInfoBarDelegate::Create(
            InfoBarService::FromWebContents(download->GetWebContents()),
            download, suggested_path, callback);
        return;
      }

    case DownloadConfirmationReason::UNEXPECTED:
      DownloadManagerService::OnDownloadCanceled(
          download,
          DownloadController::CANCEL_REASON_CANNOT_DETERMINE_DOWNLOAD_TARGET);
      callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
      return;
  }
#else   // !OS_ANDROID
  DownloadFilePicker::ShowFilePicker(download, suggested_path, callback);
#endif  // !OS_ANDROID
}

Project: Chrome

void ChromeDownloadManagerDelegate::ReserveVirtualPath(
    content::DownloadItem* download,
    const base::FilePath& virtual_path,
    bool create_directory,
    DownloadPathReservationTracker::FilenameConflictAction conflict_action,
    const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!virtual_path.empty());
#if defined(OS_CHROMEOS)
  if (drive::util::IsUnderDriveMountPoint(virtual_path)) {
    callback.Run(PathValidationResult::SUCCESS, virtual_path);
    return;
  }
#endif
  DownloadPathReservationTracker::GetReservedPath(
      download,
      virtual_path,
      download_prefs_->DownloadPath(),
      create_directory,
      conflict_action,
      callback);
}

Project: Chrome

void ChromeDownloadManagerDelegate::ReturnNextId(
    const content::DownloadIdCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!profile_->IsOffTheRecord());
  DCHECK_NE(content::DownloadItem::kInvalidId, next_download_id_);
  callback.Run(next_download_id_++);
}

Project: Chrome

  SafeBrowsingState() {}

Project: Chrome

void ChromeDownloadManagerDelegate::SanitizeSavePackageResourceName(
    base::FilePath* filename) {
  safe_browsing::FileTypePolicies* file_type_policies =
      safe_browsing::FileTypePolicies::GetInstance();

  if (file_type_policies->GetFileDangerLevel(*filename) ==
      safe_browsing::DownloadFileType::NOT_DANGEROUS)
    return;

  base::FilePath default_filename = base::FilePath::FromUTF8Unsafe(
      l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
  *filename = filename->AddExtension(default_filename.BaseName().value());
}

Project: Chrome

void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
  download_manager_ = dm;

  safe_browsing::SafeBrowsingService* sb_service =
      g_browser_process->safe_browsing_service();
  if (sb_service && !profile_->IsOffTheRecord()) {
    sb_service->AddDownloadManager(dm);
  }
}

Project: Chrome

void ChromeDownloadManagerDelegate::SetNextId(uint32_t next_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!profile_->IsOffTheRecord());

  bool download_db_available = (next_id != content::DownloadItem::kInvalidId);
  RecordDatabaseAvailability(download_db_available);
  if (download_db_available) {
    next_download_id_ = next_id;
  } else {
    next_download_id_ = content::DownloadItem::kInvalidId + 1;
  }

  IdCallbackVector callbacks;
  id_callbacks_.swap(callbacks);
  for (IdCallbackVector::const_iterator it = callbacks.begin();
       it != callbacks.end(); ++it) {
    ReturnNextId(*it);
  }
}

Project: Chrome

bool ChromeDownloadManagerDelegate::ShouldBlockFile(
    content::DownloadDangerType danger_type) const {
  DownloadPrefs::DownloadRestriction download_restriction =
      download_prefs_->download_restriction();

  switch (download_restriction) {
    case (DownloadPrefs::DownloadRestriction::NONE):
      return false;

    case (DownloadPrefs::DownloadRestriction::POTENTIALLY_DANGEROUS_FILES):
      return danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;

    case (DownloadPrefs::DownloadRestriction::DANGEROUS_FILES): {
      return (danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
              danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
              danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
    }

    case (DownloadPrefs::DownloadRestriction::ALL_FILES):
      return true;

    default:
      LOG(ERROR) << "Invalid download restruction value: "
                 << static_cast<int>(download_restriction);
  }
  return false;
}

Project: Chrome

bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(
    DownloadItem* item,
    const base::Closure& user_complete_callback) {
  return IsDownloadReadyForCompletion(item, base::Bind(
      &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal,
      weak_ptr_factory_.GetWeakPtr(), item->GetId(), user_complete_callback));
}

Project: Chrome

void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal(
    uint32_t download_id,
    const base::Closure& user_complete_callback) {
  DownloadItem* item = download_manager_->GetDownload(download_id);
  if (!item)
    return;
  if (ShouldCompleteDownload(item, user_complete_callback))
    user_complete_callback.Run();
}

Project: Chrome

bool ChromeDownloadManagerDelegate::ShouldOpenDownload(
    DownloadItem* item, const content::DownloadOpenDelayedCallback& callback) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
  if (download_crx_util::IsExtensionDownload(*item) &&
      !extensions::WebstoreInstaller::GetAssociatedApproval(*item)) {
    scoped_refptr<extensions::CrxInstaller> crx_installer =
        download_crx_util::OpenChromeExtension(profile_, *item);

    registrar_.Add(
        this,
        extensions::NOTIFICATION_CRX_INSTALLER_DONE,
        content::Source<extensions::CrxInstaller>(crx_installer.get()));

    crx_installers_[crx_installer.get()] = callback;
    item->UpdateObservers();
    return false;
  }
#endif

  return true;
}

Project: Chrome

bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension(
    const base::FilePath& path) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (path.Extension().empty())
    return false;
#if BUILDFLAG(ENABLE_EXTENSIONS)
  if (path.MatchesExtension(extensions::kExtensionFileExtension))
    return false;
#endif
  return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
}

Project: Chrome

 void ChromeDownloadManagerDelegate::ShowDownloadInShell(
     DownloadItem* download) {
   if (!download->CanShowInFolder())
    return;

  MaybeSendDangerousDownloadOpenedReport(download,
                                         true /* show_download_in_folder */);

  base::FilePath platform_path(
      GetPlatformDownloadPath(profile_, download, PLATFORM_CURRENT_PATH));
  DCHECK(!platform_path.empty());
  platform_util::ShowItemInFolder(profile_, platform_path);
}

Project: Chrome

void ChromeDownloadManagerDelegate::Shutdown() {
  download_prefs_.reset();
  weak_ptr_factory_.InvalidateWeakPtrs();
  download_manager_ = NULL;
}

Project: Chrome

ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
  DCHECK(!download_manager_);
}

Project: Chrome

bool DownloadItemImpl::AllDataSaved() const {
  return destination_info_.all_data_saved;
}

Project: Chrome

void DownloadItemImpl::AutoResumeIfValid() {
  DVLOG(20) << __func__ << "() " << DebugString(true);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ResumeMode mode = GetResumeMode();

  if (mode != RESUME_MODE_IMMEDIATE_RESTART &&
      mode != RESUME_MODE_IMMEDIATE_CONTINUE) {
    return;
  }

  auto_resume_count_++;

  ResumeInterruptedDownload(ResumptionRequestSource::AUTOMATIC);
}

Project: Chrome

bool DownloadItemImpl::CanResume() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  switch (state_) {
    case INITIAL_INTERNAL:
    case COMPLETING_INTERNAL:
    case COMPLETE_INTERNAL:
    case CANCELLED_INTERNAL:
    case RESUMING_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
      return false;

    case TARGET_PENDING_INTERNAL:
    case TARGET_RESOLVED_INTERNAL:
    case IN_PROGRESS_INTERNAL:
      return IsPaused();

    case INTERRUPTED_INTERNAL: {
      ResumeMode resume_mode = GetResumeMode();
      return resume_mode == RESUME_MODE_USER_RESTART ||
             resume_mode == RESUME_MODE_USER_CONTINUE;
    }

    case MAX_DOWNLOAD_INTERNAL_STATE:
      NOTREACHED();
  }
  return false;
}

Project: Chrome

bool DownloadItemImpl::CanShowInFolder() {
  return CanOpenDownload() && !GetFullPath().empty();
}

Project: Chrome

void DownloadItemImpl::Cancel(bool user_cancel) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DVLOG(20) << __func__ << "() download = " << DebugString(true);
  InterruptAndDiscardPartialState(
      user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
                  : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::Completed() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  DVLOG(20) << __func__ << "() " << DebugString(false);

  DCHECK(AllDataSaved());
  destination_info_.end_time = base::Time::Now();
  TransitionTo(COMPLETE_INTERNAL);

  bool is_parallelizable = job_ && job_->IsParallelizable();
  RecordDownloadCompleted(start_tick_, GetReceivedBytes(), is_parallelizable);
  if (!GetBrowserContext()->IsOffTheRecord()) {
    RecordDownloadCount(COMPLETED_COUNT_NORMAL_PROFILE);
  }
  if (is_parallelizable) {
    RecordParallelizableDownloadCount(COMPLETED_COUNT,
                                      IsParallelDownloadEnabled());
    int64_t content_length = -1;
    if (response_headers_->response_code() != net::HTTP_PARTIAL_CONTENT) {
      content_length = response_headers_->GetContentLength();
    } else {
      int64_t first_byte = -1;
      int64_t last_byte = -1;
      response_headers_->GetContentRangeFor206(&first_byte, &last_byte,
                                               &content_length);
    }
    if (content_length > 0)
      RecordParallelizableContentLength(content_length);
  }

  if (auto_opened_) {
  } else if (GetOpenWhenComplete() ||
             ShouldOpenFileBasedOnExtension() ||
             IsTemporary()) {
    if (!IsTemporary())
      OpenDownload();

    auto_opened_ = true;
  }
  UpdateObservers();
}

Project: Chrome

int64_t DownloadItemImpl::CurrentSpeed() const {
  if (IsPaused())
    return 0;
  return bytes_per_sec_;
}

Project: Chrome

const char* DownloadItemImpl::DebugDownloadStateString(
    DownloadInternalState state) {
  switch (state) {
    case INITIAL_INTERNAL:
      return "INITIAL";
    case TARGET_PENDING_INTERNAL:
      return "TARGET_PENDING";
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
      return "INTERRUPTED_TARGET_PENDING";
    case TARGET_RESOLVED_INTERNAL:
      return "TARGET_RESOLVED";
    case IN_PROGRESS_INTERNAL:
      return "IN_PROGRESS";
    case COMPLETING_INTERNAL:
      return "COMPLETING";
    case COMPLETE_INTERNAL:
      return "COMPLETE";
    case CANCELLED_INTERNAL:
      return "CANCELLED";
    case INTERRUPTED_INTERNAL:
      return "INTERRUPTED";
    case RESUMING_INTERNAL:
      return "RESUMING";
    case MAX_DOWNLOAD_INTERNAL_STATE:
      break;
  }
  NOTREACHED() << "Unknown download state " << state;
  return "unknown";
}

Project: Chrome

const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) {
  switch (mode) {
    case RESUME_MODE_INVALID:
      return "INVALID";
    case RESUME_MODE_IMMEDIATE_CONTINUE:
      return "IMMEDIATE_CONTINUE";
    case RESUME_MODE_IMMEDIATE_RESTART:
      return "IMMEDIATE_RESTART";
    case RESUME_MODE_USER_CONTINUE:
      return "USER_CONTINUE";
    case RESUME_MODE_USER_RESTART:
      return "USER_RESTART";
  }
  NOTREACHED() << "Unknown resume mode " << mode;
  return "unknown";
}

Project: Chrome

std::string DownloadItemImpl::DebugString(bool verbose) const {
  std::string description =
      base::StringPrintf("{ id = %d"
                         " state = %s",
                         download_id_,
                         DebugDownloadStateString(state_));

  std::string url_list("<none>");
  if (!request_info_.url_chain.empty()) {
    std::vector<GURL>::const_iterator iter = request_info_.url_chain.begin();
    std::vector<GURL>::const_iterator last = request_info_.url_chain.end();
    url_list = (*iter).is_valid() ? (*iter).spec() : "<invalid>";
    ++iter;
    for ( ; verbose && (iter != last); ++iter) {
      url_list += " ->\n\t";
      const GURL& next_url = *iter;
      url_list += next_url.is_valid() ? next_url.spec() : "<invalid>";
    }
  }

  if (verbose) {
    description += base::StringPrintf(
        " total = %" PRId64 " received = %" PRId64
        " reason = %s"
        " paused = %c"
        " resume_mode = %s"
        " auto_resume_count = %d"
        " danger = %d"
        " all_data_saved = %c"
        " last_modified = '%s'"
        " etag = '%s'"
        " has_download_file = %s"
        " url_chain = \n\t\"%s\"\n\t"
        " current_path = \"%" PRFilePath
        "\"\n\t"
        " target_path = \"%" PRFilePath
        "\""
        " referrer = \"%s\""
        " site_url = \"%s\"",
        GetTotalBytes(), GetReceivedBytes(),
        DownloadInterruptReasonToString(last_reason_).c_str(),
        IsPaused() ? 'T' : 'F', DebugResumeModeString(GetResumeMode()),
        auto_resume_count_, GetDangerType(), AllDataSaved() ? 'T' : 'F',
        GetLastModifiedTime().c_str(), GetETag().c_str(),
        download_file_.get() ? "true" : "false", url_list.c_str(),
        GetFullPath().value().c_str(), GetTargetFilePath().value().c_str(),
        GetReferrerUrl().spec().c_str(), GetSiteUrl().spec().c_str());
  } else {
    description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
  }

  description += " }";

  return description;
}

Project: Chrome

void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto_opened_ = auto_opened;
  Completed();
}

Project: Chrome

bool DeleteDownloadedFile(const base::FilePath& path) {
  DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());

  if (base::DirectoryExists(path))
    return true;
  return base::DeleteFile(path, false);
}

Project: Chrome

void DownloadItemImpl::DeleteFile(const base::Callback<void(bool)>& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (GetState() != DownloadItem::COMPLETE) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::BindOnce(&DeleteDownloadedFileDone,
                       base::WeakPtr<DownloadItemImpl>(), callback, false));
    return;
  }
  if (GetFullPath().empty() || file_externally_removed_) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::BindOnce(&DeleteDownloadedFileDone,
                       base::WeakPtr<DownloadItemImpl>(), callback, true));
    return;
  }
  base::PostTaskAndReplyWithResult(
      GetDownloadTaskRunner().get(), FROM_HERE,
      base::Bind(&DeleteDownloadedFile, GetFullPath()),
      base::Bind(&DeleteDownloadedFileDone, weak_ptr_factory_.GetWeakPtr(),
                 callback));
}

Project: Chrome

void DownloadItemImpl::DestinationCompleted(
    int64_t total_bytes,
    std::unique_ptr<crypto::SecureHash> secure_hash) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
  DVLOG(20) << __func__ << "() download=" << DebugString(true);

  OnAllDataSaved(total_bytes, std::move(secure_hash));
  MaybeCompleteDownload();
}

Project: Chrome

void DownloadItemImpl::DestinationError(
    DownloadInterruptReason reason,
    int64_t bytes_so_far,
    std::unique_ptr<crypto::SecureHash> secure_hash) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
  DVLOG(20) << __func__
            << "() reason:" << DownloadInterruptReasonToString(reason)
            << " this:" << DebugString(true);

  InterruptWithPartialState(bytes_so_far, std::move(secure_hash), reason);
  UpdateObservers();
}

Project: Chrome

DownloadItemImpl::DestinationInfo::DestinationInfo(
    const base::FilePath& target_path,
    const base::FilePath& current_path,
    int64_t received_bytes,
    bool all_data_saved,
    const std::string& hash,
    base::Time end_time)
    : target_path(target_path),
      current_path(current_path),
      received_bytes(received_bytes),
      all_data_saved(all_data_saved),
      hash(hash),
      end_time(end_time) {}

Project: Chrome

DownloadItemImpl::DestinationObserverAsWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

Project: Chrome

void DownloadItemImpl::DestinationUpdate(
    int64_t bytes_so_far,
    int64_t bytes_per_sec,
    const std::vector<DownloadItem::ReceivedSlice>& received_slices) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);

  DCHECK_EQ(deferred_interrupt_reason_, DOWNLOAD_INTERRUPT_REASON_NONE);

  DVLOG(20) << __func__ << "() so_far=" << bytes_so_far
            << " per_sec=" << bytes_per_sec
            << " download=" << DebugString(true);

  UpdateProgress(bytes_so_far, bytes_per_sec);
  received_slices_ = received_slices;
  TRACE_EVENT_INSTANT1("download", "DownloadItemUpdated",
                       TRACE_EVENT_SCOPE_THREAD, "bytes_so_far",
                       GetReceivedBytes());

  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::DetermineDownloadTarget() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DVLOG(20) << __func__ << "() " << DebugString(true);

  RecordDownloadCount(DETERMINE_DOWNLOAD_TARGET_COUNT);
  delegate_->DetermineDownloadTarget(
      this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined,
                       weak_ptr_factory_.GetWeakPtr()));
}

Project: Chrome

void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {
  DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
  download_file->Cancel();
}

Project: Chrome

base::FilePath DownloadFileDetach(std::unique_ptr<DownloadFile> download_file) {
  DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
  base::FilePath full_path = download_file->FullPath();
  download_file->Detach();
  return full_path;
}

Project: Chrome

  DownloadItemActivatedData(DownloadItem::DownloadType download_type,
                            uint32_t download_id,
                            std::string original_url,
                            std::string final_url,
                            std::string file_name,
                            DownloadDangerType danger_type,
                            int64_t start_offset,
                            bool has_user_gesture)
      : download_type_(download_type),
        download_id_(download_id),
        original_url_(original_url),
        final_url_(final_url),
        file_name_(file_name),
        danger_type_(danger_type),
        start_offset_(start_offset),
        has_user_gesture_(has_user_gesture) {}

Project: Chrome

DownloadItemImpl::DownloadItemImpl(
    DownloadItemImplDelegate* delegate,
    const std::string& guid,
    uint32_t download_id,
    const base::FilePath& current_path,
    const base::FilePath& target_path,
    const std::vector<GURL>& url_chain,
    const GURL& referrer_url,
    const GURL& site_url,
    const GURL& tab_url,
    const GURL& tab_refererr_url,
    const std::string& mime_type,
    const std::string& original_mime_type,
    base::Time start_time,
    base::Time end_time,
    const std::string& etag,
    const std::string& last_modified,
    int64_t received_bytes,
    int64_t total_bytes,
    const std::string& hash,
    DownloadItem::DownloadState state,
    DownloadDangerType danger_type,
    DownloadInterruptReason interrupt_reason,
    bool opened,
    base::Time last_access_time,
    bool transient,
    const std::vector<DownloadItem::ReceivedSlice>& received_slices)
    : request_info_(url_chain,
                    referrer_url,
                    site_url,
                    tab_url,
                    tab_refererr_url,
                    std::string(),
                    base::FilePath(),
                    ui::PAGE_TRANSITION_LINK,
                    false,
                    std::string(),
                    start_time),
      guid_(guid),
      download_id_(download_id),
      mime_type_(mime_type),
      original_mime_type_(original_mime_type),
      total_bytes_(total_bytes),
      last_reason_(interrupt_reason),
      start_tick_(base::TimeTicks()),
      state_(ExternalToInternalState(state)),
      danger_type_(danger_type),
      delegate_(delegate),
      opened_(opened),
      last_access_time_(last_access_time),
      transient_(transient),
      destination_info_(target_path,
                        current_path,
                        received_bytes,
                        state == COMPLETE,
                        hash,
                        end_time),
      last_modified_time_(last_modified),
      etag_(etag),
      received_slices_(received_slices),
      is_updating_observers_(false),
      weak_ptr_factory_(this) {
  delegate_->Attach();
  DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
         state_ == CANCELLED_INTERNAL);
  DCHECK(base::IsValidGUID(guid_));
  Init(false /* not actively downloading */, TYPE_HISTORY_IMPORT);
}

Project: Chrome

DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
                                   uint32_t download_id,
                                   const DownloadCreateInfo& info)
    : request_info_(info.url_chain,
                    info.referrer_url,
                    info.site_url,
                    info.tab_url,
                    info.tab_referrer_url,
                    base::UTF16ToUTF8(info.save_info->suggested_name),
                    info.save_info->file_path,
                    info.transition_type ? info.transition_type.value()
                                         : ui::PAGE_TRANSITION_LINK,
                    info.has_user_gesture,
                    info.remote_address,
                    info.start_time),
      guid_(info.guid.empty() ? base::GenerateGUID() : info.guid),
      download_id_(download_id),
      response_headers_(info.response_headers),
      content_disposition_(info.content_disposition),
      mime_type_(info.mime_type),
      original_mime_type_(info.original_mime_type),
      total_bytes_(info.total_bytes),
      last_reason_(info.result),
      start_tick_(base::TimeTicks::Now()),
      state_(INITIAL_INTERNAL),
      delegate_(delegate),
      is_temporary_(!info.transient && !info.save_info->file_path.empty()),
      transient_(info.transient),
      destination_info_(info.save_info->prompt_for_save_location
                            ? TARGET_DISPOSITION_PROMPT
                            : TARGET_DISPOSITION_OVERWRITE),
      last_modified_time_(info.last_modified),
      etag_(info.etag),
      is_updating_observers_(false),
      fetch_error_body_(info.fetch_error_body),
      weak_ptr_factory_(this) {
  delegate_->Attach();
  Init(true /* actively downloading */, TYPE_ACTIVE_DOWNLOAD);

  TRACE_EVENT_INSTANT0("download", "DownloadStarted", TRACE_EVENT_SCOPE_THREAD);
}

Project: Chrome

DownloadItemImpl::DownloadItemImpl(
    DownloadItemImplDelegate* delegate,
    uint32_t download_id,
    const base::FilePath& path,
    const GURL& url,
    const std::string& mime_type,
    std::unique_ptr<DownloadRequestHandleInterface> request_handle)
    : request_info_(url),
      guid_(base::GenerateGUID()),
      download_id_(download_id),
      mime_type_(mime_type),
      original_mime_type_(mime_type),
      start_tick_(base::TimeTicks::Now()),
      state_(IN_PROGRESS_INTERNAL),
      delegate_(delegate),
      destination_info_(path, path, 0, false, std::string(), base::Time()),
      is_updating_observers_(false),
      weak_ptr_factory_(this) {
  job_ = DownloadJobFactory::CreateJob(this, std::move(request_handle),
                                       DownloadCreateInfo(), true);
  delegate_->Attach();
  Init(true /* actively downloading */, TYPE_SAVE_PAGE_AS);
}

Project: Chrome

DownloadItemImpl::ExternalToInternalState(
    DownloadState external_state) {
  switch (external_state) {
    case IN_PROGRESS:
      return IN_PROGRESS_INTERNAL;
    case COMPLETE:
      return COMPLETE_INTERNAL;
    case CANCELLED:
      return CANCELLED_INTERNAL;
    case INTERRUPTED:
      return INTERRUPTED_INTERNAL;
    default:
      NOTREACHED();
  }
  return MAX_DOWNLOAD_INTERNAL_STATE;
}

Project: Chrome

BrowserContext* DownloadItemImpl::GetBrowserContext() const {
  return delegate_->GetBrowserContext();
}

Project: Chrome

DownloadDangerType DownloadItemImpl::GetDangerType() const {
  return danger_type_;
}

Project: Chrome

std::string GetDownloadDangerNames(DownloadDangerType type) {
  switch (type) {
    case DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
      return "NOT_DANGEROUS";
    case DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
      return "DANGEROUS_FILE";
    case DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
      return "DANGEROUS_URL";
    case DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
      return "DANGEROUS_CONTENT";
    case DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
      return "MAYBE_DANGEROUS_CONTENT";
    case DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
      return "UNCOMMON_CONTENT";
    case DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
      return "USER_VALIDATED";
    case DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
      return "DANGEROUS_HOST";
    case DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
      return "POTENTIALLY_UNWANTED";
    default:
      NOTREACHED();
      return "UNKNOWN_DANGER_TYPE";
  }
}

Project: Chrome

std::string GetDownloadTypeNames(DownloadItem::DownloadType type) {
  switch (type) {
    case DownloadItem::TYPE_ACTIVE_DOWNLOAD:
      return "NEW_DOWNLOAD";
    case DownloadItem::TYPE_HISTORY_IMPORT:
      return "HISTORY_IMPORT";
    case DownloadItem::TYPE_SAVE_PAGE_AS:
      return "SAVE_PAGE_AS";
    default:
      NOTREACHED();
      return "INVALID_TYPE";
  }
}

Project: Chrome

base::Time DownloadItemImpl::GetEndTime() const {
  return destination_info_.end_time;
}

Project: Chrome

base::FilePath DownloadItemImpl::GetFileNameToReportUser() const {
  if (!display_name_.empty())
    return display_name_;
  return GetTargetFilePath().BaseName();
}

Project: Chrome

const base::FilePath& DownloadItemImpl::GetFullPath() const {
  return destination_info_.current_path;
}

Project: Chrome

const std::string& DownloadItemImpl::GetGuid() const {
  return guid_;
}

Project: Chrome

const std::string& DownloadItemImpl::GetHash() const {
  return destination_info_.hash;
}

Project: Chrome

uint32_t DownloadItemImpl::GetId() const {
  return download_id_;
}

Project: Chrome

base::Time DownloadItemImpl::GetLastAccessTime() const {
  return last_access_time_;
}

Project: Chrome

DownloadInterruptReason DownloadItemImpl::GetLastReason() const {
  return last_reason_;
}

Project: Chrome

const GURL& DownloadItemImpl::GetOriginalUrl() const {
  return request_info_.url_chain.empty() ? GURL::EmptyGURL()
                                         : request_info_.url_chain.front();
}

Project: Chrome

int64_t DownloadItemImpl::GetReceivedBytes() const {
  return destination_info_.received_bytes;
}

Project: Chrome

DownloadItemImpl::GetReceivedSlices() const {
  return received_slices_;
}

Project: Chrome

const GURL& DownloadItemImpl::GetReferrerUrl() const {
  return request_info_.referrer_url;
}

Project: Chrome

std::string DownloadItemImpl::GetRemoteAddress() const {
  return request_info_.remote_address;
}

Project: Chrome

DownloadItemImpl::GetResponseHeaders() const {
  return response_headers_;
}

Project: Chrome

DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!GetURL().SchemeIsHTTPOrHTTPS())
    return RESUME_MODE_INVALID;

  bool restart_required =
      (GetFullPath().empty() || (etag_.empty() && last_modified_time_.empty()));

  bool user_action_required =
      (auto_resume_count_ >= kMaxAutoResumeAttempts || IsPaused());

  switch (last_reason_) {
    case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
    case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH:
      break;

    case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:

    case DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH:

    case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:

      restart_required = true;
      break;

    case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
    case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
    case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE:
    case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
    case DOWNLOAD_INTERRUPT_REASON_CRASH:
      user_action_required = true;
      break;

    case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
      user_action_required = true;
      break;

    case DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
    case DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
    case DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
    case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
      user_action_required = true;
      restart_required = true;
      break;

    case DOWNLOAD_INTERRUPT_REASON_NONE:
    case DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
    case DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
    case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
    case DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
    case DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
    case DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN:
    case DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE:
      return RESUME_MODE_INVALID;
  }

  if (user_action_required && restart_required)
    return RESUME_MODE_USER_RESTART;

  if (restart_required)
    return RESUME_MODE_IMMEDIATE_RESTART;

  if (user_action_required)
    return RESUME_MODE_USER_CONTINUE;

  return RESUME_MODE_IMMEDIATE_CONTINUE;
}

Project: Chrome

const GURL& DownloadItemImpl::GetSiteUrl() const {
  return request_info_.site_url;
}

Project: Chrome

base::Time DownloadItemImpl::GetStartTime() const {
  return request_info_.start_time;
}

Project: Chrome

DownloadItem::DownloadState DownloadItemImpl::GetState() const {
  return InternalToExternalState(state_);
}

Project: Chrome

std::string DownloadItemImpl::GetSuggestedFilename() const {
  return request_info_.suggested_filename;
}

Project: Chrome

const GURL& DownloadItemImpl::GetTabReferrerUrl() const {
  return request_info_.tab_referrer_url;
}

Project: Chrome

const GURL& DownloadItemImpl::GetTabUrl() const {
  return request_info_.tab_url;
}

Project: Chrome

const base::FilePath& DownloadItemImpl::GetTargetFilePath() const {
  return destination_info_.target_path;
}

Project: Chrome

int64_t DownloadItemImpl::GetTotalBytes() const {
  return total_bytes_;
}

Project: Chrome

ui::PageTransition DownloadItemImpl::GetTransitionType() const {
  return request_info_.transition_type;
}

Project: Chrome

const GURL& DownloadItemImpl::GetURL() const {
  return request_info_.url_chain.empty() ? GURL::EmptyGURL()
                                         : request_info_.url_chain.back();
}

Project: Chrome

const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const {
  return request_info_.url_chain;
}

Project: Chrome

WebContents* DownloadItemImpl::GetWebContents() const {
  if (job_)
    return job_->GetWebContents();
  return nullptr;
}

Project: Chrome

bool DownloadItemImpl::HasUserGesture() const {
  return request_info_.has_user_gesture;
}

Project: Chrome

void DownloadItemImpl::Init(bool active,
                            DownloadItem::DownloadType download_type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::string file_name;
  if (download_type == TYPE_HISTORY_IMPORT) {
    file_name = GetTargetFilePath().AsUTF8Unsafe();
  } else {
    file_name = GetForcedFilePath().AsUTF8Unsafe();
    if (file_name.empty())
      file_name = GetSuggestedFilename();
    if (file_name.empty())
      file_name = GetURL().ExtractFileName();
  }

  auto active_data = std::make_unique<DownloadItemActivatedData>(
      download_type, GetId(), GetOriginalUrl().spec(), GetURL().spec(),
      file_name, GetDangerType(), GetReceivedBytes(), HasUserGesture());

  if (active) {
    TRACE_EVENT_ASYNC_BEGIN1("download", "DownloadItemActive", download_id_,
                             "download_item", std::move(active_data));
  } else {
    TRACE_EVENT_INSTANT1("download", "DownloadItemActive",
                         TRACE_EVENT_SCOPE_THREAD, "download_item",
                         std::move(active_data));
  }

  DVLOG(20) << __func__ << "() " << DebugString(true);
}

Project: Chrome

DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
    DownloadInternalState internal_state) {
  switch (internal_state) {
    case INITIAL_INTERNAL:
    case TARGET_PENDING_INTERNAL:
    case TARGET_RESOLVED_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
    case IN_PROGRESS_INTERNAL:
      return IN_PROGRESS;
    case COMPLETING_INTERNAL:
      return IN_PROGRESS;
    case COMPLETE_INTERNAL:
      return COMPLETE;
    case CANCELLED_INTERNAL:
      return CANCELLED;
    case INTERRUPTED_INTERNAL:
      return INTERRUPTED;
    case RESUMING_INTERNAL:
      return IN_PROGRESS;
    case MAX_DOWNLOAD_INTERNAL_STATE:
      break;
  }
  NOTREACHED();
  return MAX_DOWNLOAD_STATE;
}

Project: Chrome

void DownloadItemImpl::InterruptAndDiscardPartialState(
    DownloadInterruptReason reason) {
  InterruptWithPartialState(0, std::unique_ptr<crypto::SecureHash>(), reason);
}

Project: Chrome

void DownloadItemImpl::InterruptWithPartialState(
    int64_t bytes_so_far,
    std::unique_ptr<crypto::SecureHash> hash_state,
    DownloadInterruptReason reason) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
  DVLOG(20) << __func__
            << "() reason:" << DownloadInterruptReasonToString(reason)
            << " bytes_so_far:" << bytes_so_far
            << " hash_state:" << (hash_state ? "Valid" : "Invalid")
            << " this=" << DebugString(true);

  switch (state_) {
    case CANCELLED_INTERNAL:
    case COMPLETING_INTERNAL:
    case COMPLETE_INTERNAL:
      return;

    case INITIAL_INTERNAL:
    case MAX_DOWNLOAD_INTERNAL_STATE:
      NOTREACHED();
      return;

    case TARGET_PENDING_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
      if (!IsCancellation(reason)) {
        UpdateProgress(bytes_so_far, 0);
        SetHashState(std::move(hash_state));
        deferred_interrupt_reason_ = reason;
        TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
        return;
      }

    case IN_PROGRESS_INTERNAL:
    case TARGET_RESOLVED_INTERNAL:
      last_reason_ = reason;

      if (download_file_) {
        ResumeMode resume_mode = GetResumeMode();
        ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE &&
                            resume_mode != RESUME_MODE_USER_CONTINUE);
      }
      break;

    case RESUMING_INTERNAL:
    case INTERRUPTED_INTERNAL:
      DCHECK(!download_file_);
      if (!IsCancellation(reason))
        return;

      last_reason_ = reason;
      if (!GetFullPath().empty()) {
        GetDownloadTaskRunner()->PostTask(
            FROM_HERE, base::BindOnce(base::IgnoreResult(&DeleteDownloadedFile),
                                      GetFullPath()));
        destination_info_.current_path.clear();
      }
      break;
  }

  destination_info_.all_data_saved = false;

  if (GetFullPath().empty()) {
    hash_state_.reset();
    destination_info_.hash.clear();
    destination_info_.received_bytes = 0;
    received_slices_.clear();
  } else {
    UpdateProgress(bytes_so_far, 0);
    SetHashState(std::move(hash_state));
  }

  if (job_)
    job_->Cancel(false);

  if (IsCancellation(reason)) {
    if (IsDangerous()) {
      RecordDangerousDownloadDiscard(
          reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
              ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
              : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
          GetDangerType(), GetTargetFilePath());
    }

    RecordDownloadCount(CANCELLED_COUNT);
    if (job_ && job_->IsParallelizable()) {
      RecordParallelizableDownloadCount(CANCELLED_COUNT,
                                        IsParallelDownloadEnabled());
    }
    DCHECK_EQ(last_reason_, reason);
    TransitionTo(CANCELLED_INTERNAL);
    return;
  }

  RecordDownloadInterrupted(reason, GetReceivedBytes(), total_bytes_,
                            job_ && job_->IsParallelizable(),
                            IsParallelDownloadEnabled());
  if (reason == DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH)
    received_bytes_at_length_mismatch_ = GetReceivedBytes();

  if (!GetWebContents())
    RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);

  DCHECK_EQ(last_reason_, reason);
  TransitionTo(INTERRUPTED_INTERNAL);
  AutoResumeIfValid();
}

Project: Chrome

bool IsCancellation(DownloadInterruptReason reason) {
  return reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN ||
         reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
}

Project: Chrome

bool DownloadItemImpl::IsDangerous() const {
  return (danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
          danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
          danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
          danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
          danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
          danger_type_ == DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED);
}

Project: Chrome

bool DownloadItemImpl::IsDone() const {
  switch (state_) {
    case INITIAL_INTERNAL:
    case COMPLETING_INTERNAL:
    case RESUMING_INTERNAL:
    case TARGET_PENDING_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
    case TARGET_RESOLVED_INTERNAL:
    case IN_PROGRESS_INTERNAL:
      return false;

    case COMPLETE_INTERNAL:
    case CANCELLED_INTERNAL:
      return true;

    case INTERRUPTED_INTERNAL:
      return !CanResume();

    case MAX_DOWNLOAD_INTERNAL_STATE:
      NOTREACHED();
  }
  return false;
}

Project: Chrome

bool DownloadItemImpl::IsDownloadReadyForCompletion(
    const base::Closure& state_change_notification) {
  if (state_ != IN_PROGRESS_INTERNAL)
    return false;

  if (!AllDataSaved())
    return false;

  if (IsDangerous())
    return false;

  DCHECK(!GetTargetFilePath().empty());
  DCHECK(!GetFullPath().empty());
  DCHECK(GetTargetFilePath().DirName() == GetFullPath().DirName());

  if (!delegate_->ShouldCompleteDownload(this, state_change_notification))
    return false;

  return true;
}

Project: Chrome

bool DownloadItemImpl::IsPaused() const {
  return job_ ? job_->is_paused() : false;
}

Project: Chrome

bool DownloadItemImpl::IsSavePackageDownload() const {
  return job_ && job_->IsSavePackageDownload();
}

Project: Chrome

bool DownloadItemImpl::IsTransient() const {
  return transient_;
}

Project: Chrome

bool DownloadItemImpl::IsValidSavePackageStateTransition(
    DownloadInternalState from,
    DownloadInternalState to) {
#if DCHECK_IS_ON()
  switch (from) {
    case INITIAL_INTERNAL:
    case TARGET_PENDING_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
    case TARGET_RESOLVED_INTERNAL:
    case COMPLETING_INTERNAL:
    case COMPLETE_INTERNAL:
    case INTERRUPTED_INTERNAL:
    case RESUMING_INTERNAL:
    case CANCELLED_INTERNAL:
      return false;

    case IN_PROGRESS_INTERNAL:
      return to == CANCELLED_INTERNAL || to == COMPLETE_INTERNAL;

    case MAX_DOWNLOAD_INTERNAL_STATE:
      NOTREACHED();
  }
  return false;
#else
  return true;
#endif
}

Project: Chrome

bool DownloadItemImpl::IsValidStateTransition(DownloadInternalState from,
                                              DownloadInternalState to) {
#if DCHECK_IS_ON()
  switch (from) {
    case INITIAL_INTERNAL:
      return to == TARGET_PENDING_INTERNAL ||
             to == INTERRUPTED_TARGET_PENDING_INTERNAL;

    case TARGET_PENDING_INTERNAL:
      return to == INTERRUPTED_TARGET_PENDING_INTERNAL ||
             to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL;

    case INTERRUPTED_TARGET_PENDING_INTERNAL:
      return to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL;

    case TARGET_RESOLVED_INTERNAL:
      return to == IN_PROGRESS_INTERNAL || to == INTERRUPTED_INTERNAL ||
             to == CANCELLED_INTERNAL;

    case IN_PROGRESS_INTERNAL:
      return to == COMPLETING_INTERNAL || to == CANCELLED_INTERNAL ||
             to == INTERRUPTED_INTERNAL;

    case COMPLETING_INTERNAL:
      return to == COMPLETE_INTERNAL;

    case COMPLETE_INTERNAL:
      return false;

    case INTERRUPTED_INTERNAL:
      return to == RESUMING_INTERNAL || to == CANCELLED_INTERNAL;

    case RESUMING_INTERNAL:
      return to == TARGET_PENDING_INTERNAL ||
             to == INTERRUPTED_TARGET_PENDING_INTERNAL ||
             to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL;

    case CANCELLED_INTERNAL:
      return false;

    case MAX_DOWNLOAD_INTERNAL_STATE:
      NOTREACHED();
  }
  return false;
#else
  return true;
#endif  // DCHECK_IS_ON()
}

Project: Chrome

base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {
  DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
  base::FilePath temp_file_path;
  if (!base::CreateTemporaryFile(&temp_file_path))
    return base::FilePath();

  if (!base::CopyFile(download_file->FullPath(), temp_file_path)) {
    DeleteDownloadedFile(temp_file_path);
    return base::FilePath();
  }

  return temp_file_path;
}

Project: Chrome

void DownloadItemImpl::MarkAsComplete() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  DCHECK(AllDataSaved());
  destination_info_.end_time = base::Time::Now();
  TransitionTo(COMPLETE_INTERNAL);
  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::MaybeCompleteDownload() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!IsSavePackageDownload());

  if (!IsDownloadReadyForCompletion(
          base::Bind(&DownloadItemImpl::MaybeCompleteDownload,
                     weak_ptr_factory_.GetWeakPtr())))
    return;
  DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
  DCHECK(!IsDangerous());
  DCHECK(AllDataSaved());

  OnDownloadCompleting();
}

Project: Chrome

void DownloadItemImpl::NotifyRemoved() {
  for (auto& observer : observers_)
    observer.OnDownloadRemoved(this);
}

Project: Chrome

void DownloadItemImpl::OnAllDataSaved(
    int64_t total_bytes,
    std::unique_ptr<crypto::SecureHash> hash_state) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!AllDataSaved());
  destination_info_.all_data_saved = true;
  SetTotalBytes(total_bytes);
  UpdateProgress(total_bytes, 0);
  received_slices_.clear();
  SetHashState(std::move(hash_state));
  hash_state_.reset();  // No need to retain hash_state_ since we are done with

  if (received_bytes_at_length_mismatch_ > 0) {
    if (total_bytes > received_bytes_at_length_mismatch_) {
      RecordDownloadCount(
          MORE_BYTES_RECEIVED_AFTER_CONTENT_LENGTH_MISMATCH_COUNT);
    } else if (total_bytes == received_bytes_at_length_mismatch_) {
      RecordDownloadCount(
          NO_BYTES_RECEIVED_AFTER_CONTENT_LENGTH_MISMATCH_COUNT);
    } else {
    }
  }
  DVLOG(20) << __func__ << "() download=" << DebugString(true);
  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type,
                                               DownloadInterruptReason reason) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(AllDataSaved());

  DCHECK_EQ(state_, IN_PROGRESS_INTERNAL);
  DVLOG(20) << __func__ << "() danger_type=" << danger_type
            << " download=" << DebugString(true);
  SetDangerType(danger_type);
  if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
    InterruptAndDiscardPartialState(reason);
    DCHECK_EQ(RESUME_MODE_INVALID, GetResumeMode());
  }
  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::OnDownloadCompleting() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (state_ != IN_PROGRESS_INTERNAL)
    return;

  DVLOG(20) << __func__ << "() " << DebugString(true);
  DCHECK(!GetTargetFilePath().empty());
  DCHECK(!IsDangerous());

  DCHECK(download_file_.get());
  DownloadFile::RenameCompletionCallback callback =
      base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
                 weak_ptr_factory_.GetWeakPtr());
  GetDownloadTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(&DownloadFile::RenameAndAnnotate,
                     base::Unretained(download_file_.get()),
                     GetTargetFilePath(),
                     delegate_->GetApplicationClientIdForFileScanning(),
                     GetURL(), GetReferrerUrl(), callback));
}

Project: Chrome

void DownloadItemImpl::OnDownloadFileInitialized(
    DownloadInterruptReason result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(state_ == TARGET_PENDING_INTERNAL ||
         state_ == INTERRUPTED_TARGET_PENDING_INTERNAL)
      << "Unexpected state: " << DebugDownloadStateString(state_);

  DVLOG(20) << __func__
            << "() result:" << DownloadInterruptReasonToString(result);
  if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
    ReleaseDownloadFile(true);
    InterruptAndDiscardPartialState(result);
  }

  DetermineDownloadTarget();
}

Project: Chrome

void DownloadItemImpl::OnDownloadRenamedToFinalName(
    DownloadInterruptReason reason,
    const base::FilePath& full_path) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!IsSavePackageDownload());

  if (state_ != IN_PROGRESS_INTERNAL)
    return;

  DVLOG(20) << __func__ << "() full_path = \"" << full_path.value() << "\" "
            << DebugString(false);

  if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
    InterruptAndDiscardPartialState(reason);
    UpdateObservers();
    return;
  }

  DCHECK(GetTargetFilePath() == full_path);

  if (full_path != GetFullPath()) {
    DCHECK(!full_path.empty());
    SetFullPath(full_path);
  }

  DCHECK(download_file_);
  ReleaseDownloadFile(false);

  TransitionTo(COMPLETING_INTERNAL);

  if (delegate_->ShouldOpenDownload(
          this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened,
                           weak_ptr_factory_.GetWeakPtr()))) {
    Completed();
  } else {
    delegate_delayed_complete_ = true;
    UpdateObservers();
  }
}

Project: Chrome

void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
    DownloadInterruptReason reason,
    const base::FilePath& full_path) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(state_ == TARGET_PENDING_INTERNAL ||
         state_ == INTERRUPTED_TARGET_PENDING_INTERNAL);
  DCHECK(download_file_);
  DVLOG(20) << __func__ << "() download=" << DebugString(true);

  if (DOWNLOAD_INTERRUPT_REASON_NONE == reason) {
    SetFullPath(full_path);
  } else {
    deferred_interrupt_reason_ = reason;
    TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
  }
  OnTargetResolved();
}

Project: Chrome

void DownloadItemImpl::OnDownloadTargetDetermined(
    const base::FilePath& target_path,
    TargetDisposition disposition,
    DownloadDangerType danger_type,
    const base::FilePath& intermediate_path,
    DownloadInterruptReason interrupt_reason) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (state_ == CANCELLED_INTERNAL)
    return;

  DCHECK(state_ == TARGET_PENDING_INTERNAL ||
         state_ == INTERRUPTED_TARGET_PENDING_INTERNAL);
  DVLOG(20) << __func__ << "() target_path:" << target_path.value()
            << " intermediate_path:" << intermediate_path.value()
            << " disposition:" << disposition << " danger_type:" << danger_type
            << " interrupt_reason:"
            << DownloadInterruptReasonToString(interrupt_reason)
            << " this:" << DebugString(true);

  RecordDownloadCount(DOWNLOAD_TARGET_DETERMINED_COUNT);

  if (IsCancellation(interrupt_reason) || target_path.empty()) {
    Cancel(true);
    return;
  }

  if (state_ == TARGET_PENDING_INTERNAL &&
      interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
    deferred_interrupt_reason_ = interrupt_reason;
    TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
    OnTargetResolved();
    return;
  }

  destination_info_.target_path = target_path;
  destination_info_.target_disposition = disposition;
  SetDangerType(danger_type);

  if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL && !download_file_) {
    OnTargetResolved();
    return;
  }

  DCHECK(intermediate_path.DirName() == target_path.DirName());

  if (intermediate_path == GetFullPath()) {
    OnDownloadRenamedToIntermediateName(DOWNLOAD_INTERRUPT_REASON_NONE,
                                        intermediate_path);
    return;
  }

  DCHECK(!IsSavePackageDownload());
  DownloadFile::RenameCompletionCallback callback =
      base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
                 weak_ptr_factory_.GetWeakPtr());
  GetDownloadTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(&DownloadFile::RenameAndUniquify,
                     base::Unretained(download_file_.get()), intermediate_path,
                     callback));
}

Project: Chrome

void DownloadItemImpl::OnDownloadedFileRemoved() {
  file_externally_removed_ = true;
  DVLOG(20) << __func__ << "() download=" << DebugString(true);
  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::OnTargetResolved() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DVLOG(20) << __func__ << "() download=" << DebugString(true);
  DCHECK((state_ == TARGET_PENDING_INTERNAL &&
          deferred_interrupt_reason_ == DOWNLOAD_INTERRUPT_REASON_NONE) ||
         (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL &&
          deferred_interrupt_reason_ != DOWNLOAD_INTERRUPT_REASON_NONE))
      << " deferred_interrupt_reason_:"
      << DownloadInterruptReasonToString(deferred_interrupt_reason_)
      << " this:" << DebugString(true);

  TransitionTo(TARGET_RESOLVED_INTERNAL);

  if (DOWNLOAD_INTERRUPT_REASON_NONE != deferred_interrupt_reason_) {
    InterruptWithPartialState(GetReceivedBytes(), std::move(hash_state_),
                              deferred_interrupt_reason_);
    deferred_interrupt_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE;
    UpdateObservers();
    return;
  }

  TransitionTo(IN_PROGRESS_INTERNAL);
  UpdateObservers();
  MaybeCompleteDownload();
}

Project: Chrome

void DownloadItemImpl::OpenDownload() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!IsDone()) {
    if (!IsTemporary())
      open_when_complete_ = !open_when_complete_;
    return;
  }

  if (state_ != COMPLETE_INTERNAL || file_externally_removed_)
    return;

  delegate_->CheckForFileRemoval(this);
  RecordOpen(GetEndTime(), !GetOpened());
  opened_ = true;
  last_access_time_ = base::Time::Now();
  for (auto& observer : observers_)
    observer.OnDownloadOpened(this);
  delegate_->OpenDownload(this);
}

Project: Chrome

void DownloadItemImpl::Pause() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (IsPaused())
    return;

  switch (state_) {
    case CANCELLED_INTERNAL:
    case COMPLETE_INTERNAL:
    case COMPLETING_INTERNAL:
    case INITIAL_INTERNAL:
    case INTERRUPTED_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
    case RESUMING_INTERNAL:
      return;

    case IN_PROGRESS_INTERNAL:
    case TARGET_PENDING_INTERNAL:
      job_->Pause();
      UpdateObservers();
      return;

    case MAX_DOWNLOAD_INTERNAL_STATE:
    case TARGET_RESOLVED_INTERNAL:
      NOTREACHED();
  }
}

Project: Chrome

int DownloadItemImpl::PercentComplete() const {
  if (delegate_delayed_complete_ || total_bytes_ <= 0)
    return -1;

  return static_cast<int>(GetReceivedBytes() * 100.0 / total_bytes_);
}

Project: Chrome

void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DVLOG(20) << __func__ << "() destroy_file:" << destroy_file;

  if (destroy_file) {
    GetDownloadTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&DownloadFileCancel, base::Passed(&download_file_)));
    destination_info_.current_path.clear();
    received_slices_.clear();
  } else {
    GetDownloadTaskRunner()->PostTask(
        FROM_HERE, base::BindOnce(base::IgnoreResult(&DownloadFileDetach),
                                  base::Passed(&download_file_)));
  }
  weak_ptr_factory_.InvalidateWeakPtrs();
}

Project: Chrome

void DownloadItemImpl::Remove() {
  DVLOG(20) << __func__ << "() download = " << DebugString(true);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  delegate_->AssertStateConsistent(this);
  InterruptAndDiscardPartialState(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
  UpdateObservers();
  delegate_->AssertStateConsistent(this);

  NotifyRemoved();
  delegate_->DownloadRemoved(this);
}

Project: Chrome

void DownloadItemImpl::RemoveObserver(Observer* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  observers_.RemoveObserver(observer);
}

Project: Chrome

DownloadItemImpl::RequestInfo::RequestInfo(
    const std::vector<GURL>& url_chain,
    const GURL& referrer_url,
    const GURL& site_url,
    const GURL& tab_url,
    const GURL& tab_referrer_url,
    const std::string& suggested_filename,
    const base::FilePath& forced_file_path,
    ui::PageTransition transition_type,
    bool has_user_gesture,
    const std::string& remote_address,
    base::Time start_time)
    : url_chain(url_chain),
      referrer_url(referrer_url),
      site_url(site_url),
      tab_url(tab_url),
      tab_referrer_url(tab_referrer_url),
      suggested_filename(suggested_filename),
      forced_file_path(forced_file_path),
      transition_type(transition_type),
      has_user_gesture(has_user_gesture),
      remote_address(remote_address),
      start_time(start_time) {}

Project: Chrome

DownloadItemImpl::RequestInfo::RequestInfo(const GURL& url)
    : url_chain(std::vector<GURL>(1, url)), start_time(base::Time::Now()) {}

Project: Chrome

void DownloadItemImpl::Resume() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DVLOG(20) << __func__ << "() download = " << DebugString(true);
  switch (state_) {
    case CANCELLED_INTERNAL:  // Nothing to resume.
    case COMPLETE_INTERNAL:
    case COMPLETING_INTERNAL:
    case INITIAL_INTERNAL:
    case INTERRUPTED_TARGET_PENDING_INTERNAL:
    case RESUMING_INTERNAL:   // Resumption in progress.
      return;

    case TARGET_PENDING_INTERNAL:
    case IN_PROGRESS_INTERNAL:
      if (!IsPaused())
        return;
      if (job_)
        job_->Resume(true);
      UpdateObservers();
      return;

    case INTERRUPTED_INTERNAL:
      auto_resume_count_ = 0;  // User input resets the counter.
      ResumeInterruptedDownload(ResumptionRequestSource::USER);
      UpdateObservers();
      return;

    case MAX_DOWNLOAD_INTERNAL_STATE:
    case TARGET_RESOLVED_INTERNAL:
      NOTREACHED();
  }
}

Project: Chrome

void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
  if (danger_type != danger_type_) {
    TRACE_EVENT_INSTANT1("download", "DownloadItemSaftyStateUpdated",
                         TRACE_EVENT_SCOPE_THREAD, "danger_type",
                         GetDownloadDangerNames(danger_type).c_str());
  }
  if ((danger_type_ == DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
       danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
       danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
       danger_type_ == DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) &&
      (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
       danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
       danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
       danger_type == DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED)) {
    RecordMaliciousDownloadClassified(danger_type);
  }
  danger_type_ = danger_type;
}

Project: Chrome

void DownloadItemImpl::SetDisplayName(const base::FilePath& name) {
  display_name_ = name;
}

Project: Chrome

void DownloadItemImpl::SetHashState(
    std::unique_ptr<crypto::SecureHash> hash_state) {
  hash_state_ = std::move(hash_state);
  if (!hash_state_) {
    destination_info_.hash.clear();
    return;
  }

  std::unique_ptr<crypto::SecureHash> clone_of_hash_state(hash_state_->Clone());
  std::vector<char> hash_value(clone_of_hash_state->GetHashLength());
  clone_of_hash_state->Finish(&hash_value.front(), hash_value.size());
  destination_info_.hash.assign(hash_value.begin(), hash_value.end());
}

Project: Chrome

void DownloadItemImpl::SetLastAccessTime(base::Time last_access_time) {
  last_access_time_ = last_access_time;
  UpdateObservers();
}

Project: Chrome

void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) {
  total_bytes_ = total_bytes;
}

Project: Chrome

 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
  return delegate_->ShouldOpenFileBasedOnExtension(GetTargetFilePath());
}

Project: Chrome

void DownloadItemImpl::Start(
    std::unique_ptr<DownloadFile> file,
    std::unique_ptr<DownloadRequestHandleInterface> req_handle,
    const DownloadCreateInfo& new_create_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!download_file_.get());
  DVLOG(20) << __func__ << "() this=" << DebugString(true);
  RecordDownloadCount(START_COUNT);

  download_file_ = std::move(file);
  job_ = DownloadJobFactory::CreateJob(this, std::move(req_handle),
                                       new_create_info, false);
  if (job_->IsParallelizable()) {
    RecordParallelizableDownloadCount(START_COUNT, IsParallelDownloadEnabled());
  }

  deferred_interrupt_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE;

  if (state_ == CANCELLED_INTERNAL) {
    ReleaseDownloadFile(true);
    job_->Cancel(true);
    return;
  }

  DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL);

  DCHECK(state_ != INITIAL_INTERNAL || GetTargetFilePath().empty());

  if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
    DCHECK(!download_file_.get());

    DCHECK(new_create_info.save_info);

    int64_t offset = new_create_info.save_info->offset;
    std::unique_ptr<crypto::SecureHash> hash_state =
        new_create_info.save_info->hash_state
            ? new_create_info.save_info->hash_state->Clone()
            : nullptr;

    destination_info_.received_bytes = offset;
    hash_state_ = std::move(hash_state);
    destination_info_.hash.clear();
    deferred_interrupt_reason_ = new_create_info.result;
    received_slices_.clear();
    TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
    DetermineDownloadTarget();
    return;
  }

  if (state_ == INITIAL_INTERNAL) {
    RecordDownloadCount(NEW_DOWNLOAD_COUNT);
    if (job_->IsParallelizable()) {
      RecordParallelizableDownloadCount(NEW_DOWNLOAD_COUNT,
                                        IsParallelDownloadEnabled());
    }
    RecordDownloadMimeType(mime_type_);
    if (!GetBrowserContext()->IsOffTheRecord()) {
      RecordDownloadCount(NEW_DOWNLOAD_COUNT_NORMAL_PROFILE);
      RecordDownloadMimeTypeForNormalProfile(mime_type_);
    }
  }

  DCHECK(download_file_);
  DCHECK(job_);

  if (state_ == RESUMING_INTERNAL)
    UpdateValidatorsOnResumption(new_create_info);

  if (!job_->IsParallelizable() && !received_slices_.empty()) {
    destination_info_.received_bytes =
        GetMaxContiguousDataBlockSizeFromBeginning(received_slices_);
    received_slices_.clear();
  }

  TransitionTo(TARGET_PENDING_INTERNAL);

  job_->Start(download_file_.get(),
              base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
                         weak_ptr_factory_.GetWeakPtr()),
              GetReceivedSlices());
}

Project: Chrome

void DownloadItemImpl::StealDangerousDownload(
    bool delete_file_afterward,
    const AcquireFileCallback& callback) {
  DVLOG(20) << __func__ << "() download = " << DebugString(true);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(IsDangerous());
  DCHECK(AllDataSaved());

  if (delete_file_afterward) {
    if (download_file_) {
      base::PostTaskAndReplyWithResult(
          GetDownloadTaskRunner().get(), FROM_HERE,
          base::Bind(&DownloadFileDetach, base::Passed(&download_file_)),
          callback);
    } else {
      callback.Run(GetFullPath());
    }
    destination_info_.current_path.clear();
    Remove();
  } else if (download_file_) {
    base::PostTaskAndReplyWithResult(
        GetDownloadTaskRunner().get(), FROM_HERE,
        base::Bind(&MakeCopyOfDownloadFile, download_file_.get()), callback);
  } else {
    callback.Run(GetFullPath());
  }
}

Project: Chrome

bool DownloadItemImpl::TimeRemaining(base::TimeDelta* remaining) const {
  if (total_bytes_ <= 0)
    return false;  // We never received the content_length for this download.

  int64_t speed = CurrentSpeed();
  if (speed == 0)
    return false;

  *remaining =
      base::TimeDelta::FromSeconds((total_bytes_ - GetReceivedBytes()) / speed);
  return true;
}

Project: Chrome

void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (state_ == new_state)
    return;

  DownloadInternalState old_state = state_;
  state_ = new_state;

  DCHECK(IsSavePackageDownload()
             ? IsValidSavePackageStateTransition(old_state, new_state)
             : IsValidStateTransition(old_state, new_state))
      << "Invalid state transition from:" << DebugDownloadStateString(old_state)
      << " to:" << DebugDownloadStateString(new_state);

  switch (state_) {
    case INITIAL_INTERNAL:
      NOTREACHED();
      break;

    case TARGET_PENDING_INTERNAL:
    case TARGET_RESOLVED_INTERNAL:
      break;

    case INTERRUPTED_TARGET_PENDING_INTERNAL:
      DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, deferred_interrupt_reason_)
          << "Interrupt reason must be set prior to transitioning into "
             "TARGET_PENDING";
      break;

    case IN_PROGRESS_INTERNAL:
      DCHECK(!GetFullPath().empty()) << "Current output path must be known.";
      DCHECK(!GetTargetFilePath().empty()) << "Target path must be known.";
      DCHECK(GetFullPath().DirName() == GetTargetFilePath().DirName())
          << "Current output directory must match target directory.";
      DCHECK(download_file_) << "Output file must be owned by download item.";
      DCHECK(job_) << "Must have active download job.";
      DCHECK(!job_->is_paused())
          << "At the time a download enters IN_PROGRESS state, "
             "it must not be paused.";
      break;

    case COMPLETING_INTERNAL:
      DCHECK(AllDataSaved()) << "All data must be saved prior to completion.";
      DCHECK(!download_file_)
          << "Download file must be released prior to completion.";
      DCHECK(!GetTargetFilePath().empty()) << "Target path must be known.";
      DCHECK(GetFullPath() == GetTargetFilePath())
          << "Current output path must match target path.";

      TRACE_EVENT_INSTANT2("download", "DownloadItemCompleting",
                           TRACE_EVENT_SCOPE_THREAD, "bytes_so_far",
                           GetReceivedBytes(), "final_hash",
                           destination_info_.hash);
      break;

    case COMPLETE_INTERNAL:
      TRACE_EVENT_INSTANT1("download", "DownloadItemFinished",
                           TRACE_EVENT_SCOPE_THREAD, "auto_opened",
                           auto_opened_ ? "yes" : "no");
      break;

    case INTERRUPTED_INTERNAL:
      DCHECK(!download_file_)
          << "Download file must be released prior to interruption.";
      DCHECK_NE(last_reason_, DOWNLOAD_INTERRUPT_REASON_NONE);
      TRACE_EVENT_INSTANT2("download", "DownloadItemInterrupted",
                           TRACE_EVENT_SCOPE_THREAD, "interrupt_reason",
                           DownloadInterruptReasonToString(last_reason_),
                           "bytes_so_far", GetReceivedBytes());
      break;

    case RESUMING_INTERNAL:
      TRACE_EVENT_INSTANT2("download", "DownloadItemResumed",
                           TRACE_EVENT_SCOPE_THREAD, "interrupt_reason",
                           DownloadInterruptReasonToString(last_reason_),
                           "bytes_so_far", GetReceivedBytes());
      break;

    case CANCELLED_INTERNAL:
      TRACE_EVENT_INSTANT1("download", "DownloadItemCancelled",
                           TRACE_EVENT_SCOPE_THREAD, "bytes_so_far",
                           GetReceivedBytes());
      break;

    case MAX_DOWNLOAD_INTERNAL_STATE:
      NOTREACHED();
      break;
  }

  DVLOG(20) << __func__ << "() from:" << DebugDownloadStateString(old_state)
            << " to:" << DebugDownloadStateString(state_)
            << " this = " << DebugString(true);
  bool is_done =
      (state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
       state_ == RESUMING_INTERNAL || state_ == CANCELLED_INTERNAL);
  bool was_done =
      (old_state == COMPLETE_INTERNAL || old_state == INTERRUPTED_INTERNAL ||
       old_state == RESUMING_INTERNAL || old_state == CANCELLED_INTERNAL);

  if (is_done && !was_done)
    TRACE_EVENT_ASYNC_END0("download", "DownloadItemActive", download_id_);

  if (was_done && !is_done) {
    std::string file_name(GetTargetFilePath().BaseName().AsUTF8Unsafe());
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
        "download", "DownloadItemActive", download_id_, "download_item",
        std::make_unique<DownloadItemActivatedData>(
            TYPE_ACTIVE_DOWNLOAD, GetId(), GetOriginalUrl().spec(),
            GetURL().spec(), file_name, GetDangerType(), GetReceivedBytes(),
            HasUserGesture()));
  }
}

Project: Chrome

void DownloadItemImpl::UpdateProgress(
    int64_t bytes_so_far,
    int64_t bytes_per_sec) {
  destination_info_.received_bytes = bytes_so_far;
  bytes_per_sec_ = bytes_per_sec;

  if (bytes_so_far > total_bytes_)
    total_bytes_ = 0;
}

Project: Chrome

void DownloadItemImpl::UpdateValidatorsOnResumption(
    const DownloadCreateInfo& new_create_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_EQ(RESUMING_INTERNAL, state_);
  DCHECK(!new_create_info.url_chain.empty());

  std::vector<GURL>::const_iterator chain_iter =
      new_create_info.url_chain.begin();
  if (*chain_iter == request_info_.url_chain.back())
    ++chain_iter;

  int origin_state = 0;
  bool is_partial = GetReceivedBytes() > 0;
  if (chain_iter != new_create_info.url_chain.end())
    origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS;
  if (etag_ != new_create_info.etag ||
      last_modified_time_ != new_create_info.last_modified) {
    received_slices_.clear();
    destination_info_.received_bytes = 0;
    origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED;
  }
  if (content_disposition_ != new_create_info.content_disposition)
    origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED;
  RecordOriginStateOnResumption(
      is_partial, static_cast<OriginStateOnResumption>(origin_state));

  request_info_.url_chain.insert(request_info_.url_chain.end(), chain_iter,
                                 new_create_info.url_chain.end());
  etag_ = new_create_info.etag;
  last_modified_time_ = new_create_info.last_modified;
  response_headers_ = new_create_info.response_headers;
  content_disposition_ = new_create_info.content_disposition;
  mime_type_ = new_create_info.mime_type;

}

Project: Chrome

void DownloadItemImpl::ValidateDangerousDownload() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!IsDone());
  DCHECK(IsDangerous());

  DVLOG(20) << __func__ << "() download=" << DebugString(true);

  if (IsDone() || !IsDangerous())
    return;

  RecordDangerousDownloadAccept(GetDangerType(),
                                GetTargetFilePath());

  danger_type_ = DOWNLOAD_DANGER_TYPE_USER_VALIDATED;

  TRACE_EVENT_INSTANT1("download", "DownloadItemSaftyStateUpdated",
                       TRACE_EVENT_SCOPE_THREAD, "danger_type",
                       GetDownloadDangerNames(danger_type_).c_str());

  UpdateObservers();  // TODO(asanka): This is potentially unsafe. The download

  MaybeCompleteDownload();
}

Project: Chrome

void DownloadItemImplDelegate::AssertStateConsistent(
    DownloadItemImpl* download) const {}

Project: Chrome

void DownloadItemImplDelegate::Attach() {
  ++count_;
}

Project: Chrome

void DownloadItemImplDelegate::CheckForFileRemoval(
    DownloadItemImpl* download_item) {}

Project: Chrome

void DownloadItemImplDelegate::Detach() {
  DCHECK_LT(0, count_);
  --count_;
}

Project: Chrome

void DownloadItemImplDelegate::DetermineDownloadTarget(
    DownloadItemImpl* download, const DownloadTargetCallback& callback) {
  base::FilePath target_path(download->GetForcedFilePath());
  callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
               DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, target_path,
               DOWNLOAD_INTERRUPT_REASON_NONE);
}

Project: Chrome

DownloadItemImplDelegate::DownloadItemImplDelegate()
    : count_(0) {}

Project: Chrome

void DownloadItemImplDelegate::DownloadRemoved(DownloadItemImpl* download) {}

Project: Chrome

std::string DownloadItemImplDelegate::GetApplicationClientIdForFileScanning()
    const {
  return std::string();
}

Project: Chrome

BrowserContext* DownloadItemImplDelegate::GetBrowserContext() const {
  return nullptr;
}

Project: Chrome

 void DownloadItemImplDelegate::OpenDownload(DownloadItemImpl* download) {}

Project: Chrome

void DownloadItemImplDelegate::ResumeInterruptedDownload(
    std::unique_ptr<DownloadUrlParameters> params,
    uint32_t id) {}

Project: Chrome

bool DownloadItemImplDelegate::ShouldCompleteDownload(
    DownloadItemImpl* download,
    const base::Closure& complete_callback) {
  return true;
}

Project: Chrome

bool DownloadItemImplDelegate::ShouldOpenDownload(
    DownloadItemImpl* download, const ShouldOpenDownloadCallback& callback) {
  return false;
}

Project: Chrome

bool DownloadItemImplDelegate::ShouldOpenFileBasedOnExtension(
    const base::FilePath& path) {
  return false;
}

Project: Chrome

 void DownloadItemImplDelegate::ShowDownloadInShell(DownloadItemImpl* download) {
 }

Project: Chrome

void DownloadManagerImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

Project: Chrome

void DownloadManagerImpl::AddUrlDownloadHandler(
    UniqueUrlDownloadHandlerPtr downloader) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (downloader)
    url_download_handlers_.push_back(std::move(downloader));
}

Project: Chrome

DownloadManagerImpl::UniqueUrlDownloadHandlerPtr BeginDownload(
    std::unique_ptr<DownloadUrlParameters> params,
    content::ResourceContext* resource_context,
    uint32_t download_id,
    base::WeakPtr<DownloadManagerImpl> download_manager) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  std::unique_ptr<net::URLRequest> url_request =
      DownloadRequestCore::CreateRequestOnIOThread(download_id, params.get());
  std::unique_ptr<storage::BlobDataHandle> blob_data_handle =
      params->GetBlobDataHandle();
  if (blob_data_handle) {
    storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
        url_request.get(), std::move(blob_data_handle));
  }

  if (params->render_process_host_id() >= 0) {
    DownloadInterruptReason reason = DownloadManagerImpl::BeginDownloadRequest(
        std::move(url_request), params->referrer(), resource_context,
        params->content_initiated(), params->render_process_host_id(),
        params->render_view_host_routing_id(),
        params->render_frame_host_routing_id(),
        params->do_not_prompt_for_login());

    if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
      return nullptr;

    CreateInterruptedDownload(params.get(), reason, download_manager);
    return nullptr;
  }

  return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr(
      UrlDownloader::BeginDownload(download_manager, std::move(url_request),
                                   params->referrer(), false)
          .release());
}

Project: Chrome

void DownloadManagerImpl::BeginDownloadInternal(
    std::unique_ptr<content::DownloadUrlParameters> params,
    uint32_t id) {
  download::InProgressCache* in_progress_cache =
      GetBrowserContext()->GetDownloadManagerDelegate()->GetInProgressCache();
  if (in_progress_cache) {
    in_progress_cache->AddOrReplaceEntry(
        download::DownloadEntry(params->guid(), params->request_origin(),
                                ToDownloadSource(params->download_source())));
  }

  if (base::FeatureList::IsEnabled(features::kNetworkService)) {
    std::unique_ptr<ResourceRequest> request = CreateResourceRequest(
        params.get());
    StoragePartitionImpl* storage_partition =
        GetStoragePartition(browser_context_, params->render_process_host_id(),
                            params->render_frame_host_routing_id());
    BrowserThread::PostTaskAndReplyWithResult(
        BrowserThread::IO, FROM_HERE,
        base::BindOnce(
            &BeginResourceDownload, std::move(params), std::move(request),
            storage_partition->url_loader_factory_getter(),
             base::WrapRefCounted(storage_partition->GetFileSystemContext()),
             id, weak_factory_.GetWeakPtr()),
        base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
                       weak_factory_.GetWeakPtr()));
  } else {
    BrowserThread::PostTaskAndReplyWithResult(
        BrowserThread::IO, FROM_HERE,
        base::BindOnce(&BeginDownload, std::move(params),
                       browser_context_->GetResourceContext(), id,
                       weak_factory_.GetWeakPtr()),
         base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
                        weak_factory_.GetWeakPtr()));
   }
}

Project: Chrome

DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest(
    std::unique_ptr<net::URLRequest> url_request,
    const Referrer& referrer,
    ResourceContext* resource_context,
    bool is_content_initiated,
    int render_process_id,
    int render_view_route_id,
    int render_frame_route_id,
    bool do_not_prompt_for_login) {
  if (ResourceDispatcherHostImpl::Get()->is_shutdown())
    return DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;

  ResourceDispatcherHostImpl::Get()->InitializeURLRequest(
      url_request.get(), referrer,
      true,  // download.
      render_process_id, render_view_route_id, render_frame_route_id,
      PREVIEWS_OFF, resource_context);

  url_request->set_first_party_url_policy(
      net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);

  const GURL& url = url_request->original_url();

  if (!CanRequestURLFromRenderer(render_process_id, url))
    return DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST;

  const net::URLRequestContext* request_context = url_request->context();
  if (!request_context->job_factory()->IsHandledProtocol(url.scheme())) {
    DVLOG(1) << "Download request for unsupported protocol: "
             << url.possibly_invalid_spec();
    return DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST;
  }

  std::unique_ptr<ResourceHandler> handler(
      DownloadResourceHandler::Create(url_request.get()));

  ResourceDispatcherHostImpl::Get()->BeginURLRequest(
      std::move(url_request), std::move(handler), true,  // download
      is_content_initiated, do_not_prompt_for_login, resource_context);
  return DOWNLOAD_INTERRUPT_REASON_NONE;
}

Project: Chrome

DownloadManagerImpl::UniqueUrlDownloadHandlerPtr BeginResourceDownload(
    std::unique_ptr<DownloadUrlParameters> params,
    std::unique_ptr<ResourceRequest> request,
    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
    scoped_refptr<storage::FileSystemContext> file_system_context,
    uint32_t download_id,
    base::WeakPtr<DownloadManagerImpl> download_manager) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (params->render_process_host_id() >= 0 &&
      !CanRequestURLFromRenderer(params->render_process_host_id(),
                                 params->url())) {
    CreateInterruptedDownload(params.get(),
                              DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST,
                              download_manager);
    return nullptr;
  }

  ResourceRequestInfo::WebContentsGetter getter =
      base::Bind(&GetWebContents, params->render_process_host_id(),
                 params->render_frame_host_routing_id(), -1);
  return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr(
      ResourceDownloader::BeginDownload(
          download_manager, std::move(params), std::move(request),
          url_loader_factory_getter, file_system_context, getter, download_id,
          false)
          .release());
}

Project: Chrome

bool CanRequestURLFromRenderer(int render_process_id, GURL url) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
          render_process_id, url)) {
    DVLOG(1) << "Denied unauthorized download request for "
             << url.possibly_invalid_spec();
    return false;
  }
  return true;
}

Project: Chrome

void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if ((download_item->GetState() == DownloadItem::COMPLETE) &&
      !download_item->GetFileExternallyRemoved() &&
      delegate_) {
    delegate_->CheckForFileExistence(
        download_item,
        base::BindOnce(&DownloadManagerImpl::OnFileExistenceChecked,
                       weak_factory_.GetWeakPtr(), download_item->GetId()));
  }
}

Project: Chrome

void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  for (const auto& it : downloads_) {
    DownloadItemImpl* item = it.second.get();
    CheckForFileRemoval(item);
  }
}

Project: Chrome

DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
    uint32_t id,
    const DownloadCreateInfo& info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!base::ContainsKey(downloads_, id));
  DownloadItemImpl* download = item_factory_->CreateActiveItem(this, id, info);
  downloads_[id] = base::WrapUnique(download);
  downloads_by_guid_[download->GetGuid()] = download;
  return download;
}

Project: Chrome

void DownloadManagerImpl::CreateDownloadHandlerForNavigation(
    base::WeakPtr<DownloadManagerImpl> download_manager,
    ResourceRequestInfo::WebContentsGetter web_contents_getter,
    std::unique_ptr<ResourceRequest> resource_request,
    std::vector<GURL> url_chain,
    scoped_refptr<ResourceResponse> response,
    net::CertStatus cert_status,
    mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  std::unique_ptr<ResourceDownloader> resource_downloader =
      ResourceDownloader::InterceptNavigationResponse(
          download_manager, std::move(resource_request),
          std::move(web_contents_getter), std::move(url_chain),
          std::move(response), std::move(cert_status),
          std::move(url_loader_client_endpoints));

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
                     download_manager,
                     DownloadManagerImpl::UniqueUrlDownloadHandlerPtr(
                         resource_downloader.release())));
}

Project: Chrome

DownloadItem* DownloadManagerImpl::CreateDownloadItem(
    const std::string& guid,
    uint32_t id,
    const base::FilePath& current_path,
    const base::FilePath& target_path,
    const std::vector<GURL>& url_chain,
    const GURL& referrer_url,
    const GURL& site_url,
    const GURL& tab_url,
    const GURL& tab_refererr_url,
    const std::string& mime_type,
    const std::string& original_mime_type,
    base::Time start_time,
    base::Time end_time,
    const std::string& etag,
    const std::string& last_modified,
    int64_t received_bytes,
    int64_t total_bytes,
    const std::string& hash,
    DownloadItem::DownloadState state,
    DownloadDangerType danger_type,
    DownloadInterruptReason interrupt_reason,
    bool opened,
    base::Time last_access_time,
    bool transient,
    const std::vector<DownloadItem::ReceivedSlice>& received_slices) {
  if (base::ContainsKey(downloads_, id)) {
    NOTREACHED();
    return nullptr;
  }
  DCHECK(!base::ContainsKey(downloads_by_guid_, guid));
  DownloadItemImpl* item = item_factory_->CreatePersistedItem(
      this, guid, id, current_path, target_path, url_chain, referrer_url,
      site_url, tab_url, tab_refererr_url, mime_type, original_mime_type,
      start_time, end_time, etag, last_modified, received_bytes, total_bytes,
      hash, state, danger_type, interrupt_reason, opened, last_access_time,
      transient, received_slices);
  downloads_[id] = base::WrapUnique(item);
  downloads_by_guid_[guid] = item;
  for (auto& observer : observers_)
    observer.OnDownloadCreated(this, item);
  DVLOG(20) << __func__ << "() download = " << item->DebugString(true);
  return item;
}

Project: Chrome

void CreateInterruptedDownload(
    DownloadUrlParameters* params,
    DownloadInterruptReason reason,
    base::WeakPtr<DownloadManagerImpl> download_manager) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  std::unique_ptr<DownloadCreateInfo> failed_created_info(
      new DownloadCreateInfo(base::Time::Now(),
                             base::WrapUnique(new DownloadSaveInfo)));
  failed_created_info->url_chain.push_back(params->url());
  failed_created_info->result = reason;
  std::unique_ptr<ByteStreamReader> empty_byte_stream;
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::BindOnce(&DownloadManager::StartDownload, download_manager,
                     std::move(failed_created_info),
                     std::make_unique<DownloadManager::InputStream>(
                         std::move(empty_byte_stream)),
                     params->callback()));
}

Project: Chrome

void DownloadManagerImpl::CreateSavePackageDownloadItem(
    const base::FilePath& main_file_path,
    const GURL& page_url,
    const std::string& mime_type,
    std::unique_ptr<DownloadRequestHandleInterface> request_handle,
    const DownloadItemImplCreated& item_created) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  GetNextId(base::Bind(
      &DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
      weak_factory_.GetWeakPtr(), main_file_path, page_url, mime_type,
      base::Passed(std::move(request_handle)), item_created));
}

Project: Chrome

void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
    const base::FilePath& main_file_path,
    const GURL& page_url,
    const std::string& mime_type,
    std::unique_ptr<DownloadRequestHandleInterface> request_handle,
    const DownloadItemImplCreated& item_created,
    uint32_t id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(content::DownloadItem::kInvalidId, id);
  DCHECK(!base::ContainsKey(downloads_, id));
  DownloadItemImpl* download_item = item_factory_->CreateSavePageItem(
      this, id, main_file_path, page_url, mime_type, std::move(request_handle));
  downloads_[download_item->GetId()] = base::WrapUnique(download_item);
  DCHECK(!base::ContainsKey(downloads_by_guid_, download_item->GetGuid()));
  downloads_by_guid_[download_item->GetGuid()] = download_item;
  for (auto& observer : observers_)
    observer.OnDownloadCreated(this, download_item);
  if (!item_created.is_null())
    item_created.Run(download_item);
}

Project: Chrome

void DownloadManagerImpl::DetermineDownloadTarget(
    DownloadItemImpl* item, const DownloadTargetCallback& callback) {
  if (!delegate_ || !delegate_->DetermineDownloadTarget(item, callback)) {
    base::FilePath target_path = item->GetForcedFilePath();
    callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
                 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, target_path,
                 DOWNLOAD_INTERRUPT_REASON_NONE);
  }
}

Project: Chrome

  DownloadItemFactoryImpl() {}

Project: Chrome

DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
    : item_factory_(new DownloadItemFactoryImpl()),
      file_factory_(new DownloadFileFactory()),
      shutdown_needed_(true),
      initialized_(false),
      history_db_initialized_(false),
      in_progress_cache_initialized_(false),
      browser_context_(browser_context),
      delegate_(nullptr),
      weak_factory_(this) {
  DCHECK(browser_context);
}

Project: Chrome

void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
  if (!download)
    return;

  downloads_by_guid_.erase(download->GetGuid());
  downloads_.erase(download->GetId());
}

Project: Chrome

void DownloadManagerImpl::DownloadUrl(
    std::unique_ptr<DownloadUrlParameters> params) {
  if (params->post_id() >= 0) {
    DCHECK(params->prefer_cache());
    DCHECK_EQ("POST", params->method());
  }

  BeginDownloadInternal(std::move(params), content::DownloadItem::kInvalidId);
}

Project: Chrome

void DownloadManagerImpl::GetAllDownloads(DownloadVector* downloads) {
  for (const auto& it : downloads_) {
    downloads->push_back(it.second.get());
  }
}

Project: Chrome

std::string DownloadManagerImpl::GetApplicationClientIdForFileScanning() const {
  if (delegate_)
    return delegate_->ApplicationClientIdForFileScanning();
  return std::string();
}

Project: Chrome

BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
  return browser_context_;
}

Project: Chrome

DownloadItem* DownloadManagerImpl::GetDownload(uint32_t download_id) {
  return base::ContainsKey(downloads_, download_id)
             ? downloads_[download_id].get()
             : nullptr;
}

Project: Chrome

DownloadFileFactory* DownloadManagerImpl::GetDownloadFileFactoryForTesting() {
  return file_factory_.get();
}

Project: Chrome

base::FilePath GetTemporaryDownloadDirectory() {
  std::unique_ptr<base::Environment> env(base::Environment::Create());
  return base::nix::GetXDGDirectory(env.get(), "XDG_DATA_HOME", ".local/share");
}

Project: Chrome

WebContents* GetWebContents(int render_process_id,
                            int render_frame_id,
                            int frame_tree_node_id) {
  DCHECK(IsBrowserSideNavigationEnabled());

  WebContents* web_contents = WebContents::FromRenderFrameHost(
      RenderFrameHost::FromID(render_process_id, render_frame_id));
  if (web_contents)
    return web_contents;

  return WebContents::FromFrameTreeNodeId(frame_tree_node_id);
}

Project: Chrome

int DownloadManagerImpl::InProgressCount() const {
  int count = 0;
  for (const auto& it : downloads_) {
    if (it.second->GetState() == DownloadItem::IN_PROGRESS)
      ++count;
  }
  return count;
}

Project: Chrome

InProgressDownloadObserver::InProgressDownloadObserver(
    download::InProgressCache* in_progress_cache)
    : in_progress_cache_(in_progress_cache) {}

Project: Chrome

void DownloadManagerImpl::InterceptNavigation(
    std::unique_ptr<ResourceRequest> resource_request,
    std::vector<GURL> url_chain,
    scoped_refptr<ResourceResponse> response,
    mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    net::CertStatus cert_status,
    int frame_tree_node_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!delegate_)
    return;

  const GURL& url = resource_request->url;
  const std::string& method = resource_request->method;
  ResourceRequestInfo::WebContentsGetter web_contents_getter =
      base::BindRepeating(&GetWebContents, ChildProcessHost::kInvalidUniqueID,
                          MSG_ROUTING_NONE, frame_tree_node_id);

  base::OnceCallback<void(bool /* download allowed */)>
      on_download_checks_done = base::BindOnce(
          &DownloadManagerImpl::InterceptNavigationOnChecksComplete,
          weak_factory_.GetWeakPtr(), web_contents_getter,
          std::move(resource_request), std::move(url_chain),
          std::move(response), cert_status,
          std::move(url_loader_client_endpoints));

  delegate_->CheckDownloadAllowed(web_contents_getter, url, method,
                                  std::move(on_download_checks_done));
}

Project: Chrome

void DownloadManagerImpl::InterceptNavigationOnChecksComplete(
    ResourceRequestInfo::WebContentsGetter web_contents_getter,
    std::unique_ptr<ResourceRequest> resource_request,
    std::vector<GURL> url_chain,
    scoped_refptr<ResourceResponse> response,
    net::CertStatus cert_status,
    mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download_allowed) {
  if (!is_download_allowed)
    return;

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::BindOnce(&DownloadManagerImpl::CreateDownloadHandlerForNavigation,
                     weak_factory_.GetWeakPtr(), web_contents_getter,
                     std::move(resource_request), std::move(url_chain),
                     std::move(response), std::move(cert_status),
                     std::move(url_loader_client_endpoints)));
}

Project: Chrome

bool DownloadManagerImpl::IsManagerInitialized() const {
  return initialized_;
}

Project: Chrome

void InProgressDownloadObserver::OnDownloadRemoved(DownloadItem* download) {
  if (!in_progress_cache_)
    return;

  in_progress_cache_->RemoveEntry(download->GetGuid());
}

Project: Chrome

void InProgressDownloadObserver::OnDownloadUpdated(DownloadItem* download) {
  if (!in_progress_cache_)
    return;

  switch (download->GetState()) {
    case DownloadItem::DownloadState::COMPLETE:
    case DownloadItem::DownloadState::CANCELLED:
      if (in_progress_cache_)
        in_progress_cache_->RemoveEntry(download->GetGuid());
      break;
    case DownloadItem::DownloadState::IN_PROGRESS:
      break;
    default:
      break;
  }
}

Project: Chrome

void DownloadManagerImpl::OnUrlDownloadStarted(
    std::unique_ptr<DownloadCreateInfo> download_create_info,
    std::unique_ptr<DownloadManager::InputStream> stream,
    const DownloadUrlParameters::OnStartedCallback& callback) {
  StartDownload(std::move(download_create_info), std::move(stream), callback);
}

Project: Chrome

void DownloadManagerImpl::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
  for (auto ptr = url_download_handlers_.begin();
       ptr != url_download_handlers_.end(); ++ptr) {
    if (ptr->get() == downloader) {
      url_download_handlers_.erase(ptr);
      return;
    }
  }
}

Project: Chrome

void DownloadManagerImpl::OpenDownload(DownloadItemImpl* download) {
  int num_unopened = 0;
  for (const auto& it : downloads_) {
    DownloadItemImpl* item = it.second.get();
    if ((item->GetState() == DownloadItem::COMPLETE) &&
        !item->GetOpened())
      ++num_unopened;
  }
  RecordOpensOutstanding(num_unopened);

  if (delegate_)
     delegate_->OpenDownload(download);
 }

Project: Chrome

void DownloadManagerImpl::PostInitialization(
    DownloadInitializationDependency dependency) {
  if (initialized_)
    return;

  switch (dependency) {
    case DOWNLOAD_INITIALIZATION_DEPENDENCY_HISTORY_DB:
      history_db_initialized_ = true;
      break;
    case DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE:
      in_progress_cache_initialized_ = true;
      break;
    case DOWNLOAD_INITIALIZATION_DEPENDENCY_NONE:
    default:
      NOTREACHED();
      break;
  }

  initialized_ = history_db_initialized_ && in_progress_cache_initialized_;

  if (initialized_) {
    for (auto& observer : observers_)
      observer.OnManagerInitialized();
  }
}

Project: Chrome

int DownloadManagerImpl::RemoveDownloadsByURLAndTime(
    const base::Callback<bool(const GURL&)>& url_filter,
    base::Time remove_begin,
    base::Time remove_end) {
  int count = 0;
  auto it = downloads_.begin();
  while (it != downloads_.end()) {
    DownloadItemImpl* download = it->second.get();

    ++it;

    if (download->GetState() != DownloadItem::IN_PROGRESS &&
        url_filter.Run(download->GetURL()) &&
        download->GetStartTime() >= remove_begin &&
        (remove_end.is_null() || download->GetStartTime() < remove_end)) {
      download->Remove();
      count++;
    }
  }
  return count;
}

Project: Chrome

void DownloadManagerImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

Project: Chrome

void DownloadManagerImpl::ResumeInterruptedDownload(
    std::unique_ptr<content::DownloadUrlParameters> params,
    uint32_t id) {
  BeginDownloadInternal(std::move(params), id);
}

Project: Chrome

void DownloadManagerImpl::SetDelegate(DownloadManagerDelegate* delegate) {
  delegate_ = delegate;

  if (initialized_ || in_progress_cache_initialized_)
    return;

  base::RepeatingClosure post_init_callback = base::BindRepeating(
      &DownloadManagerImpl::PostInitialization, weak_factory_.GetWeakPtr(),
      DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE);

  if (delegate_) {
    download::InProgressCache* in_progress_cache =
        delegate_->GetInProgressCache();
    if (in_progress_cache) {
      in_progress_cache->Initialize(post_init_callback);
      return;
    }
  }

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, post_init_callback);
}

Project: Chrome

void DownloadManagerImpl::SetDownloadFileFactoryForTesting(
    std::unique_ptr<DownloadFileFactory> file_factory) {
  file_factory_ = std::move(file_factory);
}

Project: Chrome

void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
    std::unique_ptr<DownloadItemFactory> item_factory) {
  item_factory_ = std::move(item_factory);
}

Project: Chrome

bool DownloadManagerImpl::ShouldCompleteDownload(
    DownloadItemImpl* item, const base::Closure& complete_callback) {
  if (!delegate_ ||
      delegate_->ShouldCompleteDownload(item, complete_callback)) {
    return true;
  }
  return false;
}

Project: Chrome

bool DownloadManagerImpl::ShouldOpenDownload(
    DownloadItemImpl* item, const ShouldOpenDownloadCallback& callback) {
  if (!delegate_)
    return true;

Project: Chrome

bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(
    const base::FilePath& path) {
  if (!delegate_)
    return false;

  return delegate_->ShouldOpenFileBasedOnExtension(path);
}

Project: Chrome

 void DownloadManagerImpl::ShowDownloadInShell(DownloadItemImpl* download) {
   if (delegate_)
     delegate_->ShowDownloadInShell(download);
}

Project: Chrome

void DownloadManagerImpl::Shutdown() {
  DVLOG(20) << __func__ << "() shutdown_needed_ = " << shutdown_needed_;
  if (!shutdown_needed_)
    return;
  shutdown_needed_ = false;

  for (auto& observer : observers_)
    observer.ManagerGoingDown(this);

  for (const auto& it : downloads_) {
    DownloadItemImpl* download = it.second.get();
    if (download->GetState() == DownloadItem::IN_PROGRESS)
      download->Cancel(false);
  }
  downloads_.clear();
  downloads_by_guid_.clear();
  url_download_handlers_.clear();

  observers_.Clear();

  if (delegate_)
    delegate_->Shutdown();
  delegate_ = nullptr;
}

Project: Chrome

void DownloadManagerImpl::StartDownload(
    std::unique_ptr<DownloadCreateInfo> info,
    std::unique_ptr<DownloadManager::InputStream> stream,
    const DownloadUrlParameters::OnStartedCallback& on_started) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(info);

  DCHECK(
      (info->result == DOWNLOAD_INTERRUPT_REASON_NONE && !stream->IsEmpty()) ||
      (info->result != DOWNLOAD_INTERRUPT_REASON_NONE && stream->IsEmpty()));
  DVLOG(20) << __func__
            << "() result=" << DownloadInterruptReasonToString(info->result);
  uint32_t download_id = info->download_id;
  const bool new_download = (download_id == content::DownloadItem::kInvalidId);
  if (new_download)
    RecordDownloadConnectionSecurity(info->url(), info->url_chain);
  base::Callback<void(uint32_t)> got_id(base::Bind(
      &DownloadManagerImpl::StartDownloadWithId, weak_factory_.GetWeakPtr(),
      base::Passed(&info), base::Passed(&stream), on_started, new_download));
  if (new_download) {
    GetNextId(got_id);
  } else {
    got_id.Run(download_id);
  }
}

Project: Chrome

void DownloadManagerImpl::StartDownloadWithId(
    std::unique_ptr<DownloadCreateInfo> info,
    std::unique_ptr<DownloadManager::InputStream> stream,
    const DownloadUrlParameters::OnStartedCallback& on_started,
    bool new_download,
    uint32_t id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(content::DownloadItem::kInvalidId, id);
  DownloadItemImpl* download = nullptr;
  if (new_download) {
    download = CreateActiveItem(id, *info);
  } else {
    auto item_iterator = downloads_.find(id);
    if (item_iterator == downloads_.end() ||
        (item_iterator->second->GetState() == DownloadItem::CANCELLED)) {
      info->request_handle->CancelRequest(true);
      if (!on_started.is_null())
        on_started.Run(nullptr, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
      if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE)
        GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
      return;
    }
    download = item_iterator->second.get();
  }

  base::FilePath default_download_directory;
#if defined(USE_X11)
  default_download_directory = GetTemporaryDownloadDirectory();
#else
  if (delegate_) {
    base::FilePath website_save_directory;  // Unused
    bool skip_dir_check = false;            // Unused
    delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory,
                          &default_download_directory, &skip_dir_check);
  }
#endif

  if (delegate_) {
    if (!in_progress_download_observer_) {
      in_progress_download_observer_.reset(
          new InProgressDownloadObserver(delegate_->GetInProgressCache()));
    }
    download->RemoveObserver(in_progress_download_observer_.get());
    download->AddObserver(in_progress_download_observer_.get());
  }

  std::unique_ptr<DownloadFile> download_file;

  if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
    DCHECK(stream.get());
    download_file.reset(file_factory_->CreateFile(
        std::move(info->save_info), default_download_directory,
        std::move(stream), id, download->DestinationObserverAsWeakPtr()));
  }

  download->Start(std::move(download_file), std::move(info->request_handle),
                  *info);

  if (new_download) {
    for (auto& observer : observers_)
      observer.OnDownloadCreated(this, download);
  }

  if (!on_started.is_null())
    on_started.Run(download, DOWNLOAD_INTERRUPT_REASON_NONE);
}

Project: Chrome

DownloadManagerImpl::~DownloadManagerImpl() {
  DCHECK(!shutdown_needed_);
}

Project: Chrome

void DownloadManagerDelegate::CheckDownloadAllowed(
    const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
    const GURL& url,
    const std::string& request_method,
    CheckDownloadAllowedCallback check_download_allowed_cb) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(check_download_allowed_cb), true));
}

Project: Chrome

bool DownloadManagerDelegate::DetermineDownloadTarget(
    DownloadItem* item,
    const DownloadTargetCallback& callback) {
  return false;
}

Project: Chrome

 bool DownloadManagerDelegate::GenerateFileHash() {
   return false;
 }

Project: Chrome

download::InProgressCache* DownloadManagerDelegate::GetInProgressCache() {
  return nullptr;
}

Project: Chrome

void DownloadManagerDelegate::GetNextId(const DownloadIdCallback& callback) {
  callback.Run(content::DownloadItem::kInvalidId);
}

Project: Chrome

bool DownloadManagerDelegate::ShouldCompleteDownload(
    DownloadItem* item,
    const base::Closure& callback) {
  return true;
}

Project: Chrome

bool DownloadManagerDelegate::ShouldOpenDownload(
    DownloadItem* item, const DownloadOpenDelayedCallback& callback) {
   return true;
 }

Project: Chrome

DownloadManagerDelegate::~DownloadManagerDelegate() {}