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 "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
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"
16 using content::BrowserThread;
19 namespace file_system {
23 const char kMimeTypeOctetStream[] = "application/octet-stream";
25 // Updates local state.
26 FileError UpdateLocalState(internal::ResourceMetadata* metadata,
27 const base::FilePath& file_path,
28 const std::string& mime_type_in,
29 ResourceEntry* entry) {
32 FileError error = metadata->GetResourceEntryByPath(file_path, entry);
33 if (error == FILE_ERROR_OK)
34 return FILE_ERROR_EXISTS;
36 if (error != FILE_ERROR_NOT_FOUND)
39 // If parent path is not a directory, it is an error.
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;
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;
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->mutable_file_specific_info()->set_content_mime_type(mime_type);
63 error = metadata->AddEntry(*entry, &local_id);
64 entry->set_local_id(local_id);
70 CreateFileOperation::CreateFileOperation(
71 base::SequencedTaskRunner* blocking_task_runner,
72 OperationObserver* observer,
73 internal::ResourceMetadata* metadata)
74 : blocking_task_runner_(blocking_task_runner),
77 weak_ptr_factory_(this) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
81 CreateFileOperation::~CreateFileOperation() {
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
85 void CreateFileOperation::CreateFile(const base::FilePath& file_path,
87 const std::string& mime_type,
88 const FileOperationCallback& callback) {
89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90 DCHECK(!callback.is_null());
92 ResourceEntry* entry = new ResourceEntry;
93 base::PostTaskAndReplyWithResult(
94 blocking_task_runner_.get(),
96 base::Bind(&UpdateLocalState,
101 base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState,
102 weak_ptr_factory_.GetWeakPtr(),
106 base::Owned(entry)));
109 void CreateFileOperation::CreateFileAfterUpdateLocalState(
110 const FileOperationCallback& callback,
111 const base::FilePath& file_path,
113 ResourceEntry* entry,
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 DCHECK(!callback.is_null());
118 if (error == FILE_ERROR_EXISTS) {
119 // Error if an exclusive mode is requested, or the entry is not a file.
120 error = (is_exclusive ||
121 entry->file_info().is_directory() ||
122 entry->file_specific_info().is_hosted_document()) ?
123 FILE_ERROR_EXISTS : FILE_ERROR_OK;
124 } else if (error == FILE_ERROR_OK) {
125 // Notify observer if the file was newly created.
126 observer_->OnDirectoryChangedByOperation(file_path.DirName());
127 observer_->OnEntryUpdatedByOperation(entry->local_id());
132 } // namespace file_system