download_handler.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/download_handler.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/supports_user_data.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/drive/drive.pb.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/drive/drive_integration_service.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_interface.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/chromeos/drive/write_on_cache_file.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/download/download_history.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/download/download_service.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/download/download_service_factory.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::DownloadManager;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::DownloadItem;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace drive {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Key for base::SupportsUserData::Data.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDrivePathKey[] = "DrivePath";
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// User Data stored in DownloadItem for drive path.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DriveUserData : public base::SupportsUserData::Data {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DriveUserData(const base::FilePath& path) : file_path_(path),
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                       is_complete_(false) {}
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DriveUserData() {}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath& file_path() const { return file_path_; }
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const base::FilePath& cache_file_path() const { return cache_file_path_; }
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void set_cache_file_path(const base::FilePath& path) {
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache_file_path_ = path;
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_complete() const { return is_complete_; }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_complete() { is_complete_ = true; }
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath file_path_;
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::FilePath cache_file_path_;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_complete_;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Extracts DriveUserData* from |download|.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const DriveUserData* GetDriveUserData(const DownloadItem* download) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<const DriveUserData*>(
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download->GetUserData(&kDrivePathKey));
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DriveUserData* GetDriveUserData(DownloadItem* download) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<DriveUserData*>(download->GetUserData(&kDrivePathKey));
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Creates a temporary file |drive_tmp_download_path| in
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |drive_tmp_download_dir|. Must be called on a thread that allows file
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// operations.
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetDriveTempDownloadPath(
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& drive_tmp_download_dir) {
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool created = base::CreateDirectory(drive_tmp_download_dir);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(created) << "Can not create temp download directory at "
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << drive_tmp_download_dir.value();
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath drive_tmp_download_path;
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  created = base::CreateTemporaryFileInDir(drive_tmp_download_dir,
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                           &drive_tmp_download_path);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(created) << "Temporary download file creation failed";
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return drive_tmp_download_path;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Moves downloaded file to Drive.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MoveDownloadedFile(const base::FilePath& downloaded_file,
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        base::FilePath* cache_file_path,
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        FileError error,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        const base::FilePath& dest_path) {
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (error != FILE_ERROR_OK ||
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !base::Move(downloaded_file, dest_path))
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  *cache_file_path = dest_path;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to implement CheckForFileExistence().
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ContinueCheckingForFileExistence(
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::CheckForFileExistenceCallback& callback,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileError error,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ResourceEntry> entry) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(error == FILE_ERROR_OK);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if |download| is a Drive download created from data persisted
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// on the download history DB.
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsPersistedDriveDownload(const base::FilePath& drive_tmp_download_path,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              DownloadItem* download) {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!drive_tmp_download_path.IsParent(download->GetTargetFilePath()))
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DownloadService* download_service =
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DownloadServiceFactory::GetForBrowserContext(
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          download->GetBrowserContext());
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DownloadHistory* download_history = download_service->GetDownloadHistory();
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return download_history && download_history->WasRestoredFromHistory(download);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)DownloadHandler::DownloadHandler(FileSystemInterface* file_system)
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : file_system_(file_system),
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DownloadHandler::~DownloadHandler() {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DownloadHandler* DownloadHandler::GetForProfile(Profile* profile) {
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DriveIntegrationService* service =
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DriveIntegrationServiceFactory::FindForProfile(profile);
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!service || !service->IsMounted())
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return NULL;
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return service->download_handler();
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::Initialize(
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DownloadManager* download_manager,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& drive_tmp_download_path) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!drive_tmp_download_path.empty());
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drive_tmp_download_path_ = drive_tmp_download_path;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (download_manager) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    notifier_.reset(new AllDownloadItemNotifier(download_manager, this));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove any persisted Drive DownloadItem. crbug.com/171384
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::DownloadManager::DownloadVector downloads;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    download_manager->GetAllDownloads(&downloads);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < downloads.size(); ++i) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (IsPersistedDriveDownload(drive_tmp_download_path_, downloads[i]))
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        RemoveDownload(downloads[i]->GetId());
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::SubstituteDriveDownloadPath(
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& drive_path,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::DownloadItem* download,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SubstituteDriveDownloadPathCallback& callback) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "SubstituteDriveDownloadPath " << drive_path.value();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetDownloadParams(drive_path, download);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (util::IsUnderDriveMountPoint(drive_path)) {
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Prepare the destination directory.
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const bool is_exclusive = false, is_recursive = true;
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    file_system_->CreateDirectory(
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        util::ExtractDrivePath(drive_path.DirName()),
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        is_exclusive, is_recursive,
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&DownloadHandler::OnCreateDirectory,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   callback));
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(drive_path);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::SetDownloadParams(const base::FilePath& drive_path,
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        DownloadItem* download) {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (util::IsUnderDriveMountPoint(drive_path)) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    download->SetUserData(&kDrivePathKey, new DriveUserData(drive_path));
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    download->SetDisplayName(drive_path.BaseName());
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (IsDriveDownload(download)) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This may have been previously set if the default download folder is
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // /drive, and the user has now changed the download target to a local
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // folder.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    download->SetUserData(&kDrivePathKey, NULL);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    download->SetDisplayName(base::FilePath());
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath DownloadHandler::GetTargetPath(
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DownloadItem* download) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const DriveUserData* data = GetDriveUserData(download);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If data is NULL, we've somehow lost the drive path selected by the file
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // picker.
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(data);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data ? data->file_path() : base::FilePath();
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::FilePath DownloadHandler::GetCacheFilePath(const DownloadItem* download) {
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const DriveUserData* data = GetDriveUserData(download);
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return data ? data->cache_file_path() : base::FilePath();
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DownloadHandler::IsDriveDownload(const DownloadItem* download) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We use the existence of the DriveUserData object in download as a
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // signal that this is a download to Drive.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetDriveUserData(download) != NULL;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::CheckForFileExistence(
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DownloadItem* download,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::CheckForFileExistenceCallback& callback) {
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_system_->GetResourceEntry(
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      util::ExtractDrivePath(GetTargetPath(download)),
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ContinueCheckingForFileExistence,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::OnDownloadCreated(DownloadManager* manager,
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        DownloadItem* download) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Remove any persisted Drive DownloadItem. crbug.com/171384
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsPersistedDriveDownload(drive_tmp_download_path_, download)) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove download later, since doing it here results in a crash.
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::UI,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            FROM_HERE,
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            base::Bind(&DownloadHandler::RemoveDownload,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       weak_ptr_factory_.GetWeakPtr(),
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       download->GetId()));
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::RemoveDownload(int id) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadManager* manager = notifier_->GetManager();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!manager)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download = manager->GetDownload(id);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!download)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  download->Remove();
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::OnDownloadUpdated(
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DownloadManager* manager, DownloadItem* download) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only accept downloads that have the Drive meta data associated with them.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DriveUserData* data = GetDriveUserData(download);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!drive_tmp_download_path_.IsParent(download->GetTargetFilePath()) ||
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !data ||
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data->is_complete())
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (download->GetState()) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case DownloadItem::IN_PROGRESS:
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case DownloadItem::COMPLETE:
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UploadDownloadItem(download);
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data->set_complete();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case DownloadItem::CANCELLED:
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download->SetUserData(&kDrivePathKey, NULL);
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DownloadItem::INTERRUPTED:
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Interrupted downloads can be resumed. Keep the Drive user data around
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // so that it can be used when the download resumes. The download is truly
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // done when it's complete, is cancelled or is removed.
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::OnCreateDirectory(
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SubstituteDriveDownloadPathCallback& callback,
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileError error) {
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DVLOG(1) << "OnCreateDirectory " << FileErrorToString(error);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error == FILE_ERROR_OK) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PostTaskAndReplyWithResult(
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::GetBlockingPool(),
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&GetDriveTempDownloadPath, drive_tmp_download_path_),
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        callback);
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Failed to create directory, error = "
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << FileErrorToString(error);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(base::FilePath());
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadHandler::UploadDownloadItem(DownloadItem* download) {
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK_EQ(DownloadItem::COMPLETE, download->GetState());
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::FilePath* cache_file_path = new base::FilePath;
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  WriteOnCacheFileAndReply(
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      file_system_,
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      util::ExtractDrivePath(GetTargetPath(download)),
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      download->GetMimeType(),
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MoveDownloadedFile, download->GetTargetFilePath(),
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 cache_file_path),
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&DownloadHandler::SetCacheFilePath,
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 download->GetId(),
304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Owned(cache_file_path)));
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DownloadHandler::SetCacheFilePath(int id,
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       const base::FilePath* cache_file_path,
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       FileError error) {
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (error != FILE_ERROR_OK)
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DownloadManager* manager = notifier_->GetManager();
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!manager)
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DownloadItem* download = manager->GetDownload(id);
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!download)
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DriveUserData* data = GetDriveUserData(download);
319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!data)
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  data->set_cache_file_path(*cache_file_path);
322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace drive
326