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/get_file_for_saving_operation.h"
8 #include "base/bind_helpers.h"
9 #include "chrome/browser/chromeos/drive/file_cache.h"
10 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
11 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
12 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
13 #include "chrome/browser/chromeos/drive/file_write_watcher.h"
14 #include "content/public/browser/browser_thread.h"
16 using content::BrowserThread;
19 namespace file_system {
23 // Marks the cache entry as dirty.
24 FileError MarkDirty(internal::ResourceMetadata* metadata,
25 internal::FileCache* cache,
26 const std::string& resource_id,
27 std::string* local_id) {
28 FileError error = metadata->GetIdByResourceId(resource_id, local_id);
29 if (error != FILE_ERROR_OK)
31 return cache->MarkDirty(*local_id);
36 GetFileForSavingOperation::GetFileForSavingOperation(
37 base::SequencedTaskRunner* blocking_task_runner,
38 OperationObserver* observer,
39 JobScheduler* scheduler,
40 internal::ResourceMetadata* metadata,
41 internal::FileCache* cache,
42 const base::FilePath& temporary_file_directory)
43 : create_file_operation_(new CreateFileOperation(blocking_task_runner,
48 download_operation_(new DownloadOperation(blocking_task_runner,
53 temporary_file_directory)),
54 file_write_watcher_(new internal::FileWriteWatcher),
55 blocking_task_runner_(blocking_task_runner),
59 weak_ptr_factory_(this) {
62 GetFileForSavingOperation::~GetFileForSavingOperation() {
65 void GetFileForSavingOperation::GetFileForSaving(
66 const base::FilePath& file_path,
67 const GetFileCallback& callback) {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69 DCHECK(!callback.is_null());
71 create_file_operation_->CreateFile(
73 false, // error_if_already_exists
74 std::string(), // no specific mime type
75 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate,
76 weak_ptr_factory_.GetWeakPtr(),
81 void GetFileForSavingOperation::GetFileForSavingAfterCreate(
82 const base::FilePath& file_path,
83 const GetFileCallback& callback,
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86 DCHECK(!callback.is_null());
88 if (error != FILE_ERROR_OK) {
89 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
93 download_operation_->EnsureFileDownloadedByPath(
95 ClientContext(USER_INITIATED),
96 GetFileContentInitializedCallback(),
97 google_apis::GetContentCallback(),
98 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload,
99 weak_ptr_factory_.GetWeakPtr(),
103 void GetFileForSavingOperation::GetFileForSavingAfterDownload(
104 const GetFileCallback& callback,
106 const base::FilePath& cache_path,
107 scoped_ptr<ResourceEntry> entry) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109 DCHECK(!callback.is_null());
111 if (error != FILE_ERROR_OK) {
112 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
116 const std::string& resource_id = entry->resource_id();
117 std::string* local_id = new std::string;
118 base::PostTaskAndReplyWithResult(
119 blocking_task_runner_.get(),
121 base::Bind(&MarkDirty, metadata_, cache_, resource_id, local_id),
122 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterMarkDirty,
123 weak_ptr_factory_.GetWeakPtr(),
126 base::Owned(local_id),
127 base::Passed(&entry)));
130 void GetFileForSavingOperation::GetFileForSavingAfterMarkDirty(
131 const GetFileCallback& callback,
132 const base::FilePath& cache_path,
133 const std::string* local_id,
134 scoped_ptr<ResourceEntry> entry,
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137 DCHECK(!callback.is_null());
139 if (error != FILE_ERROR_OK) {
140 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
144 file_write_watcher_->StartWatch(
146 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch,
147 weak_ptr_factory_.GetWeakPtr(),
150 base::Passed(&entry)),
151 base::Bind(&GetFileForSavingOperation::OnWriteEvent,
152 weak_ptr_factory_.GetWeakPtr(),
156 void GetFileForSavingOperation::GetFileForSavingAfterWatch(
157 const GetFileCallback& callback,
158 const base::FilePath& cache_path,
159 scoped_ptr<ResourceEntry> entry,
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
162 DCHECK(!callback.is_null());
165 callback.Run(FILE_ERROR_FAILED,
166 base::FilePath(), scoped_ptr<ResourceEntry>());
170 callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
173 void GetFileForSavingOperation::OnWriteEvent(const std::string& local_id) {
174 observer_->OnCacheFileUploadNeededByOperation(local_id);
176 // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
177 // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
178 blocking_task_runner_->PostTask(
180 base::Bind(base::IgnoreResult(
181 base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor,
182 base::Unretained(cache_),
186 } // namespace file_system