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/fake_api_util.h" 6 7#include <algorithm> 8 9#include "base/bind.h" 10#include "base/location.h" 11#include "base/message_loop/message_loop_proxy.h" 12#include "chrome/browser/google_apis/drive_entry_kinds.h" 13#include "webkit/common/blob/scoped_file.h" 14 15namespace sync_file_system { 16namespace drive_backend { 17 18bool FakeAPIUtil::RemoteResourceComparator::operator()( 19 const RemoteResource& left, 20 const RemoteResource& right) { 21 if (left.parent_resource_id != right.parent_resource_id) 22 return left.parent_resource_id < right.parent_resource_id; 23 if (left.parent_title != right.parent_title) 24 return left.parent_title < right.parent_title; 25 if (left.title != right.title) 26 return left.title < right.title; 27 if (left.resource_id != right.resource_id) 28 return left.resource_id < right.resource_id; 29 if (left.md5_checksum != right.md5_checksum) 30 return left.md5_checksum < right.md5_checksum; 31 if (left.deleted != right.deleted) 32 return left.deleted < right.deleted; 33 return left.changestamp < right.changestamp; 34} 35 36struct FakeAPIUtil::ChangeStampComparator { 37 bool operator()(const google_apis::ResourceEntry* left, 38 const google_apis::ResourceEntry* right) { 39 return left->changestamp() < right->changestamp(); 40 } 41}; 42 43FakeAPIUtil::RemoteResource::RemoteResource() 44 : type(SYNC_FILE_TYPE_UNKNOWN), deleted(false), changestamp(0) {} 45 46FakeAPIUtil::RemoteResource::RemoteResource( 47 const std::string& parent_resource_id, 48 const std::string& parent_title, 49 const std::string& title, 50 const std::string& resource_id, 51 const std::string& md5_checksum, 52 SyncFileType type, 53 bool deleted, 54 int64 changestamp) 55 : parent_resource_id(parent_resource_id), 56 parent_title(parent_title), 57 title(title), 58 resource_id(resource_id), 59 md5_checksum(md5_checksum), 60 type(type), 61 deleted(deleted), 62 changestamp(changestamp) {} 63 64FakeAPIUtil::RemoteResource::~RemoteResource() {} 65 66FakeAPIUtil::FakeAPIUtil() 67 : largest_changestamp_(0), 68 url_generator_( 69 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), 70 GURL(google_apis::GDataWapiUrlGenerator:: 71 kBaseDownloadUrlForProduction)) {} 72 73FakeAPIUtil::~FakeAPIUtil() {} 74 75void FakeAPIUtil::AddObserver(APIUtilObserver* observer) {} 76 77void FakeAPIUtil::RemoveObserver(APIUtilObserver* observer) {} 78 79void FakeAPIUtil::GetDriveDirectoryForSyncRoot( 80 const ResourceIdCallback& callback) { 81 base::MessageLoopProxy::current()->PostTask( 82 FROM_HERE, 83 base::Bind(callback, 84 google_apis::HTTP_SUCCESS, 85 "folder: sync_root_resource_id")); 86} 87 88void FakeAPIUtil::GetDriveDirectoryForOrigin( 89 const std::string& sync_root_resource_id, 90 const GURL& origin, 91 const ResourceIdCallback& callback) { 92 base::MessageLoopProxy::current()->PostTask( 93 FROM_HERE, 94 base::Bind(callback, 95 google_apis::HTTP_SUCCESS, 96 "folder resource_id for " + origin.host())); 97} 98 99void FakeAPIUtil::GetLargestChangeStamp(const ChangeStampCallback& callback) { 100 base::MessageLoopProxy::current()->PostTask( 101 FROM_HERE, 102 base::Bind(callback, google_apis::HTTP_SUCCESS, largest_changestamp_)); 103} 104 105void FakeAPIUtil::GetResourceEntry(const std::string& resource_id, 106 const ResourceEntryCallback& callback) { 107 NOTREACHED(); 108} 109 110void FakeAPIUtil::ListFiles(const std::string& directory_resource_id, 111 const ResourceListCallback& callback) { 112 ListChanges(0, callback); 113} 114 115void FakeAPIUtil::ListChanges(int64 start_changestamp, 116 const ResourceListCallback& callback) { 117 scoped_ptr<google_apis::ResourceList> change_feed( 118 new google_apis::ResourceList()); 119 120 ScopedVector<google_apis::ResourceEntry> entries; 121 typedef RemoteResourceByResourceId::const_iterator iterator; 122 for (iterator itr = remote_resources_.begin(); 123 itr != remote_resources_.end(); ++itr) { 124 if (itr->second.changestamp < start_changestamp) 125 continue; 126 scoped_ptr<google_apis::ResourceEntry> entry( 127 CreateResourceEntry(itr->second)); 128 entries.push_back(entry.release()); 129 } 130 131 std::sort(entries.begin(), entries.end(), ChangeStampComparator()); 132 133 change_feed->set_entries(&entries); 134 change_feed->set_largest_changestamp(largest_changestamp_); 135 136 base::MessageLoopProxy::current()->PostTask( 137 FROM_HERE, 138 base::Bind( 139 callback, google_apis::HTTP_SUCCESS, base::Passed(&change_feed))); 140} 141 142void FakeAPIUtil::ContinueListing(const GURL& feed_url, 143 const ResourceListCallback& callback) { 144 NOTREACHED(); 145} 146 147void FakeAPIUtil::DownloadFile(const std::string& resource_id, 148 const std::string& local_file_md5, 149 const DownloadFileCallback& callback) { 150 RemoteResourceByResourceId::iterator found = 151 remote_resources_.find(resource_id); 152 std::string file_md5; 153 int64 file_size = 0; 154 base::Time updated_time; 155 google_apis::GDataErrorCode error = google_apis::HTTP_NOT_FOUND; 156 157 if (found != remote_resources_.end() && !found->second.deleted) { 158 scoped_ptr<google_apis::ResourceEntry> entry( 159 CreateResourceEntry(found->second)); 160 file_md5 = entry->file_md5(); 161 file_size = entry->file_size(); 162 updated_time = entry->updated_time(); 163 error = google_apis::HTTP_SUCCESS; 164 } 165 166 scoped_ptr<webkit_blob::ScopedFile> dummy_local_file( 167 new webkit_blob::ScopedFile); 168 base::MessageLoopProxy::current()->PostTask( 169 FROM_HERE, 170 base::Bind(callback, error, file_md5, file_size, updated_time, 171 base::Passed(&dummy_local_file))); 172} 173 174void FakeAPIUtil::UploadNewFile(const std::string& directory_resource_id, 175 const base::FilePath& local_file_path, 176 const std::string& title, 177 const UploadFileCallback& callback) { 178 NOTREACHED(); 179} 180 181void FakeAPIUtil::UploadExistingFile(const std::string& resource_id, 182 const std::string& remote_file_md5, 183 const base::FilePath& local_file_path, 184 const UploadFileCallback& callback) { 185 NOTREACHED(); 186} 187 188void FakeAPIUtil::CreateDirectory(const std::string& parent_resource_id, 189 const std::string& title, 190 const ResourceIdCallback& callback) { 191 NOTREACHED(); 192} 193 194bool FakeAPIUtil::IsAuthenticated() const { return true; } 195 196void FakeAPIUtil::DeleteFile(const std::string& resource_id, 197 const std::string& remote_file_md5, 198 const GDataErrorCallback& callback) { 199 if (!ContainsKey(remote_resources_, resource_id)) { 200 base::MessageLoopProxy::current()->PostTask( 201 FROM_HERE, 202 base::Bind(callback, google_apis::HTTP_NOT_FOUND)); 203 return; 204 } 205 206 const RemoteResource& deleted_directory = remote_resources_[resource_id]; 207 PushRemoteChange(deleted_directory.parent_resource_id, 208 deleted_directory.parent_title, 209 deleted_directory.title, 210 deleted_directory.resource_id, 211 deleted_directory.md5_checksum, 212 SYNC_FILE_TYPE_UNKNOWN, 213 true /* deleted */); 214 215 base::MessageLoopProxy::current()->PostTask( 216 FROM_HERE, 217 base::Bind(callback, google_apis::HTTP_SUCCESS)); 218} 219 220GURL FakeAPIUtil::ResourceIdToResourceLink( 221 const std::string& resource_id) const { 222 return url_generator_.GenerateEditUrl(resource_id); 223} 224 225void FakeAPIUtil::EnsureSyncRootIsNotInMyDrive( 226 const std::string& sync_root_resource_id) { 227 // Nothing to do. 228} 229 230void FakeAPIUtil::PushRemoteChange(const std::string& parent_resource_id, 231 const std::string& parent_title, 232 const std::string& title, 233 const std::string& resource_id, 234 const std::string& md5, 235 SyncFileType type, 236 bool deleted) { 237 remote_resources_[resource_id] = RemoteResource( 238 parent_resource_id, parent_title, title, resource_id, 239 md5, type, deleted, ++largest_changestamp_); 240} 241 242scoped_ptr<google_apis::ResourceEntry> FakeAPIUtil::CreateResourceEntry( 243 const RemoteResource& resource) const { 244 scoped_ptr<google_apis::ResourceEntry> entry( 245 new google_apis::ResourceEntry()); 246 ScopedVector<google_apis::Link> parent_links; 247 scoped_ptr<google_apis::Link> link(new google_apis::Link()); 248 249 link->set_type(google_apis::Link::LINK_PARENT); 250 link->set_href(ResourceIdToResourceLink(resource.parent_resource_id)); 251 link->set_title(resource.parent_title); 252 parent_links.push_back(link.release()); 253 254 entry->set_links(&parent_links); 255 entry->set_title(resource.title); 256 entry->set_resource_id(resource.resource_id); 257 entry->set_file_md5(resource.md5_checksum); 258 entry->set_deleted(resource.deleted); 259 entry->set_changestamp(resource.changestamp); 260 261 switch (resource.type) { 262 case SYNC_FILE_TYPE_FILE: 263 entry->set_kind(google_apis::ENTRY_KIND_FILE); 264 break; 265 case SYNC_FILE_TYPE_DIRECTORY: 266 entry->set_kind(google_apis::ENTRY_KIND_FOLDER); 267 break; 268 case SYNC_FILE_TYPE_UNKNOWN: 269 entry->set_kind(google_apis::ENTRY_KIND_UNKNOWN); 270 break; 271 } 272 273 return entry.Pass(); 274} 275 276} // namespace drive_backend 277} // namespace sync_file_system 278