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"
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"
19 namespace file_system
{
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
)
32 return metadata
->GetResourceEntryById(local_id
, entry
);
37 GetFileForSavingOperation::GetFileForSavingOperation(
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
)
47 create_file_operation_(
48 new CreateFileOperation(blocking_task_runner
, delegate
, metadata
)),
49 download_operation_(new DownloadOperation(blocking_task_runner
,
54 temporary_file_directory
)),
55 file_write_watcher_(new internal::FileWriteWatcher(file_task_runner
)),
56 blocking_task_runner_(blocking_task_runner
),
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(
74 false, // error_if_already_exists
75 std::string(), // no specific mime type
76 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate
,
77 weak_ptr_factory_
.GetWeakPtr(),
82 void GetFileForSavingOperation::GetFileForSavingAfterCreate(
83 const base::FilePath
& file_path
,
84 const GetFileCallback
& callback
,
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
>());
94 download_operation_
->EnsureFileDownloadedByPath(
96 ClientContext(USER_INITIATED
),
97 GetFileContentInitializedCallback(),
98 google_apis::GetContentCallback(),
99 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload
,
100 weak_ptr_factory_
.GetWeakPtr(),
104 void GetFileForSavingOperation::GetFileForSavingAfterDownload(
105 const GetFileCallback
& callback
,
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
>());
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(),
124 base::Bind(&OpenCacheFileForWrite
,
130 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite
,
131 weak_ptr_factory_
.GetWeakPtr(),
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
,
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
>());
152 const std::string
& local_id
= entry
->local_id();
153 file_write_watcher_
->StartWatch(
155 base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch
,
156 weak_ptr_factory_
.GetWeakPtr(),
159 base::Passed(&entry
)),
160 base::Bind(&GetFileForSavingOperation::OnWriteEvent
,
161 weak_ptr_factory_
.GetWeakPtr(),
163 base::Passed(file_closer
)));
166 void GetFileForSavingOperation::GetFileForSavingAfterWatch(
167 const GetFileCallback
& callback
,
168 const base::FilePath
& cache_path
,
169 scoped_ptr
<ResourceEntry
> entry
,
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");
179 callback
.Run(FILE_ERROR_FAILED
,
180 base::FilePath(), scoped_ptr
<ResourceEntry
>());
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.",
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(
199 base::Bind(base::IgnoreResult(
200 base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor
,
201 base::Unretained(cache_
),
205 } // namespace file_system