create_file_operation.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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. 4 5#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h" 6 7#include <string> 8 9#include "base/file_util.h" 10#include "chrome/browser/chromeos/drive/drive.pb.h" 11#include "chrome/browser/chromeos/drive/file_system/operation_observer.h" 12#include "chrome/browser/chromeos/drive/resource_metadata.h" 13#include "content/public/browser/browser_thread.h" 14#include "net/base/mime_util.h" 15 16using content::BrowserThread; 17 18namespace drive { 19namespace file_system { 20 21namespace { 22 23const char kMimeTypeOctetStream[] = "application/octet-stream"; 24 25// Updates local state. 26FileError UpdateLocalState(internal::ResourceMetadata* metadata, 27 const base::FilePath& file_path, 28 const std::string& mime_type_in, 29 ResourceEntry* entry) { 30 DCHECK(metadata); 31 32 FileError error = metadata->GetResourceEntryByPath(file_path, entry); 33 if (error == FILE_ERROR_OK) 34 return FILE_ERROR_EXISTS; 35 36 if (error != FILE_ERROR_NOT_FOUND) 37 return error; 38 39 // If parent path is not a directory, it is an error. 40 ResourceEntry parent; 41 if (metadata->GetResourceEntryByPath( 42 file_path.DirName(), &parent) != FILE_ERROR_OK || 43 !parent.file_info().is_directory()) 44 return FILE_ERROR_NOT_A_DIRECTORY; 45 46 // If mime_type is not set or "application/octet-stream", guess from the 47 // |file_path|. If it is still unsure, use octet-stream by default. 48 std::string mime_type = mime_type_in; 49 if ((mime_type.empty() || mime_type == kMimeTypeOctetStream) && 50 !net::GetMimeTypeFromFile(file_path, &mime_type)) 51 mime_type = kMimeTypeOctetStream; 52 53 // Add the entry to the local resource metadata. 54 const base::Time now = base::Time::Now(); 55 entry->mutable_file_info()->set_last_modified(now.ToInternalValue()); 56 entry->mutable_file_info()->set_last_accessed(now.ToInternalValue()); 57 entry->set_title(file_path.BaseName().AsUTF8Unsafe()); 58 entry->set_parent_local_id(parent.local_id()); 59 entry->set_metadata_edit_state(ResourceEntry::DIRTY); 60 entry->set_modification_date(base::Time::Now().ToInternalValue()); 61 entry->mutable_file_specific_info()->set_content_mime_type(mime_type); 62 63 std::string local_id; 64 error = metadata->AddEntry(*entry, &local_id); 65 entry->set_local_id(local_id); 66 return error; 67} 68 69} // namespace 70 71CreateFileOperation::CreateFileOperation( 72 base::SequencedTaskRunner* blocking_task_runner, 73 OperationObserver* observer, 74 internal::ResourceMetadata* metadata) 75 : blocking_task_runner_(blocking_task_runner), 76 observer_(observer), 77 metadata_(metadata), 78 weak_ptr_factory_(this) { 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 80} 81 82CreateFileOperation::~CreateFileOperation() { 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 84} 85 86void CreateFileOperation::CreateFile(const base::FilePath& file_path, 87 bool is_exclusive, 88 const std::string& mime_type, 89 const FileOperationCallback& callback) { 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 91 DCHECK(!callback.is_null()); 92 93 ResourceEntry* entry = new ResourceEntry; 94 base::PostTaskAndReplyWithResult( 95 blocking_task_runner_.get(), 96 FROM_HERE, 97 base::Bind(&UpdateLocalState, 98 metadata_, 99 file_path, 100 mime_type, 101 entry), 102 base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState, 103 weak_ptr_factory_.GetWeakPtr(), 104 callback, 105 file_path, 106 is_exclusive, 107 base::Owned(entry))); 108} 109 110void CreateFileOperation::CreateFileAfterUpdateLocalState( 111 const FileOperationCallback& callback, 112 const base::FilePath& file_path, 113 bool is_exclusive, 114 ResourceEntry* entry, 115 FileError error) { 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 117 DCHECK(!callback.is_null()); 118 119 if (error == FILE_ERROR_EXISTS) { 120 // Error if an exclusive mode is requested, or the entry is not a file. 121 error = (is_exclusive || 122 entry->file_info().is_directory() || 123 entry->file_specific_info().is_hosted_document()) ? 124 FILE_ERROR_EXISTS : FILE_ERROR_OK; 125 } else if (error == FILE_ERROR_OK) { 126 // Notify observer if the file was newly created. 127 observer_->OnDirectoryChangedByOperation(file_path.DirName()); 128 observer_->OnEntryUpdatedByOperation(entry->local_id()); 129 } 130 callback.Run(error); 131} 132 133} // namespace file_system 134} // namespace drive 135