| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/chromeos/gdata/gdata_file_system_proxy.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/platform_file.h" | |
| 12 #include "base/string_util.h" | |
| 13 #include "base/values.h" | |
| 14 #include "chrome/browser/chromeos/gdata/drive.pb.h" | |
| 15 #include "chrome/browser/chromeos/gdata/drive_files.h" | |
| 16 #include "chrome/browser/chromeos/gdata/gdata_file_system_interface.h" | |
| 17 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" | |
| 18 #include "chrome/browser/chromeos/gdata/gdata_util.h" | |
| 19 #include "content/public/browser/browser_thread.h" | |
| 20 #include "webkit/blob/shareable_file_reference.h" | |
| 21 #include "webkit/fileapi/file_system_file_util_proxy.h" | |
| 22 #include "webkit/fileapi/file_system_types.h" | |
| 23 #include "webkit/fileapi/file_system_url.h" | |
| 24 #include "webkit/fileapi/file_system_util.h" | |
| 25 | |
| 26 using base::MessageLoopProxy; | |
| 27 using content::BrowserThread; | |
| 28 using fileapi::FileSystemURL; | |
| 29 using fileapi::FileSystemOperationInterface; | |
| 30 using webkit_blob::ShareableFileReference; | |
| 31 | |
| 32 namespace gdata { | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 const char kDriveRootDirectory[] = "drive"; | |
| 37 const char kFeedField[] = "feed"; | |
| 38 | |
| 39 // Helper function that creates platform file on blocking IO thread pool. | |
| 40 void OpenPlatformFileOnIOPool(const FilePath& local_path, | |
| 41 int file_flags, | |
| 42 base::PlatformFile* platform_file, | |
| 43 base::PlatformFileError* open_error) { | |
| 44 bool created; | |
| 45 *platform_file = base::CreatePlatformFile(local_path, | |
| 46 file_flags, | |
| 47 &created, | |
| 48 open_error); | |
| 49 } | |
| 50 | |
| 51 // Helper function to run reply on results of OpenPlatformFileOnIOPool() on | |
| 52 // IO thread. | |
| 53 void OnPlatformFileOpened( | |
| 54 const FileSystemOperationInterface::OpenFileCallback& callback, | |
| 55 base::ProcessHandle peer_handle, | |
| 56 base::PlatformFile* platform_file, | |
| 57 base::PlatformFileError* open_error) { | |
| 58 callback.Run(*open_error, *platform_file, peer_handle); | |
| 59 } | |
| 60 | |
| 61 // Helper function to run OpenFileCallback from | |
| 62 // GDataFileSystemProxy::OpenFile(). | |
| 63 void OnGetFileByPathForOpen( | |
| 64 const FileSystemOperationInterface::OpenFileCallback& callback, | |
| 65 int file_flags, | |
| 66 base::ProcessHandle peer_handle, | |
| 67 DriveFileError file_error, | |
| 68 const FilePath& local_path, | |
| 69 const std::string& unused_mime_type, | |
| 70 DriveFileType file_type) { | |
| 71 base::PlatformFileError error = | |
| 72 util::DriveFileErrorToPlatformError(file_error); | |
| 73 if (error != base::PLATFORM_FILE_OK) { | |
| 74 callback.Run(error, base::kInvalidPlatformFileValue, peer_handle); | |
| 75 return; | |
| 76 } | |
| 77 | |
| 78 base::PlatformFile* platform_file = new base::PlatformFile( | |
| 79 base::kInvalidPlatformFileValue); | |
| 80 base::PlatformFileError* open_error = | |
| 81 new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED); | |
| 82 BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE, | |
| 83 base::Bind(&OpenPlatformFileOnIOPool, | |
| 84 local_path, | |
| 85 file_flags, | |
| 86 platform_file, | |
| 87 open_error), | |
| 88 base::Bind(&OnPlatformFileOpened, | |
| 89 callback, | |
| 90 peer_handle, | |
| 91 base::Owned(platform_file), | |
| 92 base::Owned(open_error))); | |
| 93 } | |
| 94 | |
| 95 // Helper function to run SnapshotFileCallback from | |
| 96 // GDataFileSystemProxy::CreateSnapshotFile(). | |
| 97 void CallSnapshotFileCallback( | |
| 98 const FileSystemOperationInterface::SnapshotFileCallback& callback, | |
| 99 const base::PlatformFileInfo& file_info, | |
| 100 DriveFileError file_error, | |
| 101 const FilePath& local_path, | |
| 102 const std::string& unused_mime_type, | |
| 103 DriveFileType file_type) { | |
| 104 scoped_refptr<ShareableFileReference> file_ref; | |
| 105 base::PlatformFileError error = | |
| 106 util::DriveFileErrorToPlatformError(file_error); | |
| 107 | |
| 108 // If the file is a hosted document, a temporary JSON file is created to | |
| 109 // represent the document. The JSON file is not cached and its lifetime | |
| 110 // is managed by ShareableFileReference. | |
| 111 if (error == base::PLATFORM_FILE_OK && file_type == HOSTED_DOCUMENT) { | |
| 112 file_ref = ShareableFileReference::GetOrCreate( | |
| 113 local_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE, | |
| 114 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | |
| 115 } | |
| 116 | |
| 117 // When reading file, last modified time specified in file info will be | |
| 118 // compared to the last modified time of the local version of the drive file. | |
| 119 // Since those two values don't generally match (last modification time on the | |
| 120 // drive server vs. last modification time of the local, downloaded file), so | |
| 121 // we have to opt out from this check. We do this by unsetting last_modified | |
| 122 // value in the file info passed to the CreateSnapshot caller. | |
| 123 base::PlatformFileInfo final_file_info(file_info); | |
| 124 final_file_info.last_modified = base::Time(); | |
| 125 | |
| 126 callback.Run(error, final_file_info, local_path, file_ref); | |
| 127 } | |
| 128 | |
| 129 // Emits debug log when GDataFileSystem::CloseFile() is complete. | |
| 130 void EmitDebugLogForCloseFile(const FilePath& local_path, | |
| 131 DriveFileError error_code) { | |
| 132 DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << error_code; | |
| 133 } | |
| 134 | |
| 135 void DoTruncateOnFileThread( | |
| 136 const FilePath& local_cache_path, | |
| 137 int64 length, | |
| 138 base::PlatformFileError* result) { | |
| 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 140 | |
| 141 base::PlatformFile file = base::CreatePlatformFile( | |
| 142 local_cache_path, | |
| 143 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, | |
| 144 NULL, | |
| 145 result); | |
| 146 if (*result == base::PLATFORM_FILE_OK) { | |
| 147 DCHECK_NE(base::kInvalidPlatformFileValue, file); | |
| 148 if (!base::TruncatePlatformFile(file, length)) | |
| 149 *result = base::PLATFORM_FILE_ERROR_FAILED; | |
| 150 base::ClosePlatformFile(file); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 void DidCloseFileForTruncate( | |
| 155 const FileSystemOperationInterface::StatusCallback& callback, | |
| 156 base::PlatformFileError truncate_result, | |
| 157 DriveFileError close_result) { | |
| 158 // Reports the first error. | |
| 159 callback.Run(truncate_result == base::PLATFORM_FILE_OK ? | |
| 160 util::DriveFileErrorToPlatformError(close_result) : | |
| 161 truncate_result); | |
| 162 } | |
| 163 | |
| 164 } // namespace | |
| 165 | |
| 166 base::FileUtilProxy::Entry DriveEntryProtoToFileUtilProxyEntry( | |
| 167 const DriveEntryProto& proto) { | |
| 168 base::PlatformFileInfo file_info; | |
| 169 DriveEntry::ConvertProtoToPlatformFileInfo(proto.file_info(), &file_info); | |
| 170 | |
| 171 base::FileUtilProxy::Entry entry; | |
| 172 entry.name = proto.base_name(); | |
| 173 entry.is_directory = file_info.is_directory; | |
| 174 entry.size = file_info.size; | |
| 175 entry.last_modified_time = file_info.last_modified; | |
| 176 return entry; | |
| 177 } | |
| 178 | |
| 179 // GDataFileSystemProxy class implementation. | |
| 180 | |
| 181 GDataFileSystemProxy::GDataFileSystemProxy( | |
| 182 GDataFileSystemInterface* file_system) | |
| 183 : file_system_(file_system) { | |
| 184 // Should be created from the file browser extension API (AddMountFunction) | |
| 185 // on UI thread. | |
| 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 187 } | |
| 188 | |
| 189 void GDataFileSystemProxy::GetFileInfo(const FileSystemURL& file_url, | |
| 190 const FileSystemOperationInterface::GetMetadataCallback& callback) { | |
| 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 192 FilePath file_path; | |
| 193 if (!ValidateUrl(file_url, &file_path)) { | |
| 194 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 195 base::Bind(callback, | |
| 196 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 197 base::PlatformFileInfo(), | |
| 198 FilePath())); | |
| 199 return; | |
| 200 } | |
| 201 | |
| 202 file_system_->GetEntryInfoByPath( | |
| 203 file_path, | |
| 204 base::Bind(&GDataFileSystemProxy::OnGetMetadata, | |
| 205 this, | |
| 206 file_path, | |
| 207 callback)); | |
| 208 } | |
| 209 | |
| 210 void GDataFileSystemProxy::Copy(const FileSystemURL& src_file_url, | |
| 211 const FileSystemURL& dest_file_url, | |
| 212 const FileSystemOperationInterface::StatusCallback& callback) { | |
| 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 214 | |
| 215 FilePath src_file_path, dest_file_path; | |
| 216 if (!ValidateUrl(src_file_url, &src_file_path) || | |
| 217 !ValidateUrl(dest_file_url, &dest_file_path)) { | |
| 218 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 219 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
| 220 return; | |
| 221 } | |
| 222 | |
| 223 file_system_->Copy( | |
| 224 src_file_path, | |
| 225 dest_file_path, | |
| 226 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
| 227 } | |
| 228 | |
| 229 void GDataFileSystemProxy::Move(const FileSystemURL& src_file_url, | |
| 230 const FileSystemURL& dest_file_url, | |
| 231 const FileSystemOperationInterface::StatusCallback& callback) { | |
| 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 233 | |
| 234 FilePath src_file_path, dest_file_path; | |
| 235 if (!ValidateUrl(src_file_url, &src_file_path) || | |
| 236 !ValidateUrl(dest_file_url, &dest_file_path)) { | |
| 237 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 238 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
| 239 return; | |
| 240 } | |
| 241 | |
| 242 file_system_->Move( | |
| 243 src_file_path, | |
| 244 dest_file_path, | |
| 245 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
| 246 } | |
| 247 | |
| 248 void GDataFileSystemProxy::ReadDirectory(const FileSystemURL& file_url, | |
| 249 const FileSystemOperationInterface::ReadDirectoryCallback& callback) { | |
| 250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 251 | |
| 252 FilePath file_path; | |
| 253 if (!ValidateUrl(file_url, &file_path)) { | |
| 254 base::MessageLoopProxy::current()->PostTask( | |
| 255 FROM_HERE, | |
| 256 base::Bind(callback, | |
| 257 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 258 std::vector<base::FileUtilProxy::Entry>(), | |
| 259 false)); | |
| 260 return; | |
| 261 } | |
| 262 | |
| 263 file_system_->ReadDirectoryByPath( | |
| 264 file_path, | |
| 265 base::Bind(&GDataFileSystemProxy::OnReadDirectory, | |
| 266 this, | |
| 267 callback)); | |
| 268 } | |
| 269 | |
| 270 void GDataFileSystemProxy::Remove(const FileSystemURL& file_url, bool recursive, | |
| 271 const FileSystemOperationInterface::StatusCallback& callback) { | |
| 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 273 | |
| 274 FilePath file_path; | |
| 275 if (!ValidateUrl(file_url, &file_path)) { | |
| 276 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 277 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
| 278 return; | |
| 279 } | |
| 280 | |
| 281 file_system_->Remove( | |
| 282 file_path, | |
| 283 recursive, | |
| 284 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
| 285 } | |
| 286 | |
| 287 void GDataFileSystemProxy::CreateDirectory( | |
| 288 const FileSystemURL& file_url, | |
| 289 bool exclusive, | |
| 290 bool recursive, | |
| 291 const FileSystemOperationInterface::StatusCallback& callback) { | |
| 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 293 | |
| 294 FilePath file_path; | |
| 295 if (!ValidateUrl(file_url, &file_path)) { | |
| 296 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 297 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
| 298 return; | |
| 299 } | |
| 300 | |
| 301 file_system_->CreateDirectory( | |
| 302 file_path, | |
| 303 exclusive, | |
| 304 recursive, | |
| 305 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
| 306 } | |
| 307 | |
| 308 void GDataFileSystemProxy::CreateFile( | |
| 309 const FileSystemURL& file_url, | |
| 310 bool exclusive, | |
| 311 const FileSystemOperationInterface::StatusCallback& callback) { | |
| 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 313 | |
| 314 FilePath file_path; | |
| 315 if (!ValidateUrl(file_url, &file_path)) { | |
| 316 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 317 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
| 318 return; | |
| 319 } | |
| 320 | |
| 321 file_system_->CreateFile( | |
| 322 file_path, | |
| 323 exclusive, | |
| 324 base::Bind(&GDataFileSystemProxy::OnStatusCallback, this, callback)); | |
| 325 } | |
| 326 | |
| 327 void GDataFileSystemProxy::Truncate( | |
| 328 const FileSystemURL& file_url, int64 length, | |
| 329 const FileSystemOperationInterface::StatusCallback& callback) { | |
| 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 331 | |
| 332 if (length < 0) { | |
| 333 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 334 base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION)); | |
| 335 return; | |
| 336 } | |
| 337 | |
| 338 FilePath file_path; | |
| 339 if (!ValidateUrl(file_url, &file_path)) { | |
| 340 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 341 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | |
| 342 return; | |
| 343 } | |
| 344 | |
| 345 // TODO(kinaba): http://crbug.com/132780. | |
| 346 // Optimize the cases for small |length|, at least for |length| == 0. | |
| 347 // CreateWritableSnapshotFile downloads the whole content unnecessarily. | |
| 348 file_system_->OpenFile( | |
| 349 file_path, | |
| 350 base::Bind(&GDataFileSystemProxy::OnFileOpenedForTruncate, | |
| 351 this, | |
| 352 file_path, | |
| 353 length, | |
| 354 callback)); | |
| 355 } | |
| 356 | |
| 357 void GDataFileSystemProxy::OnOpenFileForWriting( | |
| 358 int file_flags, | |
| 359 base::ProcessHandle peer_handle, | |
| 360 const FileSystemOperationInterface::OpenFileCallback& callback, | |
| 361 DriveFileError file_error, | |
| 362 const FilePath& local_cache_path) { | |
| 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 364 | |
| 365 base::PlatformFileError error = | |
| 366 util::DriveFileErrorToPlatformError(file_error); | |
| 367 | |
| 368 if (error != base::PLATFORM_FILE_OK) { | |
| 369 callback.Run(error, base::kInvalidPlatformFileValue, peer_handle); | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 // Cache file prepared for modification is available. Truncate it. | |
| 374 // File operation must be done on FILE thread, so relay the operation. | |
| 375 base::PlatformFileError* result = | |
| 376 new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED); | |
| 377 base::PlatformFile* platform_file = new base::PlatformFile( | |
| 378 base::kInvalidPlatformFileValue); | |
| 379 bool posted = BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE, | |
| 380 base::Bind(&OpenPlatformFileOnIOPool, | |
| 381 local_cache_path, | |
| 382 file_flags, | |
| 383 platform_file, | |
| 384 result), | |
| 385 base::Bind(&OnPlatformFileOpened, | |
| 386 callback, | |
| 387 peer_handle, | |
| 388 base::Owned(platform_file), | |
| 389 base::Owned(result))); | |
| 390 DCHECK(posted); | |
| 391 } | |
| 392 | |
| 393 void GDataFileSystemProxy::OnCreateFileForOpen( | |
| 394 const FilePath& file_path, | |
| 395 int file_flags, | |
| 396 base::ProcessHandle peer_handle, | |
| 397 const FileSystemOperationInterface::OpenFileCallback& callback, | |
| 398 DriveFileError file_error) { | |
| 399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 400 base::PlatformFileError create_result = | |
| 401 util::DriveFileErrorToPlatformError(file_error); | |
| 402 | |
| 403 if ((create_result == base::PLATFORM_FILE_OK) || | |
| 404 ((create_result == base::PLATFORM_FILE_ERROR_EXISTS) && | |
| 405 (file_flags & base::PLATFORM_FILE_CREATE_ALWAYS))) { | |
| 406 // If we are trying to always create an existing file, then | |
| 407 // if it really exists open it as truncated. | |
| 408 file_flags &= ~base::PLATFORM_FILE_CREATE; | |
| 409 file_flags &= ~base::PLATFORM_FILE_CREATE_ALWAYS; | |
| 410 file_flags |= base::PLATFORM_FILE_OPEN_TRUNCATED; | |
| 411 } else { | |
| 412 callback.Run(create_result, base::kInvalidPlatformFileValue, peer_handle); | |
| 413 return; | |
| 414 } | |
| 415 | |
| 416 // Open created (or existing) file for writing. | |
| 417 file_system_->OpenFile( | |
| 418 file_path, | |
| 419 base::Bind(&GDataFileSystemProxy::OnOpenFileForWriting, | |
| 420 this, | |
| 421 file_flags, | |
| 422 peer_handle, | |
| 423 callback)); | |
| 424 } | |
| 425 | |
| 426 void GDataFileSystemProxy::OnFileOpenedForTruncate( | |
| 427 const FilePath& virtual_path, | |
| 428 int64 length, | |
| 429 const fileapi::FileSystemOperationInterface::StatusCallback& callback, | |
| 430 DriveFileError open_result, | |
| 431 const FilePath& local_cache_path) { | |
| 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 433 | |
| 434 if (open_result != DRIVE_FILE_OK) { | |
| 435 callback.Run(util::DriveFileErrorToPlatformError(open_result)); | |
| 436 return; | |
| 437 } | |
| 438 | |
| 439 // Cache file prepared for modification is available. Truncate it. | |
| 440 // File operation must be done on FILE thread, so relay the operation. | |
| 441 base::PlatformFileError* result = | |
| 442 new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED); | |
| 443 bool posted = BrowserThread::GetMessageLoopProxyForThread( | |
| 444 BrowserThread::FILE)->PostTaskAndReply( | |
| 445 FROM_HERE, | |
| 446 base::Bind(&DoTruncateOnFileThread, | |
| 447 local_cache_path, | |
| 448 length, | |
| 449 result), | |
| 450 base::Bind(&GDataFileSystemProxy::DidTruncate, | |
| 451 this, | |
| 452 virtual_path, | |
| 453 callback, | |
| 454 base::Owned(result))); | |
| 455 DCHECK(posted); | |
| 456 } | |
| 457 | |
| 458 void GDataFileSystemProxy::DidTruncate( | |
| 459 const FilePath& virtual_path, | |
| 460 const FileSystemOperationInterface::StatusCallback& callback, | |
| 461 base::PlatformFileError* truncate_result) { | |
| 462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 463 | |
| 464 // Truncation finished. We must close the file no matter |truncate_result| | |
| 465 // indicates an error or not. | |
| 466 file_system_->CloseFile( | |
| 467 virtual_path, | |
| 468 base::Bind(&DidCloseFileForTruncate, | |
| 469 callback, | |
| 470 base::PlatformFileError(*truncate_result))); | |
| 471 } | |
| 472 | |
| 473 void GDataFileSystemProxy::OpenFile( | |
| 474 const FileSystemURL& file_url, | |
| 475 int file_flags, | |
| 476 base::ProcessHandle peer_handle, | |
| 477 const FileSystemOperationInterface::OpenFileCallback& callback) { | |
| 478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 479 | |
| 480 FilePath file_path; | |
| 481 if (!ValidateUrl(file_url, &file_path)) { | |
| 482 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 483 base::Bind(callback, | |
| 484 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 485 base::kInvalidPlatformFileValue, | |
| 486 peer_handle)); | |
| 487 return; | |
| 488 } | |
| 489 | |
| 490 // TODO(zelidrag): Wire all other file open operations. | |
| 491 if ((file_flags & base::PLATFORM_FILE_DELETE_ON_CLOSE)) { | |
| 492 NOTIMPLEMENTED() << "File create/write operations not yet supported " | |
| 493 << file_path.value(); | |
| 494 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 495 base::Bind(callback, | |
| 496 base::PLATFORM_FILE_ERROR_FAILED, | |
| 497 base::kInvalidPlatformFileValue, | |
| 498 peer_handle)); | |
| 499 return; | |
| 500 } | |
| 501 | |
| 502 if ((file_flags & base::PLATFORM_FILE_OPEN) || | |
| 503 (file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) || | |
| 504 (file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED)) { | |
| 505 if ((file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED) || | |
| 506 (file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) || | |
| 507 (file_flags & base::PLATFORM_FILE_WRITE) || | |
| 508 (file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE)) { | |
| 509 // Open existing file for writing. | |
| 510 file_system_->OpenFile( | |
| 511 file_path, | |
| 512 base::Bind(&GDataFileSystemProxy::OnOpenFileForWriting, | |
| 513 this, | |
| 514 file_flags, | |
| 515 peer_handle, | |
| 516 callback)); | |
| 517 } else { | |
| 518 // Read-only file open. | |
| 519 file_system_->GetFileByPath(file_path, | |
| 520 base::Bind(&OnGetFileByPathForOpen, | |
| 521 callback, | |
| 522 file_flags, | |
| 523 peer_handle), | |
| 524 GetContentCallback()); | |
| 525 } | |
| 526 } else if ((file_flags & base::PLATFORM_FILE_CREATE) || | |
| 527 (file_flags & base::PLATFORM_FILE_CREATE_ALWAYS)) { | |
| 528 // Open existing file for writing. | |
| 529 file_system_->CreateFile( | |
| 530 file_path, | |
| 531 file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE, | |
| 532 base::Bind(&GDataFileSystemProxy::OnCreateFileForOpen, | |
| 533 this, | |
| 534 file_path, | |
| 535 file_flags, | |
| 536 peer_handle, | |
| 537 callback)); | |
| 538 } else { | |
| 539 NOTREACHED() << "Unhandled file flags combination " << file_flags; | |
| 540 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 541 base::Bind(callback, | |
| 542 base::PLATFORM_FILE_ERROR_FAILED, | |
| 543 base::kInvalidPlatformFileValue, | |
| 544 peer_handle)); | |
| 545 } | |
| 546 } | |
| 547 | |
| 548 void GDataFileSystemProxy::NotifyCloseFile(const FileSystemURL& url) { | |
| 549 FilePath file_path; | |
| 550 if (!ValidateUrl(url, &file_path)) | |
| 551 return; | |
| 552 | |
| 553 file_system_->CloseFile(file_path, | |
| 554 base::Bind(&EmitDebugLogForCloseFile, file_path)); | |
| 555 } | |
| 556 | |
| 557 void GDataFileSystemProxy::CreateSnapshotFile( | |
| 558 const FileSystemURL& file_url, | |
| 559 const FileSystemOperationInterface::SnapshotFileCallback& callback) { | |
| 560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 561 | |
| 562 FilePath file_path; | |
| 563 if (!ValidateUrl(file_url, &file_path)) { | |
| 564 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 565 base::Bind(callback, | |
| 566 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 567 base::PlatformFileInfo(), | |
| 568 FilePath(), | |
| 569 scoped_refptr<ShareableFileReference>(NULL))); | |
| 570 return; | |
| 571 } | |
| 572 | |
| 573 file_system_->GetEntryInfoByPath( | |
| 574 file_path, | |
| 575 base::Bind(&GDataFileSystemProxy::OnGetEntryInfoByPath, | |
| 576 this, | |
| 577 file_path, | |
| 578 callback)); | |
| 579 } | |
| 580 | |
| 581 void GDataFileSystemProxy::OnGetEntryInfoByPath( | |
| 582 const FilePath& entry_path, | |
| 583 const FileSystemOperationInterface::SnapshotFileCallback& callback, | |
| 584 DriveFileError error, | |
| 585 scoped_ptr<DriveEntryProto> entry_proto) { | |
| 586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 587 | |
| 588 if (error != DRIVE_FILE_OK || !entry_proto.get()) { | |
| 589 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 590 base::Bind(callback, | |
| 591 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 592 base::PlatformFileInfo(), | |
| 593 FilePath(), | |
| 594 scoped_refptr<ShareableFileReference>(NULL))); | |
| 595 return; | |
| 596 } | |
| 597 | |
| 598 base::PlatformFileInfo file_info; | |
| 599 DriveEntry::ConvertProtoToPlatformFileInfo( | |
| 600 entry_proto->file_info(), | |
| 601 &file_info); | |
| 602 | |
| 603 file_system_->GetFileByPath(entry_path, | |
| 604 base::Bind(&CallSnapshotFileCallback, | |
| 605 callback, | |
| 606 file_info), | |
| 607 GetContentCallback()); | |
| 608 } | |
| 609 | |
| 610 void GDataFileSystemProxy::CreateWritableSnapshotFile( | |
| 611 const FileSystemURL& file_url, | |
| 612 const fileapi::WritableSnapshotFile& callback) { | |
| 613 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 614 | |
| 615 FilePath file_path; | |
| 616 if (!ValidateUrl(file_url, &file_path)) { | |
| 617 MessageLoopProxy::current()->PostTask(FROM_HERE, | |
| 618 base::Bind(callback, | |
| 619 base::PLATFORM_FILE_ERROR_NOT_FOUND, | |
| 620 FilePath(), | |
| 621 scoped_refptr<ShareableFileReference>(NULL))); | |
| 622 return; | |
| 623 } | |
| 624 | |
| 625 file_system_->OpenFile( | |
| 626 file_path, | |
| 627 base::Bind(&GDataFileSystemProxy::OnCreateWritableSnapshotFile, | |
| 628 this, | |
| 629 file_path, | |
| 630 callback)); | |
| 631 } | |
| 632 | |
| 633 GDataFileSystemProxy::~GDataFileSystemProxy() { | |
| 634 // Should be deleted from the CrosMountPointProvider on UI thread. | |
| 635 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 636 } | |
| 637 | |
| 638 // static. | |
| 639 bool GDataFileSystemProxy::ValidateUrl( | |
| 640 const FileSystemURL& url, FilePath* file_path) { | |
| 641 // what platform you're on. | |
| 642 if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeDrive) { | |
| 643 return false; | |
| 644 } | |
| 645 *file_path = url.virtual_path(); | |
| 646 return true; | |
| 647 } | |
| 648 | |
| 649 void GDataFileSystemProxy::OnStatusCallback( | |
| 650 const fileapi::FileSystemOperationInterface::StatusCallback& callback, | |
| 651 DriveFileError error) { | |
| 652 callback.Run(util::DriveFileErrorToPlatformError(error)); | |
| 653 } | |
| 654 | |
| 655 void GDataFileSystemProxy::OnGetMetadata( | |
| 656 const FilePath& file_path, | |
| 657 const FileSystemOperationInterface::GetMetadataCallback& callback, | |
| 658 DriveFileError error, | |
| 659 scoped_ptr<DriveEntryProto> entry_proto) { | |
| 660 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 661 | |
| 662 if (error != DRIVE_FILE_OK) { | |
| 663 callback.Run(util::DriveFileErrorToPlatformError(error), | |
| 664 base::PlatformFileInfo(), | |
| 665 FilePath()); | |
| 666 return; | |
| 667 } | |
| 668 DCHECK(entry_proto.get()); | |
| 669 | |
| 670 base::PlatformFileInfo file_info; | |
| 671 DriveEntry::ConvertProtoToPlatformFileInfo( | |
| 672 entry_proto->file_info(), | |
| 673 &file_info); | |
| 674 | |
| 675 callback.Run(base::PLATFORM_FILE_OK, file_info, file_path); | |
| 676 } | |
| 677 | |
| 678 void GDataFileSystemProxy::OnReadDirectory( | |
| 679 const FileSystemOperationInterface::ReadDirectoryCallback& | |
| 680 callback, | |
| 681 DriveFileError error, | |
| 682 bool hide_hosted_documents, | |
| 683 scoped_ptr<DriveEntryProtoVector> proto_entries) { | |
| 684 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 685 | |
| 686 if (error != DRIVE_FILE_OK) { | |
| 687 callback.Run(util::DriveFileErrorToPlatformError(error), | |
| 688 std::vector<base::FileUtilProxy::Entry>(), | |
| 689 false); | |
| 690 return; | |
| 691 } | |
| 692 DCHECK(proto_entries.get()); | |
| 693 | |
| 694 std::vector<base::FileUtilProxy::Entry> entries; | |
| 695 // Convert gdata files to something File API stack can understand. | |
| 696 for (size_t i = 0; i < proto_entries->size(); ++i) { | |
| 697 const DriveEntryProto& proto = (*proto_entries)[i]; | |
| 698 if (proto.has_file_specific_info() && | |
| 699 proto.file_specific_info().is_hosted_document() && | |
| 700 hide_hosted_documents) { | |
| 701 continue; | |
| 702 } | |
| 703 entries.push_back(DriveEntryProtoToFileUtilProxyEntry(proto)); | |
| 704 } | |
| 705 | |
| 706 callback.Run(base::PLATFORM_FILE_OK, entries, false); | |
| 707 } | |
| 708 | |
| 709 void GDataFileSystemProxy::OnCreateWritableSnapshotFile( | |
| 710 const FilePath& virtual_path, | |
| 711 const fileapi::WritableSnapshotFile& callback, | |
| 712 DriveFileError result, | |
| 713 const FilePath& local_path) { | |
| 714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 715 | |
| 716 scoped_refptr<ShareableFileReference> file_ref; | |
| 717 | |
| 718 if (result == DRIVE_FILE_OK) { | |
| 719 file_ref = ShareableFileReference::GetOrCreate( | |
| 720 local_path, | |
| 721 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, | |
| 722 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | |
| 723 file_ref->AddFinalReleaseCallback( | |
| 724 base::Bind(&GDataFileSystemProxy::CloseWritableSnapshotFile, | |
| 725 this, | |
| 726 virtual_path)); | |
| 727 } | |
| 728 | |
| 729 callback.Run( | |
| 730 util::DriveFileErrorToPlatformError(result), local_path, file_ref); | |
| 731 } | |
| 732 | |
| 733 void GDataFileSystemProxy::CloseWritableSnapshotFile( | |
| 734 const FilePath& virtual_path, | |
| 735 const FilePath& local_path) { | |
| 736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 737 | |
| 738 file_system_->CloseFile(virtual_path, | |
| 739 base::Bind(&EmitDebugLogForCloseFile, virtual_path)); | |
| 740 } | |
| 741 | |
| 742 } // namespace gdata | |
| OLD | NEW |