1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/callback_helpers.h" 10 #include "base/files/file_path.h" 11 #include "base/logging.h" 12 #include "base/message_loop/message_loop_proxy.h" 13 #include "base/task_runner_util.h" 14 #include "chrome/browser/chromeos/drive/drive.pb.h" 15 #include "chrome/browser/chromeos/drive/file_cache.h" 16 #include "chrome/browser/chromeos/drive/file_errors.h" 17 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h" 18 #include "chrome/browser/chromeos/drive/file_system/download_operation.h" 19 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h" 20 #include "chrome/browser/chromeos/drive/job_scheduler.h" 21 #include "content/public/browser/browser_thread.h" 22 23 using content::BrowserThread; 24 25 namespace drive { 26 namespace file_system { 27 28 OpenFileOperation::OpenFileOperation( 29 base::SequencedTaskRunner* blocking_task_runner, 30 OperationObserver* observer, 31 JobScheduler* scheduler, 32 internal::ResourceMetadata* metadata, 33 internal::FileCache* cache, 34 const base::FilePath& temporary_file_directory) 35 : blocking_task_runner_(blocking_task_runner), 36 observer_(observer), 37 cache_(cache), 38 create_file_operation_(new CreateFileOperation( 39 blocking_task_runner, observer, metadata)), 40 download_operation_(new DownloadOperation( 41 blocking_task_runner, observer, scheduler, 42 metadata, cache, temporary_file_directory)), 43 weak_ptr_factory_(this) { 44 } 45 46 OpenFileOperation::~OpenFileOperation() { 47 } 48 49 void OpenFileOperation::OpenFile(const base::FilePath& file_path, 50 OpenMode open_mode, 51 const std::string& mime_type, 52 const OpenFileCallback& callback) { 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 54 DCHECK(!callback.is_null()); 55 56 switch (open_mode) { 57 case OPEN_FILE: 58 // It is not necessary to create a new file even if not exists. 59 // So call OpenFileAfterCreateFile directly with FILE_ERROR_OK 60 // to skip file creation. 61 OpenFileAfterCreateFile(file_path, callback, FILE_ERROR_OK); 62 break; 63 case CREATE_FILE: 64 create_file_operation_->CreateFile( 65 file_path, 66 true, // exclusive: fail if already exists 67 mime_type, 68 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile, 69 weak_ptr_factory_.GetWeakPtr(), file_path, callback)); 70 break; 71 case OPEN_OR_CREATE_FILE: 72 create_file_operation_->CreateFile( 73 file_path, 74 false, // not-exclusive 75 mime_type, 76 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile, 77 weak_ptr_factory_.GetWeakPtr(), file_path, callback)); 78 break; 79 } 80 } 81 82 void OpenFileOperation::OpenFileAfterCreateFile( 83 const base::FilePath& file_path, 84 const OpenFileCallback& callback, 85 FileError error) { 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 87 DCHECK(!callback.is_null()); 88 89 if (error != FILE_ERROR_OK) { 90 callback.Run(error, base::FilePath(), base::Closure()); 91 return; 92 } 93 94 download_operation_->EnsureFileDownloadedByPath( 95 file_path, 96 ClientContext(USER_INITIATED), 97 GetFileContentInitializedCallback(), 98 google_apis::GetContentCallback(), 99 base::Bind( 100 &OpenFileOperation::OpenFileAfterFileDownloaded, 101 weak_ptr_factory_.GetWeakPtr(), callback)); 102 } 103 104 void OpenFileOperation::OpenFileAfterFileDownloaded( 105 const OpenFileCallback& callback, 106 FileError error, 107 const base::FilePath& local_file_path, 108 scoped_ptr<ResourceEntry> entry) { 109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 110 DCHECK(!callback.is_null()); 111 112 if (error == FILE_ERROR_OK) { 113 DCHECK(entry); 114 DCHECK(entry->has_file_specific_info()); 115 if (entry->file_specific_info().is_hosted_document()) 116 // No support for opening a hosted document. 117 error = FILE_ERROR_INVALID_OPERATION; 118 } 119 120 if (error != FILE_ERROR_OK) { 121 callback.Run(error, base::FilePath(), base::Closure()); 122 return; 123 } 124 125 scoped_ptr<base::ScopedClosureRunner>* file_closer = 126 new scoped_ptr<base::ScopedClosureRunner>; 127 base::PostTaskAndReplyWithResult( 128 blocking_task_runner_.get(), 129 FROM_HERE, 130 base::Bind(&internal::FileCache::OpenForWrite, 131 base::Unretained(cache_), 132 entry->local_id(), 133 file_closer), 134 base::Bind(&OpenFileOperation::OpenFileAfterOpenForWrite, 135 weak_ptr_factory_.GetWeakPtr(), 136 local_file_path, 137 entry->local_id(), 138 callback, 139 base::Owned(file_closer))); 140 } 141 142 void OpenFileOperation::OpenFileAfterOpenForWrite( 143 const base::FilePath& local_file_path, 144 const std::string& local_id, 145 const OpenFileCallback& callback, 146 scoped_ptr<base::ScopedClosureRunner>* file_closer, 147 FileError error) { 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 149 DCHECK(!callback.is_null()); 150 151 if (error != FILE_ERROR_OK) { 152 callback.Run(error, base::FilePath(), base::Closure()); 153 return; 154 } 155 156 ++open_files_[local_id]; 157 callback.Run(error, local_file_path, 158 base::Bind(&OpenFileOperation::CloseFile, 159 weak_ptr_factory_.GetWeakPtr(), 160 local_id, 161 base::Passed(file_closer))); 162 } 163 164 void OpenFileOperation::CloseFile( 165 const std::string& local_id, 166 scoped_ptr<base::ScopedClosureRunner> file_closer) { 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 168 DCHECK_GT(open_files_[local_id], 0); 169 170 if (--open_files_[local_id] == 0) { 171 // All clients closes this file, so notify to upload the file. 172 open_files_.erase(local_id); 173 observer_->OnEntryUpdatedByOperation(local_id); 174 175 // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0), 176 // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space. 177 blocking_task_runner_->PostTask( 178 FROM_HERE, 179 base::Bind(base::IgnoreResult( 180 base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor, 181 base::Unretained(cache_), 182 0)))); 183 } 184 } 185 186 } // namespace file_system 187 } // namespace drive 188