• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/sync_file_system/drive_backend/drive_backend_util.h"
6 
7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/drive/drive_api_util.h"
13 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
14 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
15 #include "chrome/browser/sync_file_system/logger.h"
16 #include "google_apis/drive/drive_api_parser.h"
17 #include "google_apis/drive/gdata_wapi_parser.h"
18 #include "net/base/mime_util.h"
19 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
20 
21 namespace sync_file_system {
22 namespace drive_backend {
23 
PutServiceMetadataToBatch(const ServiceMetadata & service_metadata,leveldb::WriteBatch * batch)24 void PutServiceMetadataToBatch(const ServiceMetadata& service_metadata,
25                                leveldb::WriteBatch* batch) {
26   std::string value;
27   bool success = service_metadata.SerializeToString(&value);
28   DCHECK(success);
29   batch->Put(kServiceMetadataKey, value);
30 }
31 
PutFileMetadataToBatch(const FileMetadata & file,leveldb::WriteBatch * batch)32 void PutFileMetadataToBatch(const FileMetadata& file,
33                             leveldb::WriteBatch* batch) {
34   if (!batch)
35     return;
36 
37   std::string value;
38   bool success = file.SerializeToString(&value);
39   DCHECK(success);
40   batch->Put(kFileMetadataKeyPrefix + file.file_id(), value);
41 }
42 
PutFileTrackerToBatch(const FileTracker & tracker,leveldb::WriteBatch * batch)43 void PutFileTrackerToBatch(const FileTracker& tracker,
44                            leveldb::WriteBatch* batch) {
45   if (!batch)
46     return;
47 
48   std::string value;
49   bool success = tracker.SerializeToString(&value);
50   DCHECK(success);
51   batch->Put(kFileTrackerKeyPrefix + base::Int64ToString(tracker.tracker_id()),
52              value);
53 }
54 
PutFileMetadataDeletionToBatch(const std::string & file_id,leveldb::WriteBatch * batch)55 void PutFileMetadataDeletionToBatch(const std::string& file_id,
56                                     leveldb::WriteBatch* batch) {
57   if (batch)
58     batch->Delete(kFileMetadataKeyPrefix + file_id);
59 }
60 
PutFileTrackerDeletionToBatch(int64 tracker_id,leveldb::WriteBatch * batch)61 void PutFileTrackerDeletionToBatch(int64 tracker_id,
62                                    leveldb::WriteBatch* batch) {
63   if (batch)
64     batch->Delete(kFileTrackerKeyPrefix + base::Int64ToString(tracker_id));
65 }
66 
PopulateFileDetailsByFileResource(const google_apis::FileResource & file_resource,FileDetails * details)67 void PopulateFileDetailsByFileResource(
68     const google_apis::FileResource& file_resource,
69     FileDetails* details) {
70   details->clear_parent_folder_ids();
71   for (std::vector<google_apis::ParentReference>::const_iterator itr =
72            file_resource.parents().begin();
73        itr != file_resource.parents().end();
74        ++itr) {
75     details->add_parent_folder_ids(itr->file_id());
76   }
77   details->set_title(file_resource.title());
78 
79   google_apis::DriveEntryKind kind = drive::util::GetKind(file_resource);
80   if (kind == google_apis::ENTRY_KIND_FILE)
81     details->set_file_kind(FILE_KIND_FILE);
82   else if (kind == google_apis::ENTRY_KIND_FOLDER)
83     details->set_file_kind(FILE_KIND_FOLDER);
84   else
85     details->set_file_kind(FILE_KIND_UNSUPPORTED);
86 
87   details->set_md5(file_resource.md5_checksum());
88   details->set_etag(file_resource.etag());
89   details->set_creation_time(file_resource.created_date().ToInternalValue());
90   details->set_modification_time(
91       file_resource.modified_date().ToInternalValue());
92   details->set_missing(file_resource.labels().is_trashed());
93 }
94 
CreateFileMetadataFromFileResource(int64 change_id,const google_apis::FileResource & resource)95 scoped_ptr<FileMetadata> CreateFileMetadataFromFileResource(
96     int64 change_id,
97     const google_apis::FileResource& resource) {
98   scoped_ptr<FileMetadata> file(new FileMetadata);
99   file->set_file_id(resource.file_id());
100 
101   FileDetails* details = file->mutable_details();
102   details->set_change_id(change_id);
103 
104   if (resource.labels().is_trashed()) {
105     details->set_missing(true);
106     return file.Pass();
107   }
108 
109   PopulateFileDetailsByFileResource(resource, details);
110   return file.Pass();
111 }
112 
CreateFileMetadataFromChangeResource(const google_apis::ChangeResource & change)113 scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource(
114     const google_apis::ChangeResource& change) {
115   scoped_ptr<FileMetadata> file(new FileMetadata);
116   file->set_file_id(change.file_id());
117 
118   FileDetails* details = file->mutable_details();
119   details->set_change_id(change.change_id());
120 
121   if (change.is_deleted()) {
122     details->set_missing(true);
123     return file.Pass();
124   }
125 
126   PopulateFileDetailsByFileResource(*change.file(), details);
127   return file.Pass();
128 }
129 
CreateDeletedFileMetadata(int64 change_id,const std::string & file_id)130 scoped_ptr<FileMetadata> CreateDeletedFileMetadata(
131     int64 change_id,
132     const std::string& file_id) {
133   scoped_ptr<FileMetadata> file(new FileMetadata);
134   file->set_file_id(file_id);
135 
136   FileDetails* details = file->mutable_details();
137   details->set_change_id(change_id);
138   details->set_missing(true);
139   return file.Pass();
140 }
141 
CreateTemporaryFile(base::TaskRunner * file_task_runner)142 webkit_blob::ScopedFile CreateTemporaryFile(
143     base::TaskRunner* file_task_runner) {
144   base::FilePath temp_file_path;
145   if (!base::CreateTemporaryFile(&temp_file_path))
146     return webkit_blob::ScopedFile();
147 
148   return webkit_blob::ScopedFile(
149       temp_file_path,
150       webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
151       file_task_runner);
152 }
153 
FileKindToString(FileKind file_kind)154 std::string FileKindToString(FileKind file_kind) {
155   switch (file_kind) {
156     case FILE_KIND_UNSUPPORTED:
157       return "unsupported";
158     case FILE_KIND_FILE:
159       return "file";
160     case FILE_KIND_FOLDER:
161       return "folder";
162   }
163 
164   NOTREACHED();
165   return "unknown";
166 }
167 
HasFileAsParent(const FileDetails & details,const std::string & file_id)168 bool HasFileAsParent(const FileDetails& details, const std::string& file_id) {
169   for (int i = 0; i < details.parent_folder_ids_size(); ++i) {
170     if (details.parent_folder_ids(i) == file_id)
171       return true;
172   }
173   return false;
174 }
175 
GetMimeTypeFromTitle(const base::FilePath & title)176 std::string GetMimeTypeFromTitle(const base::FilePath& title) {
177   base::FilePath::StringType extension = title.Extension();
178   std::string mime_type;
179   if (extension.empty() ||
180       !net::GetWellKnownMimeTypeFromExtension(extension.substr(1), &mime_type))
181     return kMimeTypeOctetStream;
182   return mime_type;
183 }
184 
GDataErrorCodeToSyncStatusCode(google_apis::GDataErrorCode error)185 SyncStatusCode GDataErrorCodeToSyncStatusCode(
186     google_apis::GDataErrorCode error) {
187   // NOTE: Please update DriveFileSyncService::UpdateServiceState when you add
188   // more error code mapping.
189   switch (error) {
190     case google_apis::HTTP_SUCCESS:
191     case google_apis::HTTP_CREATED:
192     case google_apis::HTTP_NO_CONTENT:
193     case google_apis::HTTP_FOUND:
194       return SYNC_STATUS_OK;
195 
196     case google_apis::HTTP_NOT_MODIFIED:
197       return SYNC_STATUS_NOT_MODIFIED;
198 
199     case google_apis::HTTP_CONFLICT:
200     case google_apis::HTTP_PRECONDITION:
201       return SYNC_STATUS_HAS_CONFLICT;
202 
203     case google_apis::HTTP_UNAUTHORIZED:
204       return SYNC_STATUS_AUTHENTICATION_FAILED;
205 
206     case google_apis::GDATA_NO_CONNECTION:
207       return SYNC_STATUS_NETWORK_ERROR;
208 
209     case google_apis::HTTP_INTERNAL_SERVER_ERROR:
210     case google_apis::HTTP_BAD_GATEWAY:
211     case google_apis::HTTP_SERVICE_UNAVAILABLE:
212     case google_apis::GDATA_CANCELLED:
213     case google_apis::GDATA_NOT_READY:
214       return SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE;
215 
216     case google_apis::HTTP_NOT_FOUND:
217     case google_apis::HTTP_GONE:
218       return SYNC_FILE_ERROR_NOT_FOUND;
219 
220     case google_apis::GDATA_FILE_ERROR:
221       return SYNC_FILE_ERROR_FAILED;
222 
223     case google_apis::HTTP_FORBIDDEN:
224       return SYNC_STATUS_ACCESS_FORBIDDEN;
225 
226     case google_apis::HTTP_RESUME_INCOMPLETE:
227     case google_apis::HTTP_BAD_REQUEST:
228     case google_apis::HTTP_LENGTH_REQUIRED:
229     case google_apis::HTTP_NOT_IMPLEMENTED:
230     case google_apis::GDATA_PARSE_ERROR:
231     case google_apis::GDATA_OTHER_ERROR:
232       return SYNC_STATUS_FAILED;
233 
234     case google_apis::GDATA_NO_SPACE:
235       return SYNC_FILE_ERROR_NO_SPACE;
236   }
237 
238   // There's a case where DriveService layer returns GDataErrorCode==-1
239   // when network is unavailable. (http://crbug.com/223042)
240   // TODO(kinuko,nhiroki): We should identify from where this undefined error
241   // code is coming.
242   if (error == -1)
243     return SYNC_STATUS_NETWORK_ERROR;
244 
245   util::Log(logging::LOG_WARNING,
246             FROM_HERE,
247             "Got unexpected error: %d",
248             static_cast<int>(error));
249   return SYNC_STATUS_FAILED;
250 }
251 
CloneFileTracker(const FileTracker * obj)252 scoped_ptr<FileTracker> CloneFileTracker(const FileTracker* obj) {
253   if (!obj)
254     return scoped_ptr<FileTracker>();
255   return scoped_ptr<FileTracker>(new FileTracker(*obj));
256 }
257 
258 }  // namespace drive_backend
259 }  // namespace sync_file_system
260