Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system / create_file_operation.cc
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
16 using content::BrowserThread;
17
18 namespace drive {
19 namespace file_system {
20
21 namespace {
22
23 const char kMimeTypeOctetStream[] = "application/octet-stream";
24
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) {
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->mutable_file_specific_info()->set_content_mime_type(mime_type);
61
62   std::string local_id;
63   error = metadata->AddEntry(*entry, &local_id);
64   entry->set_local_id(local_id);
65   return error;
66 }
67
68 }  // namespace
69
70 CreateFileOperation::CreateFileOperation(
71     base::SequencedTaskRunner* blocking_task_runner,
72     OperationObserver* observer,
73     internal::ResourceMetadata* metadata)
74     : blocking_task_runner_(blocking_task_runner),
75       observer_(observer),
76       metadata_(metadata),
77       weak_ptr_factory_(this) {
78   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
79 }
80
81 CreateFileOperation::~CreateFileOperation() {
82   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83 }
84
85 void CreateFileOperation::CreateFile(const base::FilePath& file_path,
86                                      bool is_exclusive,
87                                      const std::string& mime_type,
88                                      const FileOperationCallback& callback) {
89   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90   DCHECK(!callback.is_null());
91
92   ResourceEntry* entry = new ResourceEntry;
93   base::PostTaskAndReplyWithResult(
94       blocking_task_runner_.get(),
95       FROM_HERE,
96       base::Bind(&UpdateLocalState,
97                  metadata_,
98                  file_path,
99                  mime_type,
100                  entry),
101       base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState,
102                  weak_ptr_factory_.GetWeakPtr(),
103                  callback,
104                  file_path,
105                  is_exclusive,
106                  base::Owned(entry)));
107 }
108
109 void CreateFileOperation::CreateFileAfterUpdateLocalState(
110     const FileOperationCallback& callback,
111     const base::FilePath& file_path,
112     bool is_exclusive,
113     ResourceEntry* entry,
114     FileError error) {
115   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116   DCHECK(!callback.is_null());
117
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());
128   }
129   callback.Run(error);
130 }
131
132 }  // namespace file_system
133 }  // namespace drive