Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / file_system / create_file_operation.cc
blobafbc20cf19bc733eb3e210159de58ff2d343cf10
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"
7 #include <string>
9 #include "base/files/file_util.h"
10 #include "chrome/browser/chromeos/drive/drive.pb.h"
11 #include "chrome/browser/chromeos/drive/file_change.h"
12 #include "chrome/browser/chromeos/drive/file_system/operation_delegate.h"
13 #include "chrome/browser/chromeos/drive/job_scheduler.h"
14 #include "chrome/browser/chromeos/drive/resource_metadata.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "net/base/mime_util.h"
18 using content::BrowserThread;
20 namespace drive {
21 namespace file_system {
23 namespace {
25 const char kMimeTypeOctetStream[] = "application/octet-stream";
27 // Updates local state.
28 FileError UpdateLocalState(internal::ResourceMetadata* metadata,
29 const base::FilePath& file_path,
30 const std::string& mime_type_in,
31 ResourceEntry* entry) {
32 DCHECK(metadata);
34 FileError error = metadata->GetResourceEntryByPath(file_path, entry);
35 if (error == FILE_ERROR_OK)
36 return FILE_ERROR_EXISTS;
38 if (error != FILE_ERROR_NOT_FOUND)
39 return error;
41 // If parent path is not a directory, it is an error.
42 ResourceEntry parent;
43 if (metadata->GetResourceEntryByPath(
44 file_path.DirName(), &parent) != FILE_ERROR_OK ||
45 !parent.file_info().is_directory())
46 return FILE_ERROR_NOT_A_DIRECTORY;
48 // If mime_type is not set or "application/octet-stream", guess from the
49 // |file_path|. If it is still unsure, use octet-stream by default.
50 std::string mime_type = mime_type_in;
51 if ((mime_type.empty() || mime_type == kMimeTypeOctetStream) &&
52 !net::GetMimeTypeFromFile(file_path, &mime_type))
53 mime_type = kMimeTypeOctetStream;
55 // Add the entry to the local resource metadata.
56 const base::Time now = base::Time::Now();
57 entry->mutable_file_info()->set_last_modified(now.ToInternalValue());
58 entry->mutable_file_info()->set_last_accessed(now.ToInternalValue());
59 entry->set_title(file_path.BaseName().AsUTF8Unsafe());
60 entry->set_parent_local_id(parent.local_id());
61 entry->set_metadata_edit_state(ResourceEntry::DIRTY);
62 entry->set_modification_date(base::Time::Now().ToInternalValue());
63 entry->mutable_file_specific_info()->set_content_mime_type(mime_type);
65 std::string local_id;
66 error = metadata->AddEntry(*entry, &local_id);
67 entry->set_local_id(local_id);
68 return error;
71 } // namespace
73 CreateFileOperation::CreateFileOperation(
74 base::SequencedTaskRunner* blocking_task_runner,
75 OperationDelegate* delegate,
76 internal::ResourceMetadata* metadata)
77 : blocking_task_runner_(blocking_task_runner),
78 delegate_(delegate),
79 metadata_(metadata),
80 weak_ptr_factory_(this) {
81 DCHECK_CURRENTLY_ON(BrowserThread::UI);
84 CreateFileOperation::~CreateFileOperation() {
85 DCHECK_CURRENTLY_ON(BrowserThread::UI);
88 void CreateFileOperation::CreateFile(const base::FilePath& file_path,
89 bool is_exclusive,
90 const std::string& mime_type,
91 const FileOperationCallback& callback) {
92 DCHECK_CURRENTLY_ON(BrowserThread::UI);
93 DCHECK(!callback.is_null());
95 ResourceEntry* entry = new ResourceEntry;
96 base::PostTaskAndReplyWithResult(
97 blocking_task_runner_.get(),
98 FROM_HERE,
99 base::Bind(&UpdateLocalState,
100 metadata_,
101 file_path,
102 mime_type,
103 entry),
104 base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState,
105 weak_ptr_factory_.GetWeakPtr(),
106 callback,
107 file_path,
108 is_exclusive,
109 base::Owned(entry)));
112 void CreateFileOperation::CreateFileAfterUpdateLocalState(
113 const FileOperationCallback& callback,
114 const base::FilePath& file_path,
115 bool is_exclusive,
116 ResourceEntry* entry,
117 FileError error) {
118 DCHECK_CURRENTLY_ON(BrowserThread::UI);
119 DCHECK(!callback.is_null());
121 if (error == FILE_ERROR_EXISTS) {
122 // Error if an exclusive mode is requested, or the entry is not a file.
123 error = (is_exclusive ||
124 entry->file_info().is_directory() ||
125 entry->file_specific_info().is_hosted_document()) ?
126 FILE_ERROR_EXISTS : FILE_ERROR_OK;
127 } else if (error == FILE_ERROR_OK) {
128 DCHECK(!entry->file_info().is_directory());
130 // Notify delegate if the file was newly created.
131 FileChange changed_file;
132 changed_file.Update(
133 file_path, FileChange::FILE_TYPE_FILE, FileChange::ADD_OR_UPDATE);
134 delegate_->OnFileChangedByOperation(changed_file);
135 // Synchronize in the background.
136 delegate_->OnEntryUpdatedByOperation(ClientContext(BACKGROUND),
137 entry->local_id());
139 callback.Run(error);
142 } // namespace file_system
143 } // namespace drive