Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / file_system / update_operation.cc
blob6ce958f65faa26f6c540d753ecb54ab3745f2918
1 // Copyright (c) 2012 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/update_operation.h"
7 #include "base/platform_file.h"
8 #include "chrome/browser/chromeos/drive/drive.pb.h"
9 #include "chrome/browser/chromeos/drive/file_cache.h"
10 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
11 #include "chrome/browser/chromeos/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/drive/job_scheduler.h"
13 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
14 #include "chrome/browser/chromeos/drive/resource_metadata.h"
15 #include "chrome/browser/drive/drive_api_util.h"
16 #include "content/public/browser/browser_thread.h"
18 using content::BrowserThread;
20 namespace drive {
21 namespace file_system {
23 struct UpdateOperation::LocalState {
24 LocalState() : content_is_same(false) {
27 std::string local_id;
28 ResourceEntry entry;
29 base::FilePath drive_file_path;
30 base::FilePath cache_file_path;
31 bool content_is_same;
34 namespace {
36 // Gets locally stored information about the specified file.
37 FileError GetFileLocalState(internal::ResourceMetadata* metadata,
38 internal::FileCache* cache,
39 UpdateOperation::ContentCheckMode check,
40 UpdateOperation::LocalState* local_state) {
41 FileError error = metadata->GetResourceEntryById(local_state->local_id,
42 &local_state->entry);
43 if (error != FILE_ERROR_OK)
44 return error;
46 if (local_state->entry.file_info().is_directory())
47 return FILE_ERROR_NOT_A_FILE;
49 local_state->drive_file_path = metadata->GetFilePath(local_state->local_id);
50 if (local_state->drive_file_path.empty())
51 return FILE_ERROR_NOT_FOUND;
53 error = cache->GetFile(local_state->local_id, &local_state->cache_file_path);
54 if (error != FILE_ERROR_OK)
55 return error;
57 if (check == UpdateOperation::RUN_CONTENT_CHECK) {
58 const std::string& md5 = util::GetMd5Digest(local_state->cache_file_path);
59 local_state->content_is_same =
60 (md5 == local_state->entry.file_specific_info().md5());
61 if (local_state->content_is_same)
62 cache->ClearDirty(local_state->local_id, md5);
63 } else {
64 local_state->content_is_same = false;
67 return FILE_ERROR_OK;
70 // Updates locally stored information about the specified file.
71 FileError UpdateFileLocalState(
72 internal::ResourceMetadata* metadata,
73 internal::FileCache* cache,
74 const std::string& local_id,
75 scoped_ptr<google_apis::ResourceEntry> resource_entry,
76 base::FilePath* drive_file_path) {
77 ResourceEntry existing_entry;
78 FileError error = metadata->GetResourceEntryById(local_id, &existing_entry);
79 if (error != FILE_ERROR_OK)
80 return error;
82 ResourceEntry entry;
83 std::string parent_resource_id;
84 if (!ConvertToResourceEntry(*resource_entry, &entry, &parent_resource_id))
85 return FILE_ERROR_NOT_A_FILE;
87 entry.set_local_id(local_id);
88 entry.set_parent_local_id(existing_entry.parent_local_id());
90 error = metadata->RefreshEntry(entry);
91 if (error != FILE_ERROR_OK)
92 return error;
94 *drive_file_path = metadata->GetFilePath(local_id);
95 if (drive_file_path->empty())
96 return FILE_ERROR_NOT_FOUND;
98 // Do not clear the dirty bit if someone is writing to the file.
99 if (cache->IsOpenedForWrite(local_id))
100 return FILE_ERROR_OK;
101 return cache->ClearDirty(local_id, entry.file_specific_info().md5());
104 } // namespace
106 UpdateOperation::UpdateOperation(
107 base::SequencedTaskRunner* blocking_task_runner,
108 OperationObserver* observer,
109 JobScheduler* scheduler,
110 internal::ResourceMetadata* metadata,
111 internal::FileCache* cache)
112 : blocking_task_runner_(blocking_task_runner),
113 observer_(observer),
114 scheduler_(scheduler),
115 metadata_(metadata),
116 cache_(cache),
117 weak_ptr_factory_(this) {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
121 UpdateOperation::~UpdateOperation() {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
125 void UpdateOperation::UpdateFileByLocalId(
126 const std::string& local_id,
127 const ClientContext& context,
128 ContentCheckMode check,
129 const FileOperationCallback& callback) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
131 DCHECK(!callback.is_null());
133 LocalState* local_state = new LocalState;
134 local_state->local_id = local_id;
135 base::PostTaskAndReplyWithResult(
136 blocking_task_runner_.get(),
137 FROM_HERE,
138 base::Bind(&GetFileLocalState,
139 metadata_,
140 cache_,
141 check,
142 local_state),
143 base::Bind(&UpdateOperation::UpdateFileAfterGetLocalState,
144 weak_ptr_factory_.GetWeakPtr(),
145 context,
146 callback,
147 base::Owned(local_state)));
150 void UpdateOperation::UpdateFileAfterGetLocalState(
151 const ClientContext& context,
152 const FileOperationCallback& callback,
153 const LocalState* local_state,
154 FileError error) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156 DCHECK(!callback.is_null());
158 if (error != FILE_ERROR_OK || local_state->content_is_same) {
159 callback.Run(error);
160 return;
163 scheduler_->UploadExistingFile(
164 local_state->entry.resource_id(),
165 local_state->drive_file_path,
166 local_state->cache_file_path,
167 local_state->entry.file_specific_info().content_mime_type(),
168 "", // etag
169 context,
170 base::Bind(&UpdateOperation::UpdateFileAfterUpload,
171 weak_ptr_factory_.GetWeakPtr(),
172 callback,
173 local_state->local_id));
176 void UpdateOperation::UpdateFileAfterUpload(
177 const FileOperationCallback& callback,
178 const std::string& local_id,
179 google_apis::GDataErrorCode error,
180 scoped_ptr<google_apis::ResourceEntry> resource_entry) {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 DCHECK(!callback.is_null());
184 FileError drive_error = GDataToFileError(error);
185 if (drive_error != FILE_ERROR_OK) {
186 callback.Run(drive_error);
187 return;
190 base::FilePath* drive_file_path = new base::FilePath;
191 base::PostTaskAndReplyWithResult(
192 blocking_task_runner_.get(),
193 FROM_HERE,
194 base::Bind(&UpdateFileLocalState,
195 metadata_,
196 cache_,
197 local_id,
198 base::Passed(&resource_entry),
199 drive_file_path),
200 base::Bind(&UpdateOperation::UpdateFileAfterUpdateLocalState,
201 weak_ptr_factory_.GetWeakPtr(),
202 callback,
203 base::Owned(drive_file_path)));
206 void UpdateOperation::UpdateFileAfterUpdateLocalState(
207 const FileOperationCallback& callback,
208 const base::FilePath* drive_file_path,
209 FileError error) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211 DCHECK(!callback.is_null());
213 if (error != FILE_ERROR_OK) {
214 callback.Run(error);
215 return;
217 observer_->OnDirectoryChangedByOperation(drive_file_path->DirName());
218 callback.Run(FILE_ERROR_OK);
221 } // namespace file_system
222 } // namespace drive