drive_backend_util.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/google_apis/drive_api_parser.h"
14#include "chrome/browser/google_apis/gdata_wapi_parser.h"
15#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
16#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
17#include "net/base/mime_util.h"
18#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
19
20namespace sync_file_system {
21namespace drive_backend {
22
23namespace {
24
25const char kMimeTypeOctetStream[] = "application/octet-stream";
26
27}  // namespace
28
29void PutServiceMetadataToBatch(const ServiceMetadata& service_metadata,
30                               leveldb::WriteBatch* batch) {
31  std::string value;
32  bool success = service_metadata.SerializeToString(&value);
33  DCHECK(success);
34  batch->Put(kServiceMetadataKey, value);
35}
36
37void PutFileToBatch(const FileMetadata& file, leveldb::WriteBatch* batch) {
38  std::string value;
39  bool success = file.SerializeToString(&value);
40  DCHECK(success);
41  batch->Put(kFileMetadataKeyPrefix + file.file_id(), value);
42}
43
44void PutTrackerToBatch(const FileTracker& tracker, leveldb::WriteBatch* batch) {
45  std::string value;
46  bool success = tracker.SerializeToString(&value);
47  DCHECK(success);
48  batch->Put(kFileTrackerKeyPrefix + base::Int64ToString(tracker.tracker_id()),
49             value);
50}
51
52void PopulateFileDetailsByFileResource(
53    const google_apis::FileResource& file_resource,
54    FileDetails* details) {
55  details->clear_parent_folder_ids();
56  for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
57           file_resource.parents().begin();
58       itr != file_resource.parents().end();
59       ++itr) {
60    details->add_parent_folder_ids((*itr)->file_id());
61  }
62  details->set_title(file_resource.title());
63
64  google_apis::DriveEntryKind kind = drive::util::GetKind(file_resource);
65  if (kind == google_apis::ENTRY_KIND_FILE)
66    details->set_file_kind(FILE_KIND_FILE);
67  else if (kind == google_apis::ENTRY_KIND_FOLDER)
68    details->set_file_kind(FILE_KIND_FOLDER);
69  else
70    details->set_file_kind(FILE_KIND_UNSUPPORTED);
71
72  details->set_md5(file_resource.md5_checksum());
73  details->set_etag(file_resource.etag());
74  details->set_creation_time(file_resource.created_date().ToInternalValue());
75  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
115webkit_blob::ScopedFile CreateTemporaryFile() {
116  base::FilePath temp_file_path;
117  if (!file_util::CreateTemporaryFile(&temp_file_path))
118    return webkit_blob::ScopedFile();
119
120  return webkit_blob::ScopedFile(
121      temp_file_path,
122      webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
123      base::MessageLoopProxy::current().get());
124}
125
126std::string FileKindToString(FileKind file_kind) {
127  switch (file_kind) {
128    case FILE_KIND_UNSUPPORTED:
129      return "unsupported";
130    case FILE_KIND_FILE:
131      return "file";
132    case FILE_KIND_FOLDER:
133      return "folder";
134  }
135
136  NOTREACHED();
137  return "unknown";
138}
139
140bool HasFileAsParent(const FileDetails& details, const std::string& file_id) {
141  for (int i = 0; i < details.parent_folder_ids_size(); ++i) {
142    if (details.parent_folder_ids(i) == file_id)
143      return true;
144  }
145  return false;
146}
147
148std::string GetMimeTypeFromTitle(const base::FilePath& title) {
149  base::FilePath::StringType extension = title.Extension();
150  std::string mime_type;
151  if (extension.empty() ||
152      !net::GetWellKnownMimeTypeFromExtension(extension.substr(1), &mime_type))
153    return kMimeTypeOctetStream;
154  return mime_type;
155}
156
157scoped_ptr<google_apis::ResourceEntry> GetOldestCreatedFolderResource(
158    ScopedVector<google_apis::ResourceEntry> candidates) {
159  scoped_ptr<google_apis::ResourceEntry> oldest;
160  for (size_t i = 0; i < candidates.size(); ++i) {
161    google_apis::ResourceEntry* entry = candidates[i];
162    if (!entry->is_folder())
163      continue;
164
165    if (!oldest || oldest->published_time() > entry->published_time()) {
166      oldest.reset(entry);
167      candidates[i] = NULL;
168    }
169  }
170
171  return oldest.Pass();
172}
173
174}  // namespace drive_backend
175}  // namespace sync_file_system
176