Roll src/third_party/WebKit 9f7fb92:f103b33 (svn 202621:202622)
[chromium-blink-merge.git] / components / drive / file_system / create_file_operation.cc
blob19a238e3a6128062e6a09ecf2503df4c9db3bd2f
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/create_file_operation.h"
7 #include <string>
9 #include "base/files/file_util.h"
10 #include "components/drive/drive.pb.h"
11 #include "components/drive/file_change.h"
12 #include "components/drive/file_system/operation_delegate.h"
13 #include "components/drive/job_scheduler.h"
14 #include "components/drive/resource_metadata.h"
15 #include "net/base/mime_util.h"
17 namespace drive {
18 namespace file_system {
20 namespace {
22 const char kMimeTypeOctetStream[] = "application/octet-stream";
24 // Updates local state.
25 FileError UpdateLocalState(internal::ResourceMetadata* metadata,
26 const base::FilePath& file_path,
27 const std::string& mime_type_in,
28 ResourceEntry* entry) {
29 DCHECK(metadata);
31 FileError error = metadata->GetResourceEntryByPath(file_path, entry);
32 if (error == FILE_ERROR_OK)
33 return FILE_ERROR_EXISTS;
35 if (error != FILE_ERROR_NOT_FOUND)
36 return error;
38 // If parent path is not a directory, it is an error.
39 ResourceEntry parent;
40 if (metadata->GetResourceEntryByPath(
41 file_path.DirName(), &parent) != FILE_ERROR_OK ||
42 !parent.file_info().is_directory())
43 return FILE_ERROR_NOT_A_DIRECTORY;
45 // If mime_type is not set or "application/octet-stream", guess from the
46 // |file_path|. If it is still unsure, use octet-stream by default.
47 std::string mime_type = mime_type_in;
48 if ((mime_type.empty() || mime_type == kMimeTypeOctetStream) &&
49 !net::GetMimeTypeFromFile(file_path, &mime_type))
50 mime_type = kMimeTypeOctetStream;
52 // Add the entry to the local resource metadata.
53 const base::Time now = base::Time::Now();
54 entry->mutable_file_info()->set_last_modified(now.ToInternalValue());
55 entry->mutable_file_info()->set_last_accessed(now.ToInternalValue());
56 entry->set_title(file_path.BaseName().AsUTF8Unsafe());
57 entry->set_parent_local_id(parent.local_id());
58 entry->set_metadata_edit_state(ResourceEntry::DIRTY);
59 entry->set_modification_date(base::Time::Now().ToInternalValue());
60 entry->mutable_file_specific_info()->set_content_mime_type(mime_type);
62 std::string local_id;
63 error = metadata->AddEntry(*entry, &local_id);
64 entry->set_local_id(local_id);
65 return error;
68 } // namespace
70 CreateFileOperation::CreateFileOperation(
71 base::SequencedTaskRunner* blocking_task_runner,
72 OperationDelegate* delegate,
73 internal::ResourceMetadata* metadata)
74 : blocking_task_runner_(blocking_task_runner),
75 delegate_(delegate),
76 metadata_(metadata),
77 weak_ptr_factory_(this) {
80 CreateFileOperation::~CreateFileOperation() {
81 DCHECK(thread_checker_.CalledOnValidThread());
84 void CreateFileOperation::CreateFile(const base::FilePath& file_path,
85 bool is_exclusive,
86 const std::string& mime_type,
87 const FileOperationCallback& callback) {
88 DCHECK(thread_checker_.CalledOnValidThread());
89 DCHECK(!callback.is_null());
91 ResourceEntry* entry = new ResourceEntry;
92 base::PostTaskAndReplyWithResult(
93 blocking_task_runner_.get(),
94 FROM_HERE,
95 base::Bind(&UpdateLocalState,
96 metadata_,
97 file_path,
98 mime_type,
99 entry),
100 base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState,
101 weak_ptr_factory_.GetWeakPtr(),
102 callback,
103 file_path,
104 is_exclusive,
105 base::Owned(entry)));
108 void CreateFileOperation::CreateFileAfterUpdateLocalState(
109 const FileOperationCallback& callback,
110 const base::FilePath& file_path,
111 bool is_exclusive,
112 ResourceEntry* entry,
113 FileError error) {
114 DCHECK(thread_checker_.CalledOnValidThread());
115 DCHECK(!callback.is_null());
117 if (error == FILE_ERROR_EXISTS) {
118 // Error if an exclusive mode is requested, or the entry is not a file.
119 error = (is_exclusive ||
120 entry->file_info().is_directory() ||
121 entry->file_specific_info().is_hosted_document()) ?
122 FILE_ERROR_EXISTS : FILE_ERROR_OK;
123 } else if (error == FILE_ERROR_OK) {
124 DCHECK(!entry->file_info().is_directory());
126 // Notify delegate if the file was newly created.
127 FileChange changed_file;
128 changed_file.Update(file_path, FileChange::FILE_TYPE_FILE,
129 FileChange::CHANGE_TYPE_ADD_OR_UPDATE);
130 delegate_->OnFileChangedByOperation(changed_file);
131 // Synchronize in the background.
132 delegate_->OnEntryUpdatedByOperation(ClientContext(BACKGROUND),
133 entry->local_id());
135 callback.Run(error);
138 } // namespace file_system
139 } // namespace drive