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"
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"
18 namespace file_system
{
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
) {
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
)
38 // If parent path is not a directory, it is an error.
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
);
63 error
= metadata
->AddEntry(*entry
, &local_id
);
64 entry
->set_local_id(local_id
);
70 CreateFileOperation::CreateFileOperation(
71 base::SequencedTaskRunner
* blocking_task_runner
,
72 OperationDelegate
* delegate
,
73 internal::ResourceMetadata
* metadata
)
74 : blocking_task_runner_(blocking_task_runner
),
77 weak_ptr_factory_(this) {
80 CreateFileOperation::~CreateFileOperation() {
81 DCHECK(thread_checker_
.CalledOnValidThread());
84 void CreateFileOperation::CreateFile(const base::FilePath
& file_path
,
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(),
95 base::Bind(&UpdateLocalState
,
100 base::Bind(&CreateFileOperation::CreateFileAfterUpdateLocalState
,
101 weak_ptr_factory_
.GetWeakPtr(),
105 base::Owned(entry
)));
108 void CreateFileOperation::CreateFileAfterUpdateLocalState(
109 const FileOperationCallback
& callback
,
110 const base::FilePath
& file_path
,
112 ResourceEntry
* entry
,
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
),
138 } // namespace file_system