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