Home | History | Annotate | Download | only in drive_backend
      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 "google_apis/drive/drive_api_parser.h"
     16 #include "google_apis/drive/gdata_wapi_parser.h"
     17 #include "net/base/mime_util.h"
     18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
     19 
     20 namespace sync_file_system {
     21 namespace drive_backend {
     22 
     23 namespace {
     24 
     25 const char kMimeTypeOctetStream[] = "application/octet-stream";
     26 
     27 }  // namespace
     28 
     29 void 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 
     37 void 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 
     44 void 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 
     52 void 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 
     80 scoped_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 
     98 scoped_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 
    115 scoped_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 
    127 webkit_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 
    139 std::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 
    153 bool 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 
    161 std::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 
    170 scoped_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