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 |