| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/drive/drive_resource_metadata.h" | 5 #include "chrome/browser/chromeos/drive/drive_resource_metadata.h" |
| 6 | 6 |
| 7 #include <leveldb/db.h> | 7 #include <leveldb/db.h> |
| 8 #include <stack> | 8 #include <stack> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 void DriveResourceMetadata::ClearRoot() { | 108 void DriveResourceMetadata::ClearRoot() { |
| 109 if (!root_.get()) | 109 if (!root_.get()) |
| 110 return; | 110 return; |
| 111 | 111 |
| 112 // The root is not yet initialized. | 112 // The root is not yet initialized. |
| 113 if (root_->resource_id().empty()) | 113 if (root_->resource_id().empty()) |
| 114 return; | 114 return; |
| 115 | 115 |
| 116 // Note that children have a reference to root_, | 116 // Note that children have a reference to root_, |
| 117 // so we need to delete them here. | 117 // so we need to delete them here. |
| 118 RemoveDirectoryChildren(root_.get()); | 118 RemoveDirectoryChildren(root_->resource_id()); |
| 119 RemoveEntryFromResourceMap(root_->resource_id()); | 119 RemoveEntryFromResourceMap(root_->resource_id()); |
| 120 DCHECK(resource_map_.empty()); | 120 DCHECK(resource_map_.empty()); |
| 121 // The resource_map_ should be empty here, but to make sure for non-Debug | 121 // The resource_map_ should be empty here, but to make sure for non-Debug |
| 122 // build. | 122 // build. |
| 123 resource_map_.clear(); | 123 resource_map_.clear(); |
| 124 root_.reset(); | 124 root_.reset(); |
| 125 } | 125 } |
| 126 | 126 |
| 127 void DriveResourceMetadata::GetLargestChangestamp( | 127 void DriveResourceMetadata::GetLargestChangestamp( |
| 128 const GetChangestampCallback& callback) { | 128 const GetChangestampCallback& callback) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 146 DCHECK(!directory_path.empty()); | 146 DCHECK(!directory_path.empty()); |
| 147 DCHECK(!file_path.empty()); | 147 DCHECK(!file_path.empty()); |
| 148 DCHECK(!callback.is_null()); | 148 DCHECK(!callback.is_null()); |
| 149 | 149 |
| 150 DriveEntryProto* entry = FindEntryByPathSync(file_path); | 150 DriveEntryProto* entry = FindEntryByPathSync(file_path); |
| 151 if (!entry) { | 151 if (!entry) { |
| 152 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 152 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
| 153 return; | 153 return; |
| 154 } | 154 } |
| 155 | 155 |
| 156 // Cannot move an entry without its parent. (i.e. the root) |
| 157 if (entry->parent_resource_id().empty()) { |
| 158 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_INVALID_OPERATION); |
| 159 return; |
| 160 } |
| 161 |
| 156 DriveEntryProto* destination = FindEntryByPathSync(directory_path); | 162 DriveEntryProto* destination = FindEntryByPathSync(directory_path); |
| 157 base::FilePath moved_file_path; | 163 base::FilePath moved_file_path; |
| 158 DriveFileError error = DRIVE_FILE_ERROR_FAILED; | 164 DriveFileError error = DRIVE_FILE_ERROR_FAILED; |
| 159 if (!destination) { | 165 if (!destination) { |
| 160 error = DRIVE_FILE_ERROR_NOT_FOUND; | 166 error = DRIVE_FILE_ERROR_NOT_FOUND; |
| 161 } else if (!destination->file_info().is_directory()) { | 167 } else if (!destination->file_info().is_directory()) { |
| 162 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; | 168 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; |
| 163 } else { | 169 } else { |
| 164 DriveEntryProto* parent = entry->parent_resource_id().empty() ? NULL : | 170 DetachEntryFromDirectory(entry->resource_id()); |
| 165 GetEntryByResourceId(entry->parent_resource_id()); | 171 entry->set_parent_resource_id(destination->resource_id()); |
| 166 if (parent && parent->file_info().is_directory()) | 172 AddEntryToDirectory(entry); |
| 167 DetachEntryFromDirectory(parent, entry); | 173 moved_file_path = GetFilePath(entry->resource_id()); |
| 168 | |
| 169 AddEntryToDirectory(destination, entry); | |
| 170 moved_file_path = GetFilePath(*entry); | |
| 171 error = DRIVE_FILE_OK; | 174 error = DRIVE_FILE_OK; |
| 172 } | 175 } |
| 173 DVLOG(1) << "MoveEntryToDirectory " << moved_file_path.value(); | 176 DVLOG(1) << "MoveEntryToDirectory " << moved_file_path.value(); |
| 174 base::MessageLoopProxy::current()->PostTask( | 177 base::MessageLoopProxy::current()->PostTask( |
| 175 FROM_HERE, base::Bind(callback, error, moved_file_path)); | 178 FROM_HERE, base::Bind(callback, error, moved_file_path)); |
| 176 } | 179 } |
| 177 | 180 |
| 178 void DriveResourceMetadata::RenameEntry( | 181 void DriveResourceMetadata::RenameEntry( |
| 179 const base::FilePath& file_path, | 182 const base::FilePath& file_path, |
| 180 const base::FilePath::StringType& new_name, | 183 const base::FilePath::StringType& new_name, |
| 181 const FileMoveCallback& callback) { | 184 const FileMoveCallback& callback) { |
| 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 183 DCHECK(!file_path.empty()); | 186 DCHECK(!file_path.empty()); |
| 184 DCHECK(!new_name.empty()); | 187 DCHECK(!new_name.empty()); |
| 185 DCHECK(!callback.is_null()); | 188 DCHECK(!callback.is_null()); |
| 186 | 189 |
| 187 DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name; | 190 DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name; |
| 188 DriveEntryProto* entry = FindEntryByPathSync(file_path); | 191 DriveEntryProto* entry = FindEntryByPathSync(file_path); |
| 189 if (!entry) { | 192 if (!entry) { |
| 190 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 193 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
| 191 return; | 194 return; |
| 192 } | 195 } |
| 193 | 196 |
| 194 if (new_name == file_path.BaseName().value()) { | 197 if (new_name == file_path.BaseName().value()) { |
| 195 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_EXISTS); | 198 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_EXISTS); |
| 196 return; | 199 return; |
| 197 } | 200 } |
| 198 | 201 |
| 199 entry->set_title(new_name); | 202 entry->set_title(new_name); |
| 200 | |
| 201 DriveEntryProto* parent = GetEntryByResourceId(entry->parent_resource_id()); | |
| 202 DCHECK(parent); | |
| 203 // After changing the title of the entry, call MoveEntryToDirectory to | 203 // After changing the title of the entry, call MoveEntryToDirectory to |
| 204 // remove the entry from its parent directory and then add it back in order to | 204 // remove the entry from its parent directory and then add it back in order to |
| 205 // go through the file name de-duplication. | 205 // go through the file name de-duplication. |
| 206 // TODO(achuith/satorux/zel): This code is fragile. The title has been | 206 // TODO(achuith/satorux/zel): This code is fragile. The title has been |
| 207 // changed, but not the file_name. MoveEntryToDirectory calls RemoveChild to | 207 // changed, but not the file_name. MoveEntryToDirectory calls RemoveChild to |
| 208 // remove the child based on the old file_name, and then re-adds the child by | 208 // remove the child based on the old file_name, and then re-adds the child by |
| 209 // first assigning the new title to file_name. http://crbug.com/30157 | 209 // first assigning the new title to file_name. http://crbug.com/30157 |
| 210 MoveEntryToDirectory(file_path, GetFilePath(*parent), callback); | 210 MoveEntryToDirectory(file_path, |
| 211 GetFilePath(entry->parent_resource_id()), callback); |
| 211 } | 212 } |
| 212 | 213 |
| 213 void DriveResourceMetadata::RemoveEntry(const std::string& resource_id, | 214 void DriveResourceMetadata::RemoveEntry(const std::string& resource_id, |
| 214 const FileMoveCallback& callback) { | 215 const FileMoveCallback& callback) { |
| 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 216 DCHECK(!callback.is_null()); | 217 DCHECK(!callback.is_null()); |
| 217 | 218 |
| 218 // Disallow deletion of root. | 219 // Disallow deletion of root. |
| 219 if (resource_id == root_->resource_id()) { | 220 if (resource_id == root_->resource_id()) { |
| 220 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_ACCESS_DENIED); | 221 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_ACCESS_DENIED); |
| 221 return; | 222 return; |
| 222 } | 223 } |
| 223 | 224 |
| 224 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 225 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
| 225 if (!entry) { | 226 if (!entry) { |
| 226 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 227 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
| 227 return; | 228 return; |
| 228 } | 229 } |
| 229 | 230 |
| 230 DriveEntryProto* parent = GetEntryByResourceId(entry->parent_resource_id()); | 231 const base::FilePath parent_file_path = |
| 231 DCHECK(parent && parent->file_info().is_directory()); | 232 GetFilePath(entry->parent_resource_id()); |
| 232 | 233 RemoveDirectoryChild(entry->resource_id()); |
| 233 RemoveDirectoryChild(parent, entry); | |
| 234 base::MessageLoopProxy::current()->PostTask( | 234 base::MessageLoopProxy::current()->PostTask( |
| 235 FROM_HERE, | 235 FROM_HERE, |
| 236 base::Bind(callback, DRIVE_FILE_OK, GetFilePath(*parent))); | 236 base::Bind(callback, DRIVE_FILE_OK, parent_file_path)); |
| 237 } | 237 } |
| 238 | 238 |
| 239 bool DriveResourceMetadata::AddEntryToResourceMap(DriveEntryProto* entry) { | 239 bool DriveResourceMetadata::AddEntryToResourceMap(DriveEntryProto* entry) { |
| 240 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); | 240 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); |
| 241 DCHECK(!entry->resource_id().empty()); | 241 DCHECK(!entry->resource_id().empty()); |
| 242 std::pair<ResourceMap::iterator, bool> ret = | 242 std::pair<ResourceMap::iterator, bool> ret = |
| 243 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); | 243 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); |
| 244 DCHECK(ret.second); // resource_id did not previously exist in the map. | 244 DCHECK(ret.second); // resource_id did not previously exist in the map. |
| 245 return ret.second; | 245 return ret.second; |
| 246 } | 246 } |
| 247 | 247 |
| 248 void DriveResourceMetadata::RemoveEntryFromResourceMap( | 248 void DriveResourceMetadata::RemoveEntryFromResourceMap( |
| 249 const std::string& resource_id) { | 249 const std::string& resource_id) { |
| 250 DVLOG(1) << "RemoveEntryFromResourceMap " << resource_id; | 250 DVLOG(1) << "RemoveEntryFromResourceMap " << resource_id; |
| 251 DCHECK(!resource_id.empty()); | 251 DCHECK(!resource_id.empty()); |
| 252 size_t ret = resource_map_.erase(resource_id); | 252 size_t ret = resource_map_.erase(resource_id); |
| 253 DCHECK_EQ(1u, ret); // resource_id was found in the map. | 253 DCHECK_EQ(1u, ret); // resource_id was found in the map. |
| 254 } | 254 } |
| 255 | 255 |
| 256 DriveEntryProto* DriveResourceMetadata::FindEntryByPathSync( | 256 DriveEntryProto* DriveResourceMetadata::FindEntryByPathSync( |
| 257 const base::FilePath& file_path) { | 257 const base::FilePath& file_path) { |
| 258 if (file_path == GetFilePath(*root_)) | 258 if (file_path == GetFilePath(root_->resource_id())) |
| 259 return root_.get(); | 259 return root_.get(); |
| 260 | 260 |
| 261 std::vector<base::FilePath::StringType> components; | 261 std::vector<base::FilePath::StringType> components; |
| 262 file_path.GetComponents(&components); | 262 file_path.GetComponents(&components); |
| 263 DriveEntryProto* current_dir = root_.get(); | 263 DriveEntryProto* current_dir = root_.get(); |
| 264 | 264 |
| 265 for (size_t i = 1; i < components.size() && current_dir; ++i) { | 265 for (size_t i = 1; i < components.size() && current_dir; ++i) { |
| 266 std::string resource_id = FindDirectoryChild(current_dir, components[i]); | 266 std::string resource_id = FindDirectoryChild(current_dir->resource_id(), |
| 267 components[i]); |
| 267 if (resource_id.empty()) | 268 if (resource_id.empty()) |
| 268 return NULL; | 269 return NULL; |
| 269 | 270 |
| 270 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 271 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
| 271 DCHECK(entry); | 272 DCHECK(entry); |
| 272 | 273 |
| 273 if (i == components.size() - 1) // Last component. | 274 if (i == components.size() - 1) // Last component. |
| 274 return entry; | 275 return entry; |
| 275 if (!entry->file_info().is_directory()) | 276 if (!entry->file_info().is_directory()) |
| 276 return NULL; | 277 return NULL; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 293 DCHECK(!callback.is_null()); | 294 DCHECK(!callback.is_null()); |
| 294 | 295 |
| 295 scoped_ptr<DriveEntryProto> entry_proto; | 296 scoped_ptr<DriveEntryProto> entry_proto; |
| 296 DriveFileError error = DRIVE_FILE_ERROR_FAILED; | 297 DriveFileError error = DRIVE_FILE_ERROR_FAILED; |
| 297 base::FilePath drive_file_path; | 298 base::FilePath drive_file_path; |
| 298 | 299 |
| 299 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 300 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
| 300 if (entry) { | 301 if (entry) { |
| 301 entry_proto.reset(new DriveEntryProto(*entry)); | 302 entry_proto.reset(new DriveEntryProto(*entry)); |
| 302 error = DRIVE_FILE_OK; | 303 error = DRIVE_FILE_OK; |
| 303 drive_file_path = GetFilePath(*entry); | 304 drive_file_path = GetFilePath(entry->resource_id()); |
| 304 } else { | 305 } else { |
| 305 error = DRIVE_FILE_ERROR_NOT_FOUND; | 306 error = DRIVE_FILE_ERROR_NOT_FOUND; |
| 306 } | 307 } |
| 307 | 308 |
| 308 base::MessageLoopProxy::current()->PostTask( | 309 base::MessageLoopProxy::current()->PostTask( |
| 309 FROM_HERE, | 310 FROM_HERE, |
| 310 base::Bind(callback, error, drive_file_path, base::Passed(&entry_proto))); | 311 base::Bind(callback, error, drive_file_path, base::Passed(&entry_proto))); |
| 311 } | 312 } |
| 312 | 313 |
| 313 void DriveResourceMetadata::GetEntryInfoByPath( | 314 void DriveResourceMetadata::GetEntryInfoByPath( |
| (...skipping 22 matching lines...) Expand all Loading... |
| 336 const base::FilePath& path, | 337 const base::FilePath& path, |
| 337 const ReadDirectoryCallback& callback) { | 338 const ReadDirectoryCallback& callback) { |
| 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 339 DCHECK(!callback.is_null()); | 340 DCHECK(!callback.is_null()); |
| 340 | 341 |
| 341 scoped_ptr<DriveEntryProtoVector> entries; | 342 scoped_ptr<DriveEntryProtoVector> entries; |
| 342 DriveFileError error = DRIVE_FILE_ERROR_FAILED; | 343 DriveFileError error = DRIVE_FILE_ERROR_FAILED; |
| 343 | 344 |
| 344 DriveEntryProto* entry = FindEntryByPathSync(path); | 345 DriveEntryProto* entry = FindEntryByPathSync(path); |
| 345 if (entry && entry->file_info().is_directory()) { | 346 if (entry && entry->file_info().is_directory()) { |
| 346 entries = DirectoryChildrenToProtoVector(entry); | 347 entries = DirectoryChildrenToProtoVector(entry->resource_id()); |
| 347 error = DRIVE_FILE_OK; | 348 error = DRIVE_FILE_OK; |
| 348 } else if (entry && !entry->file_info().is_directory()) { | 349 } else if (entry && !entry->file_info().is_directory()) { |
| 349 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; | 350 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; |
| 350 } else { | 351 } else { |
| 351 error = DRIVE_FILE_ERROR_NOT_FOUND; | 352 error = DRIVE_FILE_ERROR_NOT_FOUND; |
| 352 } | 353 } |
| 353 | 354 |
| 354 base::MessageLoopProxy::current()->PostTask( | 355 base::MessageLoopProxy::current()->PostTask( |
| 355 FROM_HERE, | 356 FROM_HERE, |
| 356 base::Bind(callback, error, base::Passed(&entries))); | 357 base::Bind(callback, error, base::Passed(&entries))); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 // Reject incompatible input. | 390 // Reject incompatible input. |
| 390 if (entry->file_info().is_directory() != | 391 if (entry->file_info().is_directory() != |
| 391 entry_proto.file_info().is_directory()) { | 392 entry_proto.file_info().is_directory()) { |
| 392 PostGetEntryInfoWithFilePathCallbackError( | 393 PostGetEntryInfoWithFilePathCallbackError( |
| 393 callback, DRIVE_FILE_ERROR_INVALID_OPERATION); | 394 callback, DRIVE_FILE_ERROR_INVALID_OPERATION); |
| 394 return; | 395 return; |
| 395 } | 396 } |
| 396 | 397 |
| 397 // Update data. | 398 // Update data. |
| 398 if (entry != root_.get()) { | 399 if (entry != root_.get()) { |
| 399 DriveEntryProto* old_parent = GetDirectory(entry->parent_resource_id()); | |
| 400 DriveEntryProto* new_parent = | 400 DriveEntryProto* new_parent = |
| 401 GetDirectory(entry_proto.parent_resource_id()); | 401 GetDirectory(entry_proto.parent_resource_id()); |
| 402 | 402 |
| 403 if (!old_parent || !new_parent) { | 403 if (!new_parent) { |
| 404 PostGetEntryInfoWithFilePathCallbackError( | 404 PostGetEntryInfoWithFilePathCallbackError( |
| 405 callback, DRIVE_FILE_ERROR_NOT_FOUND); | 405 callback, DRIVE_FILE_ERROR_NOT_FOUND); |
| 406 return; | 406 return; |
| 407 } | 407 } |
| 408 | 408 |
| 409 // Remove from the old parent, update the entry, and add it to the new | 409 // Remove from the old parent, update the entry, and add it to the new |
| 410 // parent. The order matters here. FromProto() could remove suffix like | 410 // parent. The order matters here. FromProto() could remove suffix like |
| 411 // "(2)" from entries with duplicate names. If FromProto() is first | 411 // "(2)" from entries with duplicate names. If FromProto() is first |
| 412 // called, RemoveChild() won't work correctly because of the missing | 412 // called, RemoveChild() won't work correctly because of the missing |
| 413 // suffix. | 413 // suffix. |
| 414 DetachEntryFromDirectory(old_parent, entry); | 414 DetachEntryFromDirectory(entry->resource_id()); |
| 415 // Note that it's safe to update the directory entry with | 415 // Note that it's safe to update the directory entry as it won't clear |
| 416 // DriveEntry::FromProto() as it won't clear children. | 416 // children. |
| 417 *entry = CreateEntryWithProperBaseName(entry_proto); | 417 *entry = CreateEntryWithProperBaseName(entry_proto); |
| 418 AddEntryToDirectory(new_parent, entry); // Transfers ownership. | 418 AddEntryToDirectory(entry); // Transfers ownership. |
| 419 } else { | 419 } else { |
| 420 // root has no parent. | 420 // root has no parent. |
| 421 *entry = CreateEntryWithProperBaseName(entry_proto); | 421 *entry = CreateEntryWithProperBaseName(entry_proto); |
| 422 } | 422 } |
| 423 | 423 |
| 424 DVLOG(1) << "RefreshEntry " << GetFilePath(*entry).value(); | 424 DVLOG(1) << "RefreshEntry " << GetFilePath(entry->resource_id()).value(); |
| 425 // Note that base_name is not the same for new_entry and entry_proto. | 425 // Note that base_name is not the same for new_entry and entry_proto. |
| 426 scoped_ptr<DriveEntryProto> result_entry_proto(new DriveEntryProto(*entry)); | 426 scoped_ptr<DriveEntryProto> result_entry_proto(new DriveEntryProto(*entry)); |
| 427 base::MessageLoopProxy::current()->PostTask( | 427 base::MessageLoopProxy::current()->PostTask( |
| 428 FROM_HERE, | 428 FROM_HERE, |
| 429 base::Bind(callback, | 429 base::Bind(callback, |
| 430 DRIVE_FILE_OK, | 430 DRIVE_FILE_OK, |
| 431 GetFilePath(*entry), | 431 GetFilePath(entry->resource_id()), |
| 432 base::Passed(&result_entry_proto))); | 432 base::Passed(&result_entry_proto))); |
| 433 } | 433 } |
| 434 | 434 |
| 435 void DriveResourceMetadata::RefreshDirectory( | 435 void DriveResourceMetadata::RefreshDirectory( |
| 436 const DirectoryFetchInfo& directory_fetch_info, | 436 const DirectoryFetchInfo& directory_fetch_info, |
| 437 const DriveEntryProtoMap& entry_proto_map, | 437 const DriveEntryProtoMap& entry_proto_map, |
| 438 const FileMoveCallback& callback) { | 438 const FileMoveCallback& callback) { |
| 439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 440 DCHECK(!callback.is_null()); | 440 DCHECK(!callback.is_null()); |
| 441 DCHECK(!directory_fetch_info.empty()); | 441 DCHECK(!directory_fetch_info.empty()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 470 // crbug.com/193525. | 470 // crbug.com/193525. |
| 471 if (entry_proto.parent_resource_id() != | 471 if (entry_proto.parent_resource_id() != |
| 472 directory_fetch_info.resource_id()) { | 472 directory_fetch_info.resource_id()) { |
| 473 DVLOG(1) << "Wrong-parent entry rejected: " << entry_proto.resource_id(); | 473 DVLOG(1) << "Wrong-parent entry rejected: " << entry_proto.resource_id(); |
| 474 continue; | 474 continue; |
| 475 } | 475 } |
| 476 | 476 |
| 477 DriveEntryProto* existing_entry = | 477 DriveEntryProto* existing_entry = |
| 478 GetEntryByResourceId(entry_proto.resource_id()); | 478 GetEntryByResourceId(entry_proto.resource_id()); |
| 479 if (existing_entry) { | 479 if (existing_entry) { |
| 480 DriveEntryProto* old_parent = | |
| 481 GetDirectory(existing_entry->parent_resource_id()); | |
| 482 DCHECK(old_parent && old_parent->file_info().is_directory()); | |
| 483 // See the comment in RefreshEntry() for why the existing entry is | 480 // See the comment in RefreshEntry() for why the existing entry is |
| 484 // updated in this way. | 481 // updated in this way. |
| 485 DetachEntryFromDirectory(old_parent, existing_entry); | 482 DetachEntryFromDirectory(existing_entry->resource_id()); |
| 486 *existing_entry = CreateEntryWithProperBaseName(entry_proto); | 483 *existing_entry = CreateEntryWithProperBaseName(entry_proto); |
| 487 AddEntryToDirectory(directory, existing_entry); | 484 AddEntryToDirectory(existing_entry); |
| 488 } else { // New entry. | 485 } else { // New entry. |
| 489 // A new directory will have changestamp of zero, so the directory will | 486 // A new directory will have changestamp of zero, so the directory will |
| 490 // be "fast-fetched". See crbug.com/178348 for details. | 487 // be "fast-fetched". See crbug.com/178348 for details. |
| 491 scoped_ptr<DriveEntryProto> new_entry( | 488 scoped_ptr<DriveEntryProto> new_entry( |
| 492 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto))); | 489 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto))); |
| 493 AddEntryToDirectory(directory, new_entry.release()); | 490 AddEntryToDirectory(new_entry.release()); |
| 494 } | 491 } |
| 495 } | 492 } |
| 496 | 493 |
| 497 // Go through the existing entries and remove deleted entries. | 494 // Go through the existing entries and remove deleted entries. |
| 498 scoped_ptr<DriveEntryProtoVector> entries = | 495 scoped_ptr<DriveEntryProtoVector> entries = |
| 499 DirectoryChildrenToProtoVector(directory); | 496 DirectoryChildrenToProtoVector(directory->resource_id()); |
| 500 for (size_t i = 0; i < entries->size(); ++i) { | 497 for (size_t i = 0; i < entries->size(); ++i) { |
| 501 const DriveEntryProto& entry_proto = entries->at(i); | 498 const DriveEntryProto& entry_proto = entries->at(i); |
| 502 if (entry_proto_map.count(entry_proto.resource_id()) == 0) { | 499 if (entry_proto_map.count(entry_proto.resource_id()) == 0) |
| 503 DriveEntryProto* entry = GetEntryByResourceId(entry_proto.resource_id()); | 500 RemoveDirectoryChild(entry_proto.resource_id()); |
| 504 RemoveDirectoryChild(directory, entry); | |
| 505 } | |
| 506 } | 501 } |
| 507 | 502 |
| 508 base::MessageLoopProxy::current()->PostTask( | 503 base::MessageLoopProxy::current()->PostTask( |
| 509 FROM_HERE, | 504 FROM_HERE, |
| 510 base::Bind(callback, DRIVE_FILE_OK, GetFilePath(*directory))); | 505 base::Bind(callback, DRIVE_FILE_OK, |
| 506 GetFilePath(directory->resource_id()))); |
| 511 } | 507 } |
| 512 | 508 |
| 513 void DriveResourceMetadata::AddEntry(const DriveEntryProto& entry_proto, | 509 void DriveResourceMetadata::AddEntry(const DriveEntryProto& entry_proto, |
| 514 const FileMoveCallback& callback) { | 510 const FileMoveCallback& callback) { |
| 515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 516 DCHECK(!callback.is_null()); | 512 DCHECK(!callback.is_null()); |
| 517 | 513 |
| 518 DriveEntryProto* parent = GetDirectory(entry_proto.parent_resource_id()); | 514 DriveEntryProto* parent = GetDirectory(entry_proto.parent_resource_id()); |
| 519 if (!parent) { | 515 if (!parent) { |
| 520 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 516 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
| 521 return; | 517 return; |
| 522 } | 518 } |
| 523 | 519 |
| 524 DriveEntryProto* added_entry = | 520 DriveEntryProto* added_entry = |
| 525 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto)); | 521 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto)); |
| 526 AddEntryToDirectory(parent, added_entry); // Transfers ownership. | 522 AddEntryToDirectory(added_entry); // Transfers ownership. |
| 527 base::MessageLoopProxy::current()->PostTask( | 523 base::MessageLoopProxy::current()->PostTask( |
| 528 FROM_HERE, | 524 FROM_HERE, |
| 529 base::Bind(callback, DRIVE_FILE_OK, GetFilePath(*added_entry))); | 525 base::Bind(callback, DRIVE_FILE_OK, |
| 526 GetFilePath(added_entry->resource_id()))); |
| 530 } | 527 } |
| 531 | 528 |
| 532 DriveEntryProto* DriveResourceMetadata::GetDirectory( | 529 DriveEntryProto* DriveResourceMetadata::GetDirectory( |
| 533 const std::string& resource_id) { | 530 const std::string& resource_id) { |
| 534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 531 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 535 DCHECK(!resource_id.empty()); | 532 DCHECK(!resource_id.empty()); |
| 536 | 533 |
| 537 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 534 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
| 538 return entry && entry->file_info().is_directory() ? entry : NULL; | 535 return entry && entry->file_info().is_directory() ? entry : NULL; |
| 539 } | 536 } |
| 540 | 537 |
| 541 base::FilePath DriveResourceMetadata::GetFilePath( | 538 base::FilePath DriveResourceMetadata::GetFilePath( |
| 542 const DriveEntryProto& entry) { | 539 const std::string& resource_id) { |
| 540 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
| 541 DCHECK(entry); |
| 543 base::FilePath path; | 542 base::FilePath path; |
| 544 DriveEntryProto* parent = entry.parent_resource_id().empty() ? NULL : | 543 if (!entry->parent_resource_id().empty()) |
| 545 GetEntryByResourceId(entry.parent_resource_id()); | 544 path = GetFilePath(entry->parent_resource_id()); |
| 546 if (parent) | 545 path = path.Append(entry->base_name()); |
| 547 path = GetFilePath(*parent); | |
| 548 path = path.Append(entry.base_name()); | |
| 549 return path; | 546 return path; |
| 550 } | 547 } |
| 551 | 548 |
| 552 void DriveResourceMetadata::GetChildDirectories( | 549 void DriveResourceMetadata::GetChildDirectories( |
| 553 const std::string& resource_id, | 550 const std::string& resource_id, |
| 554 const GetChildDirectoriesCallback& changed_dirs_callback) { | 551 const GetChildDirectoriesCallback& changed_dirs_callback) { |
| 555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 556 DCHECK(!changed_dirs_callback.is_null()); | 553 DCHECK(!changed_dirs_callback.is_null()); |
| 557 | 554 |
| 558 std::set<base::FilePath> changed_directories; | 555 std::set<base::FilePath> changed_directories; |
| 559 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 556 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
| 560 DriveEntryProto* directory = | 557 DriveEntryProto* directory = |
| 561 entry && entry->file_info().is_directory() ? entry : NULL; | 558 entry && entry->file_info().is_directory() ? entry : NULL; |
| 562 if (directory) | 559 if (directory) |
| 563 GetDescendantDirectoryPaths(*directory, &changed_directories); | 560 GetDescendantDirectoryPaths(directory->resource_id(), &changed_directories); |
| 564 | 561 |
| 565 base::MessageLoopProxy::current()->PostTask( | 562 base::MessageLoopProxy::current()->PostTask( |
| 566 FROM_HERE, | 563 FROM_HERE, |
| 567 base::Bind(changed_dirs_callback, changed_directories)); | 564 base::Bind(changed_dirs_callback, changed_directories)); |
| 568 } | 565 } |
| 569 | 566 |
| 570 void DriveResourceMetadata::GetDescendantDirectoryPaths( | 567 void DriveResourceMetadata::GetDescendantDirectoryPaths( |
| 571 const DriveEntryProto& directory, | 568 const std::string& directory_resource_id, |
| 572 std::set<base::FilePath>* child_directories) { | 569 std::set<base::FilePath>* child_directories) { |
| 573 DCHECK(directory.file_info().is_directory()); | 570 const ChildMap& children = child_maps_[directory_resource_id]; |
| 574 const ChildMap& children = child_maps_[directory.resource_id()]; | |
| 575 for (ChildMap::const_iterator iter = children.begin(); | 571 for (ChildMap::const_iterator iter = children.begin(); |
| 576 iter != children.end(); ++iter) { | 572 iter != children.end(); ++iter) { |
| 577 DriveEntryProto* entry = GetEntryByResourceId(iter->second); | 573 DriveEntryProto* entry = GetEntryByResourceId(iter->second); |
| 578 if (entry && entry->file_info().is_directory()) { | 574 if (entry && entry->file_info().is_directory()) { |
| 579 child_directories->insert(GetFilePath(*entry)); | 575 child_directories->insert(GetFilePath(entry->resource_id())); |
| 580 GetDescendantDirectoryPaths(*entry, child_directories); | 576 GetDescendantDirectoryPaths(entry->resource_id(), child_directories); |
| 581 } | 577 } |
| 582 } | 578 } |
| 583 } | 579 } |
| 584 | 580 |
| 585 void DriveResourceMetadata::RemoveAll(const base::Closure& callback) { | 581 void DriveResourceMetadata::RemoveAll(const base::Closure& callback) { |
| 586 RemoveDirectoryChildren(root_.get()); | 582 RemoveDirectoryChildren(root_->resource_id()); |
| 587 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback); | 583 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback); |
| 588 } | 584 } |
| 589 | 585 |
| 590 void DriveResourceMetadata::SerializeToString(std::string* serialized_proto) { | 586 void DriveResourceMetadata::SerializeToString(std::string* serialized_proto) { |
| 591 DriveRootDirectoryProto proto; | 587 DriveRootDirectoryProto proto; |
| 592 DirectoryToProto(root_.get(), proto.mutable_drive_directory()); | 588 DirectoryToProto(root_->resource_id(), proto.mutable_drive_directory()); |
| 593 proto.set_largest_changestamp(largest_changestamp_); | 589 proto.set_largest_changestamp(largest_changestamp_); |
| 594 proto.set_version(kProtoVersion); | 590 proto.set_version(kProtoVersion); |
| 595 | 591 |
| 596 const bool ok = proto.SerializeToString(serialized_proto); | 592 const bool ok = proto.SerializeToString(serialized_proto); |
| 597 DCHECK(ok); | 593 DCHECK(ok); |
| 598 } | 594 } |
| 599 | 595 |
| 600 bool DriveResourceMetadata::ParseFromString( | 596 bool DriveResourceMetadata::ParseFromString( |
| 601 const std::string& serialized_proto) { | 597 const std::string& serialized_proto) { |
| 602 DriveRootDirectoryProto proto; | 598 DriveRootDirectoryProto proto; |
| 603 if (!proto.ParseFromString(serialized_proto)) | 599 if (!proto.ParseFromString(serialized_proto)) |
| 604 return false; | 600 return false; |
| 605 | 601 |
| 606 if (proto.version() != kProtoVersion) { | 602 if (proto.version() != kProtoVersion) { |
| 607 LOG(ERROR) << "Incompatible proto detected (incompatible version): " | 603 LOG(ERROR) << "Incompatible proto detected (incompatible version): " |
| 608 << proto.version(); | 604 << proto.version(); |
| 609 return false; | 605 return false; |
| 610 } | 606 } |
| 611 | 607 |
| 612 // An old proto file might not have per-directory changestamps. Add them if | 608 // An old proto file might not have per-directory changestamps. Add them if |
| 613 // needed. | 609 // needed. |
| 614 const DriveDirectoryProto& root = proto.drive_directory(); | 610 const DriveDirectoryProto& root = proto.drive_directory(); |
| 615 if (!root.drive_entry().directory_specific_info().has_changestamp()) { | 611 if (!root.drive_entry().directory_specific_info().has_changestamp()) { |
| 616 AddPerDirectoryChangestamps(proto.mutable_drive_directory(), | 612 AddPerDirectoryChangestamps(proto.mutable_drive_directory(), |
| 617 proto.largest_changestamp()); | 613 proto.largest_changestamp()); |
| 618 } | 614 } |
| 619 | 615 |
| 620 ProtoToDirectory(proto.drive_directory(), root_.get()); | 616 if (proto.drive_directory().drive_entry().resource_id() != |
| 617 root_->resource_id()) { |
| 618 LOG(ERROR) << "Incompatible proto detected (incompatible root ID): " |
| 619 << proto.drive_directory().drive_entry().resource_id(); |
| 620 return false; |
| 621 } |
| 622 |
| 623 *root_ = CreateEntryWithProperBaseName(proto.drive_directory().drive_entry()); |
| 624 AddDescendantsFromProto(proto.drive_directory()); |
| 621 | 625 |
| 622 loaded_ = true; | 626 loaded_ = true; |
| 623 largest_changestamp_ = proto.largest_changestamp(); | 627 largest_changestamp_ = proto.largest_changestamp(); |
| 624 | 628 |
| 625 return true; | 629 return true; |
| 626 } | 630 } |
| 627 | 631 |
| 628 void DriveResourceMetadata::GetEntryInfoPairByPathsAfterGetFirst( | 632 void DriveResourceMetadata::GetEntryInfoPairByPathsAfterGetFirst( |
| 629 const base::FilePath& first_path, | 633 const base::FilePath& first_path, |
| 630 const base::FilePath& second_path, | 634 const base::FilePath& second_path, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 DCHECK(!callback.is_null()); | 669 DCHECK(!callback.is_null()); |
| 666 DCHECK(result.get()); | 670 DCHECK(result.get()); |
| 667 | 671 |
| 668 result->second.path = second_path; | 672 result->second.path = second_path; |
| 669 result->second.error = error; | 673 result->second.error = error; |
| 670 result->second.proto = entry_proto.Pass(); | 674 result->second.proto = entry_proto.Pass(); |
| 671 | 675 |
| 672 callback.Run(result.Pass()); | 676 callback.Run(result.Pass()); |
| 673 } | 677 } |
| 674 | 678 |
| 675 void DriveResourceMetadata::AddEntryToDirectory(DriveEntryProto* directory, | 679 void DriveResourceMetadata::AddEntryToDirectory(DriveEntryProto* entry) { |
| 676 DriveEntryProto* entry) { | |
| 677 DCHECK(directory->file_info().is_directory()); | |
| 678 DCHECK(entry->parent_resource_id().empty() || | |
| 679 entry->parent_resource_id() == directory->resource_id()); | |
| 680 | |
| 681 // Try to add the entry to resource map. | 680 // Try to add the entry to resource map. |
| 682 if (!AddEntryToResourceMap(entry)) { | 681 if (!AddEntryToResourceMap(entry)) { |
| 683 LOG(WARNING) << "Duplicate resource=" << entry->resource_id() | 682 LOG(WARNING) << "Duplicate resource=" << entry->resource_id() |
| 684 << ", title=" << entry->title(); | 683 << ", title=" << entry->title(); |
| 685 return; | 684 return; |
| 686 } | 685 } |
| 687 | 686 |
| 688 // The entry name may have been changed due to prior name de-duplication. | 687 // The entry name may have been changed due to prior name de-duplication. |
| 689 // We need to first restore the file name based on the title before going | 688 // We need to first restore the file name based on the title before going |
| 690 // through name de-duplication again when it is added to another directory. | 689 // through name de-duplication again when it is added to another directory. |
| 691 SetBaseNameFromTitle(entry); | 690 SetBaseNameFromTitle(entry); |
| 692 | 691 |
| 693 // Do file name de-duplication - find files with the same name and | 692 // Do file name de-duplication - find files with the same name and |
| 694 // append a name modifier to the name. | 693 // append a name modifier to the name. |
| 695 int modifier = 1; | 694 int modifier = 1; |
| 696 base::FilePath full_file_name(entry->base_name()); | 695 base::FilePath full_file_name(entry->base_name()); |
| 697 const std::string extension = full_file_name.Extension(); | 696 const std::string extension = full_file_name.Extension(); |
| 698 const std::string file_name = full_file_name.RemoveExtension().value(); | 697 const std::string file_name = full_file_name.RemoveExtension().value(); |
| 699 while (!FindDirectoryChild(directory, full_file_name.value()).empty()) { | 698 while (!FindDirectoryChild(entry->parent_resource_id(), |
| 699 full_file_name.value()).empty()) { |
| 700 if (!extension.empty()) { | 700 if (!extension.empty()) { |
| 701 full_file_name = base::FilePath(base::StringPrintf("%s (%d)%s", | 701 full_file_name = base::FilePath(base::StringPrintf("%s (%d)%s", |
| 702 file_name.c_str(), | 702 file_name.c_str(), |
| 703 ++modifier, | 703 ++modifier, |
| 704 extension.c_str())); | 704 extension.c_str())); |
| 705 } else { | 705 } else { |
| 706 full_file_name = base::FilePath(base::StringPrintf("%s (%d)", | 706 full_file_name = base::FilePath(base::StringPrintf("%s (%d)", |
| 707 file_name.c_str(), | 707 file_name.c_str(), |
| 708 ++modifier)); | 708 ++modifier)); |
| 709 } | 709 } |
| 710 } | 710 } |
| 711 entry->set_base_name(full_file_name.value()); | 711 entry->set_base_name(full_file_name.value()); |
| 712 | 712 |
| 713 // Setup child and parent links. | 713 // Setup child and parent links. |
| 714 child_maps_[directory->resource_id()].insert( | 714 child_maps_[entry->parent_resource_id()].insert( |
| 715 std::make_pair(entry->base_name(), entry->resource_id())); | 715 std::make_pair(entry->base_name(), entry->resource_id())); |
| 716 entry->set_parent_resource_id(directory->resource_id()); | |
| 717 } | 716 } |
| 718 | 717 |
| 719 void DriveResourceMetadata::RemoveDirectoryChild(DriveEntryProto* directory, | 718 void DriveResourceMetadata::RemoveDirectoryChild( |
| 720 DriveEntryProto* entry) { | 719 const std::string& child_resource_id) { |
| 721 DCHECK(directory->file_info().is_directory()); | 720 DriveEntryProto* entry = GetEntryByResourceId(child_resource_id); |
| 722 DetachEntryFromDirectory(directory, entry); | 721 DCHECK(entry); |
| 722 DetachEntryFromDirectory(child_resource_id); |
| 723 if (entry->file_info().is_directory()) | 723 if (entry->file_info().is_directory()) |
| 724 RemoveDirectoryChildren(entry); | 724 RemoveDirectoryChildren(child_resource_id); |
| 725 delete entry; | 725 delete entry; |
| 726 } | 726 } |
| 727 | 727 |
| 728 std::string DriveResourceMetadata::FindDirectoryChild( | 728 std::string DriveResourceMetadata::FindDirectoryChild( |
| 729 DriveEntryProto* directory, | 729 const std::string& directory_resource_id, |
| 730 const base::FilePath::StringType& file_name) { | 730 const base::FilePath::StringType& file_name) { |
| 731 DCHECK(directory->file_info().is_directory()); | 731 const ChildMap& children = child_maps_[directory_resource_id]; |
| 732 const ChildMap& children = child_maps_[directory->resource_id()]; | |
| 733 DriveResourceMetadata::ChildMap::const_iterator iter = | 732 DriveResourceMetadata::ChildMap::const_iterator iter = |
| 734 children.find(file_name); | 733 children.find(file_name); |
| 735 if (iter != children.end()) | 734 if (iter != children.end()) |
| 736 return iter->second; | 735 return iter->second; |
| 737 return std::string(); | 736 return std::string(); |
| 738 } | 737 } |
| 739 | 738 |
| 740 void DriveResourceMetadata::DetachEntryFromDirectory( | 739 void DriveResourceMetadata::DetachEntryFromDirectory( |
| 741 DriveEntryProto* directory, | 740 const std::string& child_resource_id) { |
| 742 DriveEntryProto* entry) { | 741 DriveEntryProto* entry = GetEntryByResourceId(child_resource_id); |
| 743 DCHECK(directory->file_info().is_directory()); | |
| 744 DCHECK(entry); | 742 DCHECK(entry); |
| 745 | 743 |
| 746 const std::string& base_name(entry->base_name()); | 744 const std::string& base_name(entry->base_name()); |
| 747 // entry must be present in this directory. | 745 // entry must be present in this directory. |
| 748 DCHECK_EQ(entry->resource_id(), FindDirectoryChild(directory, base_name)); | 746 DCHECK_EQ(entry->resource_id(), |
| 747 FindDirectoryChild(entry->parent_resource_id(), base_name)); |
| 749 // Remove entry from resource map first. | 748 // Remove entry from resource map first. |
| 750 RemoveEntryFromResourceMap(entry->resource_id()); | 749 RemoveEntryFromResourceMap(entry->resource_id()); |
| 751 | 750 |
| 752 // Then delete it from tree. | 751 // Then delete it from tree. |
| 753 child_maps_[directory->resource_id()].erase(base_name); | 752 child_maps_[entry->parent_resource_id()].erase(base_name); |
| 754 | 753 |
| 755 entry->set_parent_resource_id(std::string()); | 754 entry->set_parent_resource_id(std::string()); |
| 756 } | 755 } |
| 757 | 756 |
| 758 void DriveResourceMetadata::RemoveDirectoryChildren( | 757 void DriveResourceMetadata::RemoveDirectoryChildren( |
| 759 DriveEntryProto* directory) { | 758 const std::string& directory_resource_id) { |
| 760 DCHECK(directory->file_info().is_directory()); | |
| 761 DriveResourceMetadata::ChildMap* children = | 759 DriveResourceMetadata::ChildMap* children = |
| 762 &child_maps_[directory->resource_id()]; | 760 &child_maps_[directory_resource_id]; |
| 763 for (DriveResourceMetadata::ChildMap::iterator iter = children->begin(); | 761 for (DriveResourceMetadata::ChildMap::iterator iter = children->begin(); |
| 764 iter != children->end(); ++iter) { | 762 iter != children->end(); ++iter) { |
| 765 DriveEntryProto* child = GetEntryByResourceId(iter->second); | 763 DriveEntryProto* child = GetEntryByResourceId(iter->second); |
| 766 DCHECK(child); | 764 DCHECK(child); |
| 767 // Remove directories recursively. | 765 // Remove directories recursively. |
| 768 if (child->file_info().is_directory()) | 766 if (child->file_info().is_directory()) |
| 769 RemoveDirectoryChildren(child); | 767 RemoveDirectoryChildren(child->resource_id()); |
| 770 | 768 |
| 771 RemoveEntryFromResourceMap(iter->second); | 769 RemoveEntryFromResourceMap(iter->second); |
| 772 delete child; | 770 delete child; |
| 773 } | 771 } |
| 774 child_maps_.erase(directory->resource_id()); | 772 child_maps_.erase(directory_resource_id); |
| 775 } | 773 } |
| 776 | 774 |
| 777 void DriveResourceMetadata::ProtoToDirectory(const DriveDirectoryProto& proto, | 775 void DriveResourceMetadata::AddDescendantsFromProto( |
| 778 DriveEntryProto* directory) { | 776 const DriveDirectoryProto& proto) { |
| 779 DCHECK(proto.drive_entry().file_info().is_directory()); | 777 DCHECK(proto.drive_entry().file_info().is_directory()); |
| 780 DCHECK(!proto.drive_entry().has_file_specific_info()); | 778 DCHECK(!proto.drive_entry().has_file_specific_info()); |
| 779 DCHECK(child_maps_[proto.drive_entry().resource_id()].empty()); |
| 781 | 780 |
| 782 *directory = CreateEntryWithProperBaseName(proto.drive_entry()); | 781 // Add child files. |
| 783 | |
| 784 for (int i = 0; i < proto.child_files_size(); ++i) { | 782 for (int i = 0; i < proto.child_files_size(); ++i) { |
| 785 scoped_ptr<DriveEntryProto> file(new DriveEntryProto( | 783 scoped_ptr<DriveEntryProto> file(new DriveEntryProto( |
| 786 CreateEntryWithProperBaseName(proto.child_files(i)))); | 784 CreateEntryWithProperBaseName(proto.child_files(i)))); |
| 787 AddEntryToDirectory(directory, file.release()); | 785 DCHECK_EQ(proto.drive_entry().resource_id(), file->parent_resource_id()); |
| 786 AddEntryToDirectory(file.release()); |
| 788 } | 787 } |
| 788 // Add child directories recursively. |
| 789 for (int i = 0; i < proto.child_directories_size(); ++i) { | 789 for (int i = 0; i < proto.child_directories_size(); ++i) { |
| 790 scoped_ptr<DriveEntryProto> child_dir(new DriveEntryProto); | 790 scoped_ptr<DriveEntryProto> child_dir(new DriveEntryProto); |
| 791 ProtoToDirectory(proto.child_directories(i), child_dir.get()); | 791 *child_dir = CreateEntryWithProperBaseName( |
| 792 AddEntryToDirectory(directory, child_dir.release()); | 792 proto.child_directories(i).drive_entry()); |
| 793 DCHECK_EQ(proto.drive_entry().resource_id(), |
| 794 child_dir->parent_resource_id()); |
| 795 AddEntryToDirectory(child_dir.release()); // Transfer ownership. |
| 796 AddDescendantsFromProto(proto.child_directories(i)); |
| 793 } | 797 } |
| 794 } | 798 } |
| 795 | 799 |
| 796 void DriveResourceMetadata::DirectoryToProto(DriveEntryProto* directory, | 800 void DriveResourceMetadata::DirectoryToProto( |
| 797 DriveDirectoryProto* proto) { | 801 const std::string& directory_resource_id, |
| 802 DriveDirectoryProto* proto) { |
| 803 DriveEntryProto* directory = GetEntryByResourceId(directory_resource_id); |
| 804 DCHECK(directory); |
| 798 *proto->mutable_drive_entry() = *directory; | 805 *proto->mutable_drive_entry() = *directory; |
| 799 DCHECK(proto->drive_entry().file_info().is_directory()); | 806 DCHECK(proto->drive_entry().file_info().is_directory()); |
| 800 | 807 |
| 801 const ChildMap& children = child_maps_[directory->resource_id()]; | 808 const ChildMap& children = child_maps_[directory_resource_id]; |
| 802 for (ChildMap::const_iterator iter = children.begin(); | 809 for (ChildMap::const_iterator iter = children.begin(); |
| 803 iter != children.end(); ++iter) { | 810 iter != children.end(); ++iter) { |
| 804 DriveEntryProto* entry = GetEntryByResourceId(iter->second); | 811 DriveEntryProto* entry = GetEntryByResourceId(iter->second); |
| 805 DCHECK(entry); | 812 DCHECK(entry); |
| 806 if (entry->file_info().is_directory()) | 813 if (entry->file_info().is_directory()) |
| 807 DirectoryToProto(entry, proto->add_child_directories()); | 814 DirectoryToProto(entry->resource_id(), proto->add_child_directories()); |
| 808 else | 815 else |
| 809 *proto->add_child_files() = *entry; | 816 *proto->add_child_files() = *entry; |
| 810 } | 817 } |
| 811 } | 818 } |
| 812 | 819 |
| 813 scoped_ptr<DriveEntryProtoVector> | 820 scoped_ptr<DriveEntryProtoVector> |
| 814 DriveResourceMetadata::DirectoryChildrenToProtoVector( | 821 DriveResourceMetadata::DirectoryChildrenToProtoVector( |
| 815 DriveEntryProto* directory) { | 822 const std::string& directory_resource_id) { |
| 816 DCHECK(directory->file_info().is_directory()); | |
| 817 scoped_ptr<DriveEntryProtoVector> entries(new DriveEntryProtoVector); | 823 scoped_ptr<DriveEntryProtoVector> entries(new DriveEntryProtoVector); |
| 818 const ChildMap& children = child_maps_[directory->resource_id()]; | 824 const ChildMap& children = child_maps_[directory_resource_id]; |
| 819 for (ChildMap::const_iterator iter = children.begin(); | 825 for (ChildMap::const_iterator iter = children.begin(); |
| 820 iter != children.end(); ++iter) { | 826 iter != children.end(); ++iter) { |
| 821 const DriveEntryProto& proto = *GetEntryByResourceId(iter->second); | 827 const DriveEntryProto* child = GetEntryByResourceId(iter->second); |
| 822 entries->push_back(proto); | 828 DCHECK(child); |
| 829 entries->push_back(*child); |
| 823 } | 830 } |
| 824 return entries.Pass(); | 831 return entries.Pass(); |
| 825 } | 832 } |
| 826 | 833 |
| 827 } // namespace drive | 834 } // namespace drive |
| OLD | NEW |