Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(572)

Side by Side Diff: chrome/browser/chromeos/drive/file_system/copy_operation.cc

Issue 149413002: drive: Make CopyOperation aware of locally created files (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix mistakenly called CopyResourceOnServer Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h" 5 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/task_runner_util.h" 10 #include "base/task_runner_util.h"
11 #include "chrome/browser/chromeos/drive/drive.pb.h" 11 #include "chrome/browser/chromeos/drive/drive.pb.h"
12 #include "chrome/browser/chromeos/drive/file_cache.h" 12 #include "chrome/browser/chromeos/drive/file_cache.h"
13 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h" 13 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
14 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h" 14 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h" 15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/drive/job_scheduler.h" 16 #include "chrome/browser/chromeos/drive/job_scheduler.h"
17 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h" 17 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
18 #include "chrome/browser/chromeos/drive/resource_metadata.h" 18 #include "chrome/browser/chromeos/drive/resource_metadata.h"
19 #include "chrome/browser/drive/drive_api_util.h" 19 #include "chrome/browser/drive/drive_api_util.h"
20 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
21 #include "google_apis/drive/drive_api_parser.h" 21 #include "google_apis/drive/drive_api_parser.h"
22 22
23 using content::BrowserThread; 23 using content::BrowserThread;
24 24
25 namespace drive { 25 namespace drive {
26 namespace file_system { 26 namespace file_system {
27 27
28 struct CopyOperation::CopyParams {
29 base::FilePath src_file_path;
30 base::FilePath dest_file_path;
31 bool preserve_last_modified;
32 FileOperationCallback callback;
33 ResourceEntry src_entry;
34 ResourceEntry parent_entry;
35 };
36
28 namespace { 37 namespace {
29 38
30 FileError PrepareCopy(internal::ResourceMetadata* metadata, 39 FileError TryToCopyLocally(internal::ResourceMetadata* metadata,
31 const base::FilePath& src_path, 40 internal::FileCache* cache,
32 const base::FilePath& dest_path, 41 CopyOperation::CopyParams* params,
33 ResourceEntry* src_entry, 42 std::vector<std::string>* updated_local_ids,
34 std::string* parent_resource_id) { 43 bool* directory_changed,
35 FileError error = metadata->GetResourceEntryByPath(src_path, src_entry); 44 bool* should_copy_on_server) {
45 FileError error = metadata->GetResourceEntryByPath(params->src_file_path,
46 &params->src_entry);
36 if (error != FILE_ERROR_OK) 47 if (error != FILE_ERROR_OK)
37 return error; 48 return error;
38 49
39 ResourceEntry parent_entry; 50 error = metadata->GetResourceEntryByPath(params->dest_file_path.DirName(),
40 error = metadata->GetResourceEntryByPath(dest_path.DirName(), &parent_entry); 51 &params->parent_entry);
41 if (error != FILE_ERROR_OK) 52 if (error != FILE_ERROR_OK)
42 return error; 53 return error;
43 54
44 if (!parent_entry.file_info().is_directory()) 55 if (!params->parent_entry.file_info().is_directory())
45 return FILE_ERROR_NOT_A_DIRECTORY; 56 return FILE_ERROR_NOT_A_DIRECTORY;
46 57
47 // Drive File System doesn't support recursive copy. 58 // Drive File System doesn't support recursive copy.
48 if (src_entry->file_info().is_directory()) 59 if (params->src_entry.file_info().is_directory())
49 return FILE_ERROR_NOT_A_FILE; 60 return FILE_ERROR_NOT_A_FILE;
50 61
51 *parent_resource_id = parent_entry.resource_id(); 62 // Check destination.
52 return FILE_ERROR_OK; 63 ResourceEntry dest_entry;
64 error = metadata->GetResourceEntryByPath(params->dest_file_path, &dest_entry);
65 switch (error) {
66 case FILE_ERROR_OK:
67 // File API spec says it is an error to try to "copy a file to a path
68 // occupied by a directory".
69 if (dest_entry.file_info().is_directory())
70 return FILE_ERROR_INVALID_OPERATION;
71
72 // Move the existing entry to the trash.
73 dest_entry.set_parent_local_id(util::kDriveTrashDirLocalId);
74 error = metadata->RefreshEntry(dest_entry);
75 if (error != FILE_ERROR_OK)
76 return error;
77 updated_local_ids->push_back(dest_entry.local_id());
78 *directory_changed = true;
79 break;
80 case FILE_ERROR_NOT_FOUND:
81 break;
82 default:
83 return error;
84 }
85
86 // If the entry exists on the server and the cache file is not dirty,
87 // server side copy can be used.
88 FileCacheEntry cache_entry;
89 cache->GetCacheEntry(params->src_entry.local_id(), &cache_entry);
90 if (!params->src_entry.resource_id().empty() && !cache_entry.is_dirty()) {
91 *should_copy_on_server = true;
92 return FILE_ERROR_OK;
93 }
94
95 // Copy locally.
96 ResourceEntry entry;
97 const int64 now = base::Time::Now().ToInternalValue();
98 entry.set_title(params->dest_file_path.BaseName().AsUTF8Unsafe());
99 entry.set_parent_local_id(params->parent_entry.local_id());
100 entry.mutable_file_specific_info()->set_content_mime_type(
101 params->src_entry.file_specific_info().content_mime_type());
102 entry.set_metadata_edit_state(ResourceEntry::DIRTY);
103 entry.mutable_file_info()->set_last_modified(
104 params->preserve_last_modified ?
105 params->src_entry.file_info().last_modified() : now);
106 entry.mutable_file_info()->set_last_accessed(now);
107
108 std::string local_id;
109 error = metadata->AddEntry(entry, &local_id);
110 if (error != FILE_ERROR_OK)
111 return error;
112 updated_local_ids->push_back(local_id);
113 *directory_changed = true;
114
115 base::FilePath cache_file_path;
116 error = cache->GetFile(params->src_entry.local_id(), &cache_file_path);
117 if (error != FILE_ERROR_OK)
118 return error;
119
120 return cache->Store(local_id, std::string(), cache_file_path,
121 internal::FileCache::FILE_OPERATION_COPY);
53 } 122 }
54 123
55 int64 GetFileSize(const base::FilePath& file_path) { 124 int64 GetFileSize(const base::FilePath& file_path) {
56 int64 file_size; 125 int64 file_size;
57 if (!base::GetFileSize(file_path, &file_size)) 126 if (!base::GetFileSize(file_path, &file_size))
58 return -1; 127 return -1;
59 return file_size; 128 return file_size;
60 } 129 }
61 130
62 // Stores the copied entry and returns its path. 131 // Stores the copied entry and returns its path.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 if (util::HasGDocFileExtension(local_src_path)) { 205 if (util::HasGDocFileExtension(local_src_path)) {
137 *gdoc_resource_id = util::ReadResourceIdFromGDocFile(local_src_path); 206 *gdoc_resource_id = util::ReadResourceIdFromGDocFile(local_src_path);
138 *parent_resource_id = parent_entry.resource_id(); 207 *parent_resource_id = parent_entry.resource_id();
139 } 208 }
140 209
141 return FILE_ERROR_OK; 210 return FILE_ERROR_OK;
142 } 211 }
143 212
144 } // namespace 213 } // namespace
145 214
146 struct CopyOperation::CopyParams {
147 base::FilePath dest_file_path;
148 bool preserve_last_modified;
149 FileOperationCallback callback;
150 };
151
152 CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner, 215 CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner,
153 OperationObserver* observer, 216 OperationObserver* observer,
154 JobScheduler* scheduler, 217 JobScheduler* scheduler,
155 internal::ResourceMetadata* metadata, 218 internal::ResourceMetadata* metadata,
156 internal::FileCache* cache, 219 internal::FileCache* cache,
157 const ResourceIdCanonicalizer& id_canonicalizer) 220 const ResourceIdCanonicalizer& id_canonicalizer)
158 : blocking_task_runner_(blocking_task_runner), 221 : blocking_task_runner_(blocking_task_runner),
159 observer_(observer), 222 observer_(observer),
160 scheduler_(scheduler), 223 scheduler_(scheduler),
161 metadata_(metadata), 224 metadata_(metadata),
(...skipping 12 matching lines...) Expand all
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
175 } 238 }
176 239
177 void CopyOperation::Copy(const base::FilePath& src_file_path, 240 void CopyOperation::Copy(const base::FilePath& src_file_path,
178 const base::FilePath& dest_file_path, 241 const base::FilePath& dest_file_path,
179 bool preserve_last_modified, 242 bool preserve_last_modified,
180 const FileOperationCallback& callback) { 243 const FileOperationCallback& callback) {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 DCHECK(!callback.is_null()); 245 DCHECK(!callback.is_null());
183 246
184 CopyParams params; 247 CopyParams* params = new CopyParams;
185 params.dest_file_path = dest_file_path; 248 params->src_file_path = src_file_path;
186 params.preserve_last_modified = preserve_last_modified; 249 params->dest_file_path = dest_file_path;
187 params.callback = callback; 250 params->preserve_last_modified = preserve_last_modified;
251 params->callback = callback;
188 252
189 ResourceEntry* src_entry = new ResourceEntry; 253 std::vector<std::string>* updated_local_ids = new std::vector<std::string>;
190 std::string* parent_resource_id = new std::string; 254 bool* directory_changed = new bool(false);
255 bool* should_copy_on_server = new bool(false);
191 base::PostTaskAndReplyWithResult( 256 base::PostTaskAndReplyWithResult(
192 blocking_task_runner_.get(), 257 blocking_task_runner_.get(),
193 FROM_HERE, 258 FROM_HERE,
194 base::Bind(&PrepareCopy, 259 base::Bind(&TryToCopyLocally, metadata_, cache_, params,
195 metadata_, src_file_path, dest_file_path, 260 updated_local_ids, directory_changed, should_copy_on_server),
196 src_entry, parent_resource_id), 261 base::Bind(&CopyOperation::CopyAfterTryToCopyLocally,
197 base::Bind(&CopyOperation::CopyAfterPrepare, 262 weak_ptr_factory_.GetWeakPtr(), base::Owned(params),
198 weak_ptr_factory_.GetWeakPtr(), params, 263 base::Owned(updated_local_ids), base::Owned(directory_changed),
199 base::Owned(src_entry), base::Owned(parent_resource_id))); 264 base::Owned(should_copy_on_server)));
200 } 265 }
201 266
202 void CopyOperation::CopyAfterPrepare(const CopyParams& params, 267 void CopyOperation::CopyAfterTryToCopyLocally(
203 ResourceEntry* src_entry, 268 const CopyParams* params,
204 std::string* parent_resource_id, 269 const std::vector<std::string>* updated_local_ids,
205 FileError error) { 270 const bool* directory_changed,
271 const bool* should_copy_on_server,
272 FileError error) {
206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
207 DCHECK(!params.callback.is_null()); 274 DCHECK(!params->callback.is_null());
208 275
209 if (error != FILE_ERROR_OK) { 276 for (size_t i = 0; i < updated_local_ids->size(); ++i)
210 params.callback.Run(error); 277 observer_->OnEntryUpdatedByOperation((*updated_local_ids)[i]);
278
279 if (*directory_changed)
280 observer_->OnDirectoryChangedByOperation(params->dest_file_path.DirName());
281
282 if (error != FILE_ERROR_OK || !*should_copy_on_server) {
283 params->callback.Run(error);
211 return; 284 return;
212 } 285 }
213 286
214 base::FilePath new_title = params.dest_file_path.BaseName(); 287 base::FilePath new_title = params->dest_file_path.BaseName();
215 if (src_entry->file_specific_info().is_hosted_document()) { 288 if (params->src_entry.file_specific_info().is_hosted_document()) {
216 // Drop the document extension, which should not be in the title. 289 // Drop the document extension, which should not be in the title.
217 // TODO(yoshiki): Remove this code with crbug.com/223304. 290 // TODO(yoshiki): Remove this code with crbug.com/223304.
218 new_title = new_title.RemoveExtension(); 291 new_title = new_title.RemoveExtension();
219 } 292 }
220 293
221 base::Time last_modified = 294 base::Time last_modified =
222 params.preserve_last_modified ? 295 params->preserve_last_modified ?
223 base::Time::FromInternalValue(src_entry->file_info().last_modified()) : 296 base::Time::FromInternalValue(
224 base::Time(); 297 params->src_entry.file_info().last_modified()) : base::Time();
225 298
226 CopyResourceOnServer( 299 CopyResourceOnServer(
227 src_entry->resource_id(), *parent_resource_id, 300 params->src_entry.resource_id(), params->parent_entry.resource_id(),
228 new_title.AsUTF8Unsafe(), last_modified, params.callback); 301 new_title.AsUTF8Unsafe(), last_modified, params->callback);
229 } 302 }
230 303
231 void CopyOperation::TransferFileFromLocalToRemote( 304 void CopyOperation::TransferFileFromLocalToRemote(
232 const base::FilePath& local_src_path, 305 const base::FilePath& local_src_path,
233 const base::FilePath& remote_dest_path, 306 const base::FilePath& remote_dest_path,
234 const FileOperationCallback& callback) { 307 const FileOperationCallback& callback) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
236 DCHECK(!callback.is_null()); 309 DCHECK(!callback.is_null());
237 310
238 std::string* gdoc_resource_id = new std::string; 311 std::string* gdoc_resource_id = new std::string;
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 518 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
446 DCHECK(!callback.is_null()); 519 DCHECK(!callback.is_null());
447 520
448 if (error == FILE_ERROR_OK) 521 if (error == FILE_ERROR_OK)
449 observer_->OnEntryUpdatedByOperation(*local_id); 522 observer_->OnEntryUpdatedByOperation(*local_id);
450 callback.Run(error); 523 callback.Run(error);
451 } 524 }
452 525
453 } // namespace file_system 526 } // namespace file_system
454 } // namespace drive 527 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698