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/open_file_operation.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/task_runner_util.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "components/drive/drive.pb.h"
15 #include "components/drive/file_cache.h"
16 #include "components/drive/file_errors.h"
17 #include "components/drive/file_system/create_file_operation.h"
18 #include "components/drive/file_system/download_operation.h"
19 #include "components/drive/file_system/operation_delegate.h"
20 #include "components/drive/job_scheduler.h"
23 namespace file_system
{
25 OpenFileOperation::OpenFileOperation(
26 base::SequencedTaskRunner
* blocking_task_runner
,
27 OperationDelegate
* delegate
,
28 JobScheduler
* scheduler
,
29 internal::ResourceMetadata
* metadata
,
30 internal::FileCache
* cache
,
31 const base::FilePath
& temporary_file_directory
)
32 : blocking_task_runner_(blocking_task_runner
),
35 create_file_operation_(new CreateFileOperation(
36 blocking_task_runner
, delegate
, metadata
)),
37 download_operation_(new DownloadOperation(
38 blocking_task_runner
, delegate
, scheduler
,
39 metadata
, cache
, temporary_file_directory
)),
40 weak_ptr_factory_(this) {
43 OpenFileOperation::~OpenFileOperation() {
46 void OpenFileOperation::OpenFile(const base::FilePath
& file_path
,
48 const std::string
& mime_type
,
49 const OpenFileCallback
& callback
) {
50 DCHECK(thread_checker_
.CalledOnValidThread());
51 DCHECK(!callback
.is_null());
55 // It is not necessary to create a new file even if not exists.
56 // So call OpenFileAfterCreateFile directly with FILE_ERROR_OK
57 // to skip file creation.
58 OpenFileAfterCreateFile(file_path
, callback
, FILE_ERROR_OK
);
61 create_file_operation_
->CreateFile(
63 true, // exclusive: fail if already exists
65 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile
,
66 weak_ptr_factory_
.GetWeakPtr(), file_path
, callback
));
68 case OPEN_OR_CREATE_FILE
:
69 create_file_operation_
->CreateFile(
71 false, // not-exclusive
73 base::Bind(&OpenFileOperation::OpenFileAfterCreateFile
,
74 weak_ptr_factory_
.GetWeakPtr(), file_path
, callback
));
79 void OpenFileOperation::OpenFileAfterCreateFile(
80 const base::FilePath
& file_path
,
81 const OpenFileCallback
& callback
,
83 DCHECK(thread_checker_
.CalledOnValidThread());
84 DCHECK(!callback
.is_null());
86 if (error
!= FILE_ERROR_OK
) {
87 callback
.Run(error
, base::FilePath(), base::Closure());
91 download_operation_
->EnsureFileDownloadedByPath(
93 ClientContext(USER_INITIATED
),
94 GetFileContentInitializedCallback(),
95 google_apis::GetContentCallback(),
97 &OpenFileOperation::OpenFileAfterFileDownloaded
,
98 weak_ptr_factory_
.GetWeakPtr(), callback
));
101 void OpenFileOperation::OpenFileAfterFileDownloaded(
102 const OpenFileCallback
& callback
,
104 const base::FilePath
& local_file_path
,
105 scoped_ptr
<ResourceEntry
> entry
) {
106 DCHECK(thread_checker_
.CalledOnValidThread());
107 DCHECK(!callback
.is_null());
109 if (error
== FILE_ERROR_OK
) {
111 DCHECK(entry
->has_file_specific_info());
112 if (entry
->file_specific_info().is_hosted_document())
113 // No support for opening a hosted document.
114 error
= FILE_ERROR_INVALID_OPERATION
;
117 if (error
!= FILE_ERROR_OK
) {
118 callback
.Run(error
, base::FilePath(), base::Closure());
122 scoped_ptr
<base::ScopedClosureRunner
>* file_closer
=
123 new scoped_ptr
<base::ScopedClosureRunner
>;
124 base::PostTaskAndReplyWithResult(
125 blocking_task_runner_
.get(),
127 base::Bind(&internal::FileCache::OpenForWrite
,
128 base::Unretained(cache_
),
131 base::Bind(&OpenFileOperation::OpenFileAfterOpenForWrite
,
132 weak_ptr_factory_
.GetWeakPtr(),
136 base::Owned(file_closer
)));
139 void OpenFileOperation::OpenFileAfterOpenForWrite(
140 const base::FilePath
& local_file_path
,
141 const std::string
& local_id
,
142 const OpenFileCallback
& callback
,
143 scoped_ptr
<base::ScopedClosureRunner
>* file_closer
,
145 DCHECK(thread_checker_
.CalledOnValidThread());
146 DCHECK(!callback
.is_null());
148 if (error
!= FILE_ERROR_OK
) {
149 callback
.Run(error
, base::FilePath(), base::Closure());
153 ++open_files_
[local_id
];
154 callback
.Run(error
, local_file_path
,
155 base::Bind(&OpenFileOperation::CloseFile
,
156 weak_ptr_factory_
.GetWeakPtr(),
158 base::Passed(file_closer
)));
161 void OpenFileOperation::CloseFile(
162 const std::string
& local_id
,
163 scoped_ptr
<base::ScopedClosureRunner
> file_closer
) {
164 DCHECK(thread_checker_
.CalledOnValidThread());
165 DCHECK_GT(open_files_
[local_id
], 0);
167 if (--open_files_
[local_id
] == 0) {
168 // All clients closes this file, so notify to upload the file.
169 open_files_
.erase(local_id
);
170 delegate_
->OnEntryUpdatedByOperation(ClientContext(USER_INITIATED
),
173 // Clients may have enlarged the file. By FreeDiskpSpaceIfNeededFor(0),
174 // we try to ensure (0 + the-minimum-safe-margin = 512MB as of now) space.
175 blocking_task_runner_
->PostTask(
177 base::Bind(base::IgnoreResult(
178 base::Bind(&internal::FileCache::FreeDiskSpaceIfNeededFor
,
179 base::Unretained(cache_
),
184 } // namespace file_system