@Override
 public void onConfirmInfoBarButtonClicked(ConfirmInfoBar infoBar, boolean confirm) {
   if (mPendingRequest.hasDownloadId()) {
     nativeDangerousDownloadValidated(mTab, mPendingRequest.getDownloadId(), confirm);
     if (confirm) {
       showDownloadStartNotification();
     }
     closeBlankTab();
   } else if (confirm) {
     // User confirmed the download.
     if (mPendingRequest.isGETRequest()) {
       enqueueDownloadManagerRequest(mPendingRequest);
     } else {
       DownloadInfo newDownloadInfo =
           DownloadInfo.Builder.fromDownloadInfo(mPendingRequest).setIsSuccessful(true).build();
       DownloadManagerService.getDownloadManagerService(mContext)
           .onDownloadCompleted(newDownloadInfo);
     }
   } else {
     // User did not accept the download, discard the file if it is a POST download.
     if (!mPendingRequest.isGETRequest()) {
       discardFile(mPendingRequest.getFilePath());
     }
   }
   mPendingRequest = null;
   infoBar.dismissJavaOnlyInfoBar();
 }
 private void deleteFileForOverwrite(DownloadInfo info) {
   File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
   if (!dir.isDirectory()) return;
   final File file = new File(dir, info.getFileName());
   if (!file.delete()) {
     Log.e(LOGTAG, "Failed to delete a file." + info.getFileName());
   }
 }
 private static void deleteFileForOverwrite(DownloadInfo info) {
   assert !ThreadUtils.runningOnUiThread();
   File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
   if (!dir.isDirectory()) return;
   final File file = new File(dir, info.getFileName());
   if (!file.delete()) {
     Log.e(TAG, "Failed to delete a file: " + info.getFileName());
   }
 }
 @Override
 public void onInfoBarDismissed(InfoBar infoBar) {
   if (mPendingRequest != null) {
     if (mPendingRequest.hasDownloadId()) {
       nativeDangerousDownloadValidated(mTab, mPendingRequest.getDownloadId(), false);
     } else if (!mPendingRequest.isGETRequest()) {
       // Infobar was dismissed, discard the file if a POST download is pending.
       discardFile(mPendingRequest.getFilePath());
     }
   }
   // Forget the pending request.
   mPendingRequest = null;
 }
  @Override
  public void onConfirmInfoBarButtonClicked(ConfirmInfoBar infoBar, boolean confirm) {
    assert mTab != null;
    if (mPendingRequest.hasDownloadId()) {
      nativeDangerousDownloadValidated(mTab, mPendingRequest.getDownloadId(), confirm);
      if (confirm) {
        showDownloadStartNotification();
      }
      closeBlankTab();
    } else if (confirm) {
      // User confirmed the download.
      if (mPendingRequest.isGETRequest()) {
        final DownloadInfo info = mPendingRequest;
        new AsyncTask<Void, Void, Pair<String, String>>() {
          @Override
          protected Pair<String, String> doInBackground(Void... params) {
            Pair<String, String> result = getDownloadDirectoryNameAndFullPath();
            String fullDirPath = result.second;
            return doesFileAlreadyExists(fullDirPath, info.getFileName()) ? result : null;
          }

          @Override
          protected void onPostExecute(Pair<String, String> result) {
            if (result != null) {
              // File already exists.
              String dirName = result.first;
              String fullDirPath = result.second;
              launchDownloadInfoBar(info, dirName, fullDirPath);
            } else {
              enqueueDownloadManagerRequest(info);
            }
          }
        }.execute();
      } else {
        DownloadInfo newDownloadInfo =
            DownloadInfo.Builder.fromDownloadInfo(mPendingRequest).setIsSuccessful(true).build();
        DownloadManagerService.getDownloadManagerService(mContext)
            .onDownloadCompleted(newDownloadInfo);
      }
    } else {
      // User did not accept the download, discard the file if it is a POST download.
      if (!mPendingRequest.isGETRequest()) {
        discardFile(mPendingRequest.getFilePath());
      }
    }
    mPendingRequest = null;
    infoBar.dismissJavaOnlyInfoBar();
  }
 /**
  * Request a download from the given url, or if a streaming viewer is available stream the content
  * into the viewer.
  *
  * @param downloadInfo Information about the download.
  */
 @Override
 public void requestHttpGetDownload(DownloadInfo downloadInfo) {
   // If we're dealing with A/V content that's not explicitly marked for download, check if it
   // is streamable.
   if (!DownloadManagerService.isAttachment(downloadInfo.getContentDisposition())) {
     // Query the package manager to see if there's a registered handler that matches.
     Intent intent = new Intent(Intent.ACTION_VIEW);
     intent.setDataAndType(Uri.parse(downloadInfo.getUrl()), downloadInfo.getMimeType());
     // If the intent is resolved to ourselves, we don't want to attempt to load the url
     // only to try and download it again.
     if (DownloadManagerService.openIntent(mContext, intent, false)) {
       return;
     }
   }
   onDownloadStartNoStream(downloadInfo);
 }
  /**
   * Notify the host application a download should be done, even if there is a streaming viewer
   * available for this type.
   *
   * @param downloadInfo Information about the download.
   */
  protected void onDownloadStartNoStream(final DownloadInfo downloadInfo) {
    final String newMimeType =
        remapGenericMimeType(
            downloadInfo.getMimeType(), downloadInfo.getUrl(), downloadInfo.getFileName());
    final String fileName =
        TextUtils.isEmpty(downloadInfo.getFileName())
            ? fileName(downloadInfo.getUrl(), newMimeType, downloadInfo.getContentDisposition())
            : downloadInfo.getFileName();
    new AsyncTask<Void, Void, Object[]>() {
      @Override
      protected Object[] doInBackground(Void... params) {
        // Check to see if we have an SDCard.
        String status = Environment.getExternalStorageState();
        Pair<String, String> result = getDownloadDirectoryNameAndFullPath();
        String dirName = result.first;
        String fullDirPath = result.second;
        boolean fileExists = doesFileAlreadyExists(fullDirPath, fileName);

        return new Object[] {status, dirName, fullDirPath, fileExists};
      }

      @Override
      protected void onPostExecute(Object[] result) {
        String externalStorageState = (String) result[0];
        String dirName = (String) result[1];
        String fullDirPath = (String) result[2];
        Boolean fileExists = (Boolean) result[3];
        if (!checkExternalStorageAndNotify(fileName, fullDirPath, externalStorageState)) {
          return;
        }
        String url = sanitizeDownloadUrl(downloadInfo);
        if (url == null) return;
        DownloadInfo newInfo =
            DownloadInfo.Builder.fromDownloadInfo(downloadInfo)
                .setUrl(url)
                .setMimeType(newMimeType)
                .setDescription(url)
                .setFileName(fileName)
                .setIsGETRequest(true)
                .build();

        // TODO(acleung): This is a temp fix to disable auto downloading if flash files.
        // We want to avoid downloading flash files when it is linked as an iframe.
        // The proper fix would be to let chrome knows which frame originated the request.
        if ("application/x-shockwave-flash".equals(newInfo.getMimeType())) return;

        if (isDangerousFile(fileName, newMimeType)) {
          confirmDangerousDownload(newInfo);
        } else {
          // Not a dangerous file, proceed.
          if (fileExists) {
            launchDownloadInfoBar(newInfo, dirName, fullDirPath);
          } else {
            enqueueDownloadManagerRequest(newInfo);
          }
        }
      }
    }.execute();
  }
  /**
   * Launch an info bar if the file name already exists for the download.
   *
   * @param info The information of the file we are about to download.
   * @return Whether an info bar has been launched or not.
   */
  private boolean launchInfoBarIfFileExists(final DownloadInfo info) {
    // Checks if file exists.
    final String fileName = info.getFileName();
    File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    if (!dir.mkdir() && !dir.isDirectory()) return false;
    String dirName = dir.getName();
    final File file = new File(dir, info.getFileName());
    String fullDirPath = file.getParent();
    if (!file.exists()) return false;
    if (TextUtils.isEmpty(fileName)
        || TextUtils.isEmpty(dirName)
        || TextUtils.isEmpty(fullDirPath)) {
      return false;
    }

    nativeLaunchDownloadOverwriteInfoBar(
        this, mTab, info, info.getFileName(), dirName, fullDirPath);
    return true;
  }
  /**
   * Request user confirmation on a dangerous download.
   *
   * @param downloadInfo Information about the download.
   */
  private void confirmDangerousDownload(DownloadInfo downloadInfo) {
    // A Dangerous file is already pending user confirmation, ignore the new download.
    if (mPendingRequest != null) return;

    mPendingRequest = downloadInfo;

    // TODO(dfalcantara): Ask ainslie@ for an icon to use for this InfoBar.
    int drawableId = 0;
    final String titleText = nativeGetDownloadWarningText(mPendingRequest.getFileName());
    final String okButtonText = mContext.getResources().getString(R.string.ok);
    final String cancelButtonText = mContext.getResources().getString(R.string.cancel);

    mTab.getInfoBarContainer()
        .addInfoBar(
            new ConfirmInfoBar(
                this, drawableId, null, titleText, null, okButtonText, cancelButtonText));
  }
  /**
   * Notify the host application a download should be done, even if there is a streaming viewer
   * available for this type.
   *
   * @param downloadInfo Information about the download.
   */
  protected void onDownloadStartNoStream(DownloadInfo downloadInfo) {
    final String newMimeType =
        remapGenericMimeType(
            downloadInfo.getMimeType(), downloadInfo.getUrl(), downloadInfo.getFileName());
    final String path =
        TextUtils.isEmpty(downloadInfo.getFileName())
            ? fileName(downloadInfo.getUrl(), newMimeType, downloadInfo.getContentDisposition())
            : downloadInfo.getFileName();
    final File file = new File(path);
    final String fileName = file.getName();

    if (!checkExternalStorageAndNotify(downloadPath(fileName))) {
      return;
    }
    String url = sanitizeDownloadUrl(downloadInfo);
    if (url == null) return;
    DownloadInfo newInfo =
        DownloadInfo.Builder.fromDownloadInfo(downloadInfo)
            .setUrl(url)
            .setMimeType(newMimeType)
            .setDescription(url)
            .setFileName(fileName)
            .setIsGETRequest(true)
            .build();

    // TODO(acleung): This is a temp fix to disable auto downloading if flash files.
    // We want to avoid downloading flash files when it is linked as an iframe.
    // The proper fix would be to let chrome knows which frame originated the request.
    if ("application/x-shockwave-flash".equals(newInfo.getMimeType())) return;

    if (isDangerousFile(fileName, newMimeType)) {
      confirmDangerousDownload(newInfo);
    } else {
      // Not a dangerous file, proceed.
      enqueueDownloadManagerRequest(newInfo);
    }
  }
 private void launchDownloadInfoBar(DownloadInfo info, String dirName, String fullDirPath) {
   if (mTab == null) return;
   nativeLaunchDownloadOverwriteInfoBar(
       ChromeDownloadDelegate.this, mTab, info, info.getFileName(), dirName, fullDirPath);
 }
 /**
  * Sanitize the URL for the download item.
  *
  * @param downloadInfo Information about the download.
  */
 protected String sanitizeDownloadUrl(DownloadInfo downloadInfo) {
   return downloadInfo.getUrl();
 }