BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / components / drive / file_system / get_file_for_saving_operation.cc
blob30aefd69d372d64a6fb67c0b9cc8e1fb0951e75a
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 "components/drive/file_system/get_file_for_saving_operation.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h"
10 #include "components/drive/event_logger.h"
11 #include "components/drive/file_cache.h"
12 #include "components/drive/file_system/create_file_operation.h"
13 #include "components/drive/file_system/download_operation.h"
14 #include "components/drive/file_system/operation_delegate.h"
15 #include "components/drive/file_write_watcher.h"
16 #include "components/drive/job_scheduler.h"
18 namespace drive {
19 namespace file_system {
21 namespace {
23 FileError OpenCacheFileForWrite(
24 internal::ResourceMetadata* metadata,
25 internal::FileCache* cache,
26 const std::string& local_id,
27 scoped_ptr<base::ScopedClosureRunner>* file_closer,
28 ResourceEntry* entry) {
29 FileError error = cache->OpenForWrite(local_id, file_closer);
30 if (error != FILE_ERROR_OK)
31 return error;
32 return metadata->GetResourceEntryById(local_id, entry);
35 } // namespace
37 GetFileForSavingOperation::GetFileForSavingOperation(
38 EventLogger* logger,
39 base::SequencedTaskRunner* blocking_task_runner,
40 base::SingleThreadTaskRunner* file_task_runner,
41 OperationDelegate* delegate,
42 JobScheduler* scheduler,
43 internal::ResourceMetadata* metadata,
44 internal::FileCache* cache,
45 const base::FilePath& temporary_file_directory)
46 : logger_(logger),
47 create_file_operation_(
48 new CreateFileOperation(blocking_task_runner, delegate, metadata)),
49 download_operation_(new DownloadOperation(blocking_task_runner,
50 delegate,
51 scheduler,
52 metadata,
53 cache,
54 temporary_file_directory)),
55 file_write_watcher_(new internal::FileWriteWatcher(file_task_runner)),
56 blocking_task_runner_(blocking_task_runner),
57 delegate_(delegate),
58 metadata_(metadata),
59 cache_(cache),
60 weak_ptr_factory_(this) {
63 GetFileForSavingOperation::~GetFileForSavingOperation() {
66 void GetFileForSavingOperation::GetFileForSaving(
67 const base::FilePath& file_path,
68 const GetFileCallback& callback) {
69 DCHECK(thread_checker_.CalledOnValidThread());
70 DCHECK(!callback.is_null());
72 create_file_operation_->CreateFile(
73 file_path,
74 false, // error_if_already_exists
75 std::string(), // no specific mime type
76 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate,
77 weak_ptr_factory_.GetWeakPtr(),
78 file_path,
79 callback));
82 void GetFileForSavingOperation::GetFileForSavingAfterCreate(
83 const base::FilePath& file_path,
84 const GetFileCallback& callback,
85 FileError error) {
86 DCHECK(thread_checker_.CalledOnValidThread());
87 DCHECK(!callback.is_null());
89 if (error != FILE_ERROR_OK) {
90 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
91 return;
94 download_operation_->EnsureFileDownloadedByPath(
95 file_path,
96 ClientContext(USER_INITIATED),
97 GetFileContentInitializedCallback(),
98 google_apis::GetContentCallback(),
99 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload,
100 weak_ptr_factory_.GetWeakPtr(),
101 callback));
104 void GetFileForSavingOperation::GetFileForSavingAfterDownload(
105 const GetFileCallback& callback,
106 FileError error,
107 const base::FilePath& cache_path,
108 scoped_ptr<ResourceEntry> entry) {
109 DCHECK(thread_checker_.CalledOnValidThread());
110 DCHECK(!callback.is_null());
112 if (error != FILE_ERROR_OK) {
113 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
114 return;
117 const std::string& local_id = entry->local_id();
118 ResourceEntry* entry_ptr = entry.get();
119 scoped_ptr<base::ScopedClosureRunner>* file_closer =
120 new scoped_ptr<base::ScopedClosureRunner>;
121 base::PostTaskAndReplyWithResult(
122 blocking_task_runner_.get(),
123 FROM_HERE,
124 base::Bind(&OpenCacheFileForWrite,
125 metadata_,
126 cache_,
127 local_id,
128 file_closer,
129 entry_ptr),
130 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite,
131 weak_ptr_factory_.GetWeakPtr(),
132 callback,
133 cache_path,
134 base::Passed(&entry),
135 base::Owned(file_closer)));
138 void GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite(
139 const GetFileCallback& callback,
140 const base::FilePath& cache_path,
141 scoped_ptr<ResourceEntry> entry,
142 scoped_ptr<base::ScopedClosureRunner>* file_closer,
143 FileError error) {
144 DCHECK(thread_checker_.CalledOnValidThread());
145 DCHECK(!callback.is_null());
147 if (error != FILE_ERROR_OK) {
148 callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
149 return;
152 const std::string& local_id = entry->local_id();
153 file_write_watcher_->StartWatch(
154 cache_path,
155 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch,
156 weak_ptr_factory_.GetWeakPtr(),
157 callback,
158 cache_path,
159 base::Passed(&entry)),
160 base::Bind(&GetFileForSavingOperation::OnWriteEvent,
161 weak_ptr_factory_.GetWeakPtr(),
162 local_id,
163 base::Passed(file_closer)));
166 void GetFileForSavingOperation::GetFileForSavingAfterWatch(
167 const GetFileCallback& callback,
168 const base::FilePath& cache_path,
169 scoped_ptr<ResourceEntry> entry,
170 bool success) {
171 DCHECK(thread_checker_.CalledOnValidThread());
172 DCHECK(!callback.is_null());
174 logger_->Log(logging::LOG_INFO, "Started watching modification to %s [%s].",
175 entry->local_id().c_str(),
176 success ? "ok" : "fail");
178 if (!success) {
179 callback.Run(FILE_ERROR_FAILED,
180 base::FilePath(), scoped_ptr<ResourceEntry>());
181 return;
184 callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
187 void GetFileForSavingOperation::OnWriteEvent(
188 const std::string& local_id,
189 scoped_ptr<base::ScopedClosureRunner> file_closer) {
190 logger_->Log(logging::LOG_INFO, "Detected modification to %s.",
191 local_id.c_str());
193 delegate_->OnEntryUpdatedByOperation(ClientContext(USER_INITIATED), local_id);
195 // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
196 // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
197 blocking_task_runner_->PostTask(
198 FROM_HERE,
199 base::Bind(base::IgnoreResult(
200 base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor,
201 base::Unretained(cache_),
202 0))));
205 } // namespace file_system
206 } // namespace drive