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_v1/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 "google_apis/drive/drive_entry_kinds.h" 13 #include "webkit/common/blob/scoped_file.h" 14 15 namespace sync_file_system { 16 namespace drive_backend { 17 18 bool 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 36 struct 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 43 FakeAPIUtil::RemoteResource::RemoteResource() 44 : type(SYNC_FILE_TYPE_UNKNOWN), deleted(false), changestamp(0) {} 45 46 FakeAPIUtil::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 64 FakeAPIUtil::RemoteResource::~RemoteResource() {} 65 66 FakeAPIUtil::FakeAPIUtil() 67 : largest_changestamp_(0), 68 url_generator_( 69 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), 70 GURL(google_apis::GDataWapiUrlGenerator:: 71 kBaseDownloadUrlForProduction)) {} 72 73 FakeAPIUtil::~FakeAPIUtil() {} 74 75 void FakeAPIUtil::AddObserver(APIUtilObserver* observer) {} 76 77 void FakeAPIUtil::RemoveObserver(APIUtilObserver* observer) {} 78 79 void 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 88 void 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 99 void 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 105 void FakeAPIUtil::GetResourceEntry(const std::string& resource_id, 106 const ResourceEntryCallback& callback) { 107 NOTREACHED(); 108 } 109 110 void FakeAPIUtil::ListFiles(const std::string& directory_resource_id, 111 const ResourceListCallback& callback) { 112 ListChanges(0, callback); 113 } 114 115 void 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.Pass()); 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 142 void FakeAPIUtil::ContinueListing(const GURL& next_link, 143 const ResourceListCallback& callback) { 144 NOTREACHED(); 145 } 146 147 void 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 webkit_blob::ScopedFile dummy; 167 base::MessageLoopProxy::current()->PostTask( 168 FROM_HERE, 169 base::Bind(callback, error, file_md5, file_size, updated_time, 170 base::Passed(&dummy))); 171 } 172 173 void FakeAPIUtil::UploadNewFile(const std::string& directory_resource_id, 174 const base::FilePath& local_file_path, 175 const std::string& title, 176 const UploadFileCallback& callback) { 177 NOTREACHED(); 178 } 179 180 void FakeAPIUtil::UploadExistingFile(const std::string& resource_id, 181 const std::string& remote_file_md5, 182 const base::FilePath& local_file_path, 183 const UploadFileCallback& callback) { 184 NOTREACHED(); 185 } 186 187 void FakeAPIUtil::CreateDirectory(const std::string& parent_resource_id, 188 const std::string& title, 189 const ResourceIdCallback& callback) { 190 NOTREACHED(); 191 } 192 193 bool FakeAPIUtil::IsAuthenticated() const { return true; } 194 195 void FakeAPIUtil::DeleteFile(const std::string& resource_id, 196 const std::string& remote_file_md5, 197 const GDataErrorCallback& callback) { 198 if (!ContainsKey(remote_resources_, resource_id)) { 199 base::MessageLoopProxy::current()->PostTask( 200 FROM_HERE, 201 base::Bind(callback, google_apis::HTTP_NOT_FOUND)); 202 return; 203 } 204 205 const RemoteResource& deleted_directory = remote_resources_[resource_id]; 206 PushRemoteChange(deleted_directory.parent_resource_id, 207 deleted_directory.parent_title, 208 deleted_directory.title, 209 deleted_directory.resource_id, 210 deleted_directory.md5_checksum, 211 SYNC_FILE_TYPE_UNKNOWN, 212 true /* deleted */); 213 214 base::MessageLoopProxy::current()->PostTask( 215 FROM_HERE, 216 base::Bind(callback, google_apis::HTTP_SUCCESS)); 217 } 218 219 void FakeAPIUtil::EnsureSyncRootIsNotInMyDrive( 220 const std::string& sync_root_resource_id) { 221 // Nothing to do. 222 } 223 224 void FakeAPIUtil::PushRemoteChange(const std::string& parent_resource_id, 225 const std::string& parent_title, 226 const std::string& title, 227 const std::string& resource_id, 228 const std::string& md5, 229 SyncFileType type, 230 bool deleted) { 231 remote_resources_[resource_id] = RemoteResource( 232 parent_resource_id, parent_title, title, resource_id, 233 md5, type, deleted, ++largest_changestamp_); 234 } 235 236 scoped_ptr<google_apis::ResourceEntry> FakeAPIUtil::CreateResourceEntry( 237 const RemoteResource& resource) const { 238 scoped_ptr<google_apis::ResourceEntry> entry( 239 new google_apis::ResourceEntry()); 240 ScopedVector<google_apis::Link> parent_links; 241 scoped_ptr<google_apis::Link> link(new google_apis::Link()); 242 243 link->set_type(google_apis::Link::LINK_PARENT); 244 link->set_href(ResourceIdToResourceLink(resource.parent_resource_id)); 245 link->set_title(resource.parent_title); 246 parent_links.push_back(link.release()); 247 248 entry->set_links(parent_links.Pass()); 249 entry->set_title(resource.title); 250 entry->set_resource_id(resource.resource_id); 251 entry->set_file_md5(resource.md5_checksum); 252 entry->set_deleted(resource.deleted); 253 entry->set_changestamp(resource.changestamp); 254 255 switch (resource.type) { 256 case SYNC_FILE_TYPE_FILE: 257 entry->set_kind(google_apis::ENTRY_KIND_FILE); 258 break; 259 case SYNC_FILE_TYPE_DIRECTORY: 260 entry->set_kind(google_apis::ENTRY_KIND_FOLDER); 261 break; 262 case SYNC_FILE_TYPE_UNKNOWN: 263 entry->set_kind(google_apis::ENTRY_KIND_UNKNOWN); 264 break; 265 } 266 267 return entry.Pass(); 268 } 269 270 GURL FakeAPIUtil::ResourceIdToResourceLink( 271 const std::string& resource_id) const { 272 return url_generator_.GenerateEditUrl(resource_id); 273 } 274 275 } // namespace drive_backend 276 } // namespace sync_file_system 277