drive_backend_util.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/drive/drive_api_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/drive/drive_api_parser.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/drive/gdata_wapi_parser.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_file_system {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace drive_backend {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMimeTypeOctetStream[] = "application/octet-stream";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PutServiceMetadataToBatch(const ServiceMetadata& service_metadata,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               leveldb::WriteBatch* batch) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = service_metadata.SerializeToString(&value);
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(success);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  batch->Put(kServiceMetadataKey, value);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PutFileToBatch(const FileMetadata& file, leveldb::WriteBatch* batch) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = file.SerializeToString(&value);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(success);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  batch->Put(kFileMetadataKeyPrefix + file.file_id(), value);
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PutTrackerToBatch(const FileTracker& tracker, leveldb::WriteBatch* batch) {
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string value;
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool success = tracker.SerializeToString(&value);
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(success);
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  batch->Put(kFileTrackerKeyPrefix + base::Int64ToString(tracker.tracker_id()),
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             value);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PopulateFileDetailsByFileResource(
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const google_apis::FileResource& file_resource,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileDetails* details) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details->clear_parent_folder_ids();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           file_resource.parents().begin();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       itr != file_resource.parents().end();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++itr) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    details->add_parent_folder_ids((*itr)->file_id());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details->set_title(file_resource.title());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  google_apis::DriveEntryKind kind = drive::util::GetKind(file_resource);
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (kind == google_apis::ENTRY_KIND_FILE)
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    details->set_file_kind(FILE_KIND_FILE);
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else if (kind == google_apis::ENTRY_KIND_FOLDER)
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    details->set_file_kind(FILE_KIND_FOLDER);
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    details->set_file_kind(FILE_KIND_UNSUPPORTED);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details->set_md5(file_resource.md5_checksum());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details->set_etag(file_resource.etag());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details->set_creation_time(file_resource.created_date().ToInternalValue());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  details->set_modification_time(
76      file_resource.modified_date().ToInternalValue());
77  details->set_missing(false);
78}
79
80scoped_ptr<FileMetadata> CreateFileMetadataFromFileResource(
81    int64 change_id,
82    const google_apis::FileResource& resource) {
83  scoped_ptr<FileMetadata> file(new FileMetadata);
84  file->set_file_id(resource.file_id());
85
86  FileDetails* details = file->mutable_details();
87  details->set_change_id(change_id);
88
89  if (resource.labels().is_trashed()) {
90    details->set_missing(true);
91    return file.Pass();
92  }
93
94  PopulateFileDetailsByFileResource(resource, details);
95  return file.Pass();
96}
97
98scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource(
99    const google_apis::ChangeResource& change) {
100  scoped_ptr<FileMetadata> file(new FileMetadata);
101  file->set_file_id(change.file_id());
102
103  FileDetails* details = file->mutable_details();
104  details->set_change_id(change.change_id());
105
106  if (change.is_deleted()) {
107    details->set_missing(true);
108    return file.Pass();
109  }
110
111  PopulateFileDetailsByFileResource(*change.file(), details);
112  return file.Pass();
113}
114
115scoped_ptr<FileMetadata> CreateDeletedFileMetadata(
116    int64 change_id,
117    const std::string& file_id) {
118  scoped_ptr<FileMetadata> file(new FileMetadata);
119  file->set_file_id(file_id);
120
121  FileDetails* details = file->mutable_details();
122  details->set_change_id(change_id);
123  details->set_missing(true);
124  return file.Pass();
125}
126
127webkit_blob::ScopedFile CreateTemporaryFile(
128    base::TaskRunner* file_task_runner) {
129  base::FilePath temp_file_path;
130  if (!base::CreateTemporaryFile(&temp_file_path))
131    return webkit_blob::ScopedFile();
132
133  return webkit_blob::ScopedFile(
134      temp_file_path,
135      webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
136      file_task_runner);
137}
138
139std::string FileKindToString(FileKind file_kind) {
140  switch (file_kind) {
141    case FILE_KIND_UNSUPPORTED:
142      return "unsupported";
143    case FILE_KIND_FILE:
144      return "file";
145    case FILE_KIND_FOLDER:
146      return "folder";
147  }
148
149  NOTREACHED();
150  return "unknown";
151}
152
153bool HasFileAsParent(const FileDetails& details, const std::string& file_id) {
154  for (int i = 0; i < details.parent_folder_ids_size(); ++i) {
155    if (details.parent_folder_ids(i) == file_id)
156      return true;
157  }
158  return false;
159}
160
161std::string GetMimeTypeFromTitle(const base::FilePath& title) {
162  base::FilePath::StringType extension = title.Extension();
163  std::string mime_type;
164  if (extension.empty() ||
165      !net::GetWellKnownMimeTypeFromExtension(extension.substr(1), &mime_type))
166    return kMimeTypeOctetStream;
167  return mime_type;
168}
169
170scoped_ptr<google_apis::ResourceEntry> GetOldestCreatedFolderResource(
171    ScopedVector<google_apis::ResourceEntry> candidates) {
172  scoped_ptr<google_apis::ResourceEntry> oldest;
173  for (size_t i = 0; i < candidates.size(); ++i) {
174    google_apis::ResourceEntry* entry = candidates[i];
175    if (!entry->is_folder() || entry->deleted())
176      continue;
177
178    if (!oldest || oldest->published_time() > entry->published_time()) {
179      oldest.reset(entry);
180      candidates[i] = NULL;
181    }
182  }
183
184  return oldest.Pass();
185}
186
187}  // namespace drive_backend
188}  // namespace sync_file_system
189