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.
5 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/task_runner_util.h"
13 #include "chrome/browser/chromeos/drive/drive.pb.h"
14 #include "chrome/browser/chromeos/drive/file_cache.h"
15 #include "chrome/browser/chromeos/drive/file_errors.h"
16 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
17 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
18 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
19 #include "chrome/browser/chromeos/drive/file_system_interface.h"
20 #include "content/public/browser/browser_thread.h"
22 using content::BrowserThread;
25 namespace file_system {
27 OpenFileOperation::OpenFileOperation(
28 base::SequencedTaskRunner* blocking_task_runner,
29 OperationObserver* observer,
30 JobScheduler* scheduler,
31 internal::ResourceMetadata* metadata,
32 internal::FileCache* cache,
33 const base::FilePath& temporary_file_directory)
34 : blocking_task_runner_(blocking_task_runner),
37 create_file_operation_(new CreateFileOperation(
38 blocking_task_runner, observer, scheduler, metadata, cache)),
39 download_operation_(new DownloadOperation(
40 blocking_task_runner, observer, scheduler,
41 metadata, cache, temporary_file_directory)),
42 weak_ptr_factory_(this) {
45 OpenFileOperation::~OpenFileOperation() {
48 void OpenFileOperation::OpenFile(const base::FilePath& file_path,
50 const std::string& mime_type,
51 const OpenFileCallback& callback) {
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
53 DCHECK(!callback.is_null());
57 // It is not necessary to create a new file even if not exists.
58 // So call OpenFileAfterCreateFile directly with FILE_ERROR_OK
59 // to skip file creation.
60 OpenFileAfterCreateFile(file_path, callback, FILE_ERROR_OK);
63 create_file_operation_->CreateFile(
65 true, // exclusive: fail if already exists
67 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile,
68 weak_ptr_factory_.GetWeakPtr(), file_path, callback));
70 case OPEN_OR_CREATE_FILE:
71 create_file_operation_->CreateFile(
73 false, // not-exclusive
75 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile,
76 weak_ptr_factory_.GetWeakPtr(), file_path, callback));
81 void OpenFileOperation::OpenFileAfterCreateFile(
82 const base::FilePath& file_path,
83 const OpenFileCallback& callback,
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86 DCHECK(!callback.is_null());
88 if (error != FILE_ERROR_OK) {
89 callback.Run(error, base::FilePath(), base::Closure());
93 download_operation_->EnsureFileDownloadedByPath(
95 ClientContext(USER_INITIATED),
96 GetFileContentInitializedCallback(),
97 google_apis::GetContentCallback(),
99 &OpenFileOperation::OpenFileAfterFileDownloaded,
100 weak_ptr_factory_.GetWeakPtr(), callback));
103 void OpenFileOperation::OpenFileAfterFileDownloaded(
104 const OpenFileCallback& callback,
106 const base::FilePath& local_file_path,
107 scoped_ptr<ResourceEntry> entry) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109 DCHECK(!callback.is_null());
111 if (error == FILE_ERROR_OK) {
113 DCHECK(entry->has_file_specific_info());
114 if (entry->file_specific_info().is_hosted_document())
115 // No support for opening a hosted document.
116 error = FILE_ERROR_INVALID_OPERATION;
119 if (error != FILE_ERROR_OK) {
120 callback.Run(error, base::FilePath(), base::Closure());
124 base::PostTaskAndReplyWithResult(
125 blocking_task_runner_.get(),
127 base::Bind(&internal::FileCache::MarkDirty,
128 base::Unretained(cache_),
130 base::Bind(&OpenFileOperation::OpenFileAfterMarkDirty,
131 weak_ptr_factory_.GetWeakPtr(),
137 void OpenFileOperation::OpenFileAfterMarkDirty(
138 const base::FilePath& local_file_path,
139 const std::string& local_id,
140 const OpenFileCallback& callback,
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 DCHECK(!callback.is_null());
145 if (error != FILE_ERROR_OK) {
146 callback.Run(error, base::FilePath(), base::Closure());
150 ++open_files_[local_id];
151 callback.Run(error, local_file_path,
152 base::Bind(&OpenFileOperation::CloseFile,
153 weak_ptr_factory_.GetWeakPtr(), local_id));
156 void OpenFileOperation::CloseFile(const std::string& local_id) {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
158 DCHECK_GT(open_files_[local_id], 0);
160 if (--open_files_[local_id] == 0) {
161 // All clients closes this file, so notify to upload the file.
162 open_files_.erase(local_id);
163 observer_->OnCacheFileUploadNeededByOperation(local_id);
165 // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
166 // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
167 blocking_task_runner_->PostTask(
169 base::Bind(base::IgnoreResult(
170 base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor,
171 base::Unretained(cache_),
176 } // namespace file_system