Commit message: None
CVE: CVE-2018-6152
Vulnerability description: The implementation of the Page.downloadBehavior backend unconditionally marked downloaded files as safe, regardless of file type in Google Chrome prior to 66.0.3359.117 allowed an attacker who convinced a user to install a malicious extension to potentially perform a sandbox escape via a crafted HTML page and user interaction.

Project: Chrome

bool DevToolsDownloadManagerDelegate::DetermineDownloadTarget(
    content::DownloadItem* item,
    const content::DownloadTargetCallback& callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  DevToolsDownloadManagerHelper* download_helper =
      DevToolsDownloadManagerHelper::FromWebContents(item->GetWebContents());

  if (proxy_download_delegate_ && !download_helper)
    return proxy_download_delegate_->DetermineDownloadTarget(item, callback);

  if (!download_helper ||
      download_helper->GetDownloadBehavior() !=
          DevToolsDownloadManagerHelper::DownloadBehavior::ALLOW) {
    base::FilePath empty_path = base::FilePath();
    callback.Run(empty_path,
                 content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
                 download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, empty_path,
                 content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED);
    return true;
  }

  base::FilePath download_path =
      base::FilePath::FromUTF8Unsafe(download_helper->GetDownloadPath());

  FilenameDeterminedCallback filename_determined_callback =
      base::Bind(&DevToolsDownloadManagerDelegate::OnDownloadPathGenerated,
                 base::Unretained(this), item->GetId(), callback);

  PostTaskWithTraits(
      FROM_HERE,
      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
       base::TaskPriority::USER_VISIBLE},
      base::BindOnce(&DevToolsDownloadManagerDelegate::GenerateFilename,
                     item->GetURL(), item->GetContentDisposition(),
                     item->GetSuggestedFilename(), item->GetMimeType(),
                     download_path, filename_determined_callback));
  return true;
}

Project: Chrome

DevToolsDownloadManagerDelegate::DevToolsDownloadManagerDelegate()
    : download_manager_(nullptr), proxy_download_delegate_(nullptr) {
  g_devtools_manager_delegate = this;
}

Project: Chrome

DevToolsDownloadManagerDelegate::GetInstance() {
  if (!g_devtools_manager_delegate)
    new DevToolsDownloadManagerDelegate();

  return g_devtools_manager_delegate;
}

Project: Chrome

void DevToolsDownloadManagerDelegate::GetNextId(
    const content::DownloadIdCallback& callback) {
  static uint32_t next_id = content::DownloadItem::kInvalidId + 1;
  if (proxy_download_delegate_) {
    proxy_download_delegate_->GetNextId(callback);
    return;
  }
  callback.Run(next_id++);
}

Project: Chrome

bool DevToolsDownloadManagerDelegate::ShouldOpenDownload(
    content::DownloadItem* item,
    const content::DownloadOpenDelayedCallback& callback) {
  DevToolsDownloadManagerHelper* download_helper =
      DevToolsDownloadManagerHelper::FromWebContents(item->GetWebContents());

  if (download_helper)
    return true;
  if (proxy_download_delegate_)
    return proxy_download_delegate_->ShouldOpenDownload(item, callback);
  return false;
}

Project: Chrome

void DevToolsDownloadManagerDelegate::Shutdown() {
  if (proxy_download_delegate_)
    proxy_download_delegate_->Shutdown();
  download_manager_ = nullptr;
}

Project: Chrome

DevToolsDownloadManagerDelegate::~DevToolsDownloadManagerDelegate() {
  DevToolsDownloadManagerDelegate* download_delegate = GetInstance();
  download_delegate->download_manager_->SetDelegate(
      download_delegate->proxy_download_delegate_);
  download_delegate->download_manager_ = nullptr;

  if (download_manager_) {
    download_manager_->SetDelegate(proxy_download_delegate_);
    download_manager_ = nullptr;
  }
  g_devtools_manager_delegate = nullptr;
}