Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: chrome/browser/chromeos/drive/drive_resource_metadata.cc

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

Powered by Google App Engine
This is Rietveld 408576698