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/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
;
21 namespace file_system
{
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
) {
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
)
41 // If parent path is not a directory, it is an error.
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
);
66 error
= metadata
->AddEntry(*entry
, &local_id
);
67 entry
->set_local_id(local_id
);
73 CreateFileOperation::CreateFileOperation(
74 base::SequencedTaskRunner
* blocking_task_runner
,
75 OperationDelegate
* delegate
,
76 internal::ResourceMetadata
* metadata
)
77 : blocking_task_runner_(blocking_task_runner
),
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
,
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(),
99 base::Bind(&UpdateLocalState
,
104 base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState
,
105 weak_ptr_factory_
.GetWeakPtr(),
109 base::Owned(entry
)));
112 void CreateFileOperation::CreateFileAfterUpdateLocalState(
113 const FileOperationCallback
& callback
,
114 const base::FilePath
& file_path
,
116 ResourceEntry
* entry
,
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
;
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
),
142 } // namespace file_system