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

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

Issue 23258006: drive: Move RefreshDirectory from ResourceMetadata to ChangeListLoader (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comment fix Created 7 years, 4 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 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/change_list_processor.h" 5 #include "chrome/browser/chromeos/drive/change_list_processor.h"
6 6
7 #include "base/files/scoped_temp_dir.h" 7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop_proxy.h" 8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "chrome/browser/chromeos/drive/drive.pb.h" 10 #include "chrome/browser/chromeos/drive/drive.pb.h"
11 #include "chrome/browser/chromeos/drive/file_system_util.h" 11 #include "chrome/browser/chromeos/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/drive/resource_metadata.h" 12 #include "chrome/browser/chromeos/drive/resource_metadata.h"
13 #include "chrome/browser/chromeos/drive/test_util.h" 13 #include "chrome/browser/chromeos/drive/test_util.h"
14 #include "chrome/browser/google_apis/drive_api_parser.h" 14 #include "chrome/browser/google_apis/drive_api_parser.h"
15 #include "chrome/browser/google_apis/gdata_wapi_parser.h" 15 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
16 #include "chrome/browser/google_apis/test_util.h" 16 #include "chrome/browser/google_apis/test_util.h"
17 #include "content/public/test/test_browser_thread_bundle.h" 17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
19 19
20 namespace drive { 20 namespace drive {
21 namespace internal { 21 namespace internal {
22 22
23 namespace { 23 namespace {
24 24
25 const int64 kBaseResourceListChangestamp = 123; 25 const int64 kBaseResourceListChangestamp = 123;
26 const char kBaseResourceListFile[] = "gdata/root_feed.json"; 26 const char kBaseResourceListFile[] = "gdata/root_feed.json";
27 const char kRootId[] = "fake_root";
27 28
28 enum FileOrDirectory { 29 enum FileOrDirectory {
29 FILE, 30 FILE,
30 DIRECTORY, 31 DIRECTORY,
31 }; 32 };
32 33
33 struct EntryExpectation { 34 struct EntryExpectation {
34 std::string path; 35 std::string path;
35 std::string id; 36 std::string id;
36 std::string parent_id; 37 std::string parent_id;
(...skipping 24 matching lines...) Expand all
61 test_data_path)))); 62 test_data_path))));
62 return changes.Pass(); 63 return changes.Pass();
63 } 64 }
64 65
65 // Applies the |changes| to |metadata_| as a full resource list of changestamp 66 // Applies the |changes| to |metadata_| as a full resource list of changestamp
66 // |kBaseResourceListChangestamp|. 67 // |kBaseResourceListChangestamp|.
67 void ApplyFullResourceList(ScopedVector<ChangeList> changes) { 68 void ApplyFullResourceList(ScopedVector<ChangeList> changes) {
68 scoped_ptr<google_apis::AboutResource> about_resource( 69 scoped_ptr<google_apis::AboutResource> about_resource(
69 new google_apis::AboutResource); 70 new google_apis::AboutResource);
70 about_resource->set_largest_change_id(kBaseResourceListChangestamp); 71 about_resource->set_largest_change_id(kBaseResourceListChangestamp);
71 about_resource->set_root_folder_id("fake_root"); 72 about_resource->set_root_folder_id(kRootId);
72 73
73 ChangeListProcessor processor(metadata_.get()); 74 ChangeListProcessor processor(metadata_.get());
74 processor.Apply(about_resource.Pass(), 75 processor.Apply(about_resource.Pass(),
75 changes.Pass(), 76 changes.Pass(),
76 false /* is_delta_update */); 77 false /* is_delta_update */);
77 } 78 }
78 79
79 // Applies the |changes| to |metadata_| as a delta update. Delta changelists 80 // Applies the |changes| to |metadata_| as a delta update. Delta changelists
80 // should contain their changestamp in themselves. 81 // should contain their changestamp in themselves.
81 std::set<base::FilePath> ApplyChangeList(ScopedVector<ChangeList> changes) { 82 std::set<base::FilePath> ApplyChangeList(ScopedVector<ChangeList> changes) {
(...skipping 23 matching lines...) Expand all
105 }; 106 };
106 107
107 } // namespace 108 } // namespace
108 109
109 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) { 110 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) {
110 ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)); 111 ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
111 112
112 const EntryExpectation kExpected[] = { 113 const EntryExpectation kExpected[] = {
113 // Root files 114 // Root files
114 {"drive/root", 115 {"drive/root",
115 "fake_root", util::kDriveGrandRootSpecialResourceId, DIRECTORY}, 116 kRootId, util::kDriveGrandRootSpecialResourceId, DIRECTORY},
116 {"drive/root/File 1.txt", 117 {"drive/root/File 1.txt",
117 "file:2_file_resource_id", "fake_root", FILE}, 118 "file:2_file_resource_id", kRootId, FILE},
118 {"drive/root/Slash \xE2\x88\x95 in file 1.txt", 119 {"drive/root/Slash \xE2\x88\x95 in file 1.txt",
119 "file:slash_file_resource_id", "fake_root", FILE}, 120 "file:slash_file_resource_id", kRootId, FILE},
120 {"drive/root/Document 1 excludeDir-test.gdoc", 121 {"drive/root/Document 1 excludeDir-test.gdoc",
121 "document:5_document_resource_id", "fake_root", FILE}, 122 "document:5_document_resource_id", kRootId, FILE},
122 // Subdirectory files 123 // Subdirectory files
123 {"drive/root/Directory 1", 124 {"drive/root/Directory 1",
124 "folder:1_folder_resource_id", "fake_root", DIRECTORY}, 125 "folder:1_folder_resource_id", kRootId, DIRECTORY},
125 {"drive/root/Directory 1/SubDirectory File 1.txt", 126 {"drive/root/Directory 1/SubDirectory File 1.txt",
126 "file:subdirectory_file_1_id", "folder:1_folder_resource_id", FILE}, 127 "file:subdirectory_file_1_id", "folder:1_folder_resource_id", FILE},
127 {"drive/root/Directory 1/Shared To The Account Owner.txt", 128 {"drive/root/Directory 1/Shared To The Account Owner.txt",
128 "file:subdirectory_unowned_file_1_id", 129 "file:subdirectory_unowned_file_1_id",
129 "folder:1_folder_resource_id", FILE}, 130 "folder:1_folder_resource_id", FILE},
130 {"drive/root/Directory 2 excludeDir-test", 131 {"drive/root/Directory 2 excludeDir-test",
131 "folder:sub_dir_folder_2_self_link", "fake_root", DIRECTORY}, 132 "folder:sub_dir_folder_2_self_link", kRootId, DIRECTORY},
132 {"drive/root/Slash \xE2\x88\x95 in directory", 133 {"drive/root/Slash \xE2\x88\x95 in directory",
133 "folder:slash_dir_folder_resource_id", "fake_root", DIRECTORY}, 134 "folder:slash_dir_folder_resource_id", kRootId, DIRECTORY},
134 {"drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt", 135 {"drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt",
135 "file:slash_subdir_file", 136 "file:slash_subdir_file",
136 "folder:slash_dir_folder_resource_id", FILE}, 137 "folder:slash_dir_folder_resource_id", FILE},
137 // Deeper 138 // Deeper
138 {"drive/root/Directory 1/Sub Directory Folder", 139 {"drive/root/Directory 1/Sub Directory Folder",
139 "folder:sub_dir_folder_resource_id", 140 "folder:sub_dir_folder_resource_id",
140 "folder:1_folder_resource_id", DIRECTORY}, 141 "folder:1_folder_resource_id", DIRECTORY},
141 {"drive/root/Directory 1/Sub Directory Folder/Sub Sub Directory Folder", 142 {"drive/root/Directory 1/Sub Directory Folder/Sub Sub Directory Folder",
142 "folder:sub_sub_directory_folder_id", 143 "folder:sub_sub_directory_folder_id",
143 "folder:sub_dir_folder_resource_id", DIRECTORY}, 144 "folder:sub_dir_folder_resource_id", DIRECTORY},
(...skipping 16 matching lines...) Expand all
160 } 161 }
161 162
162 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) { 163 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) {
163 const char kTestJson[] = 164 const char kTestJson[] =
164 "gdata/delta_file_added_in_new_directory.json"; 165 "gdata/delta_file_added_in_new_directory.json";
165 166
166 ChangeListProcessor::ResourceEntryMap entry_map; 167 ChangeListProcessor::ResourceEntryMap entry_map;
167 ChangeListProcessor::ConvertToMap( 168 ChangeListProcessor::ConvertToMap(
168 ParseChangeList(kTestJson), &entry_map, NULL); 169 ParseChangeList(kTestJson), &entry_map, NULL);
169 170
170 const std::string kRootId("fake_root");
171 const std::string kNewFolderId("folder:new_folder_resource_id"); 171 const std::string kNewFolderId("folder:new_folder_resource_id");
172 const std::string kNewFileId("document:file_added_in_new_dir_id"); 172 const std::string kNewFileId("document:file_added_in_new_dir_id");
173 173
174 // Check the content of parsed ResourceEntryMap. 174 // Check the content of parsed ResourceEntryMap.
175 EXPECT_EQ(2U, entry_map.size()); 175 EXPECT_EQ(2U, entry_map.size());
176 EXPECT_TRUE(entry_map.count(kNewFolderId)); 176 EXPECT_TRUE(entry_map.count(kNewFolderId));
177 EXPECT_TRUE(entry_map.count(kNewFileId)); 177 EXPECT_TRUE(entry_map.count(kNewFileId));
178 EXPECT_EQ(kRootId, entry_map[kNewFolderId].parent_local_id()); 178 EXPECT_EQ(kRootId, entry_map[kNewFolderId].parent_local_id());
179 EXPECT_EQ(kNewFolderId, entry_map[kNewFileId].parent_local_id()); 179 EXPECT_EQ(kNewFolderId, entry_map[kNewFileId].parent_local_id());
180 EXPECT_TRUE(entry_map[kNewFolderId].file_info().is_directory()); 180 EXPECT_TRUE(entry_map[kNewFolderId].file_info().is_directory());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 } 242 }
243 243
244 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) { 244 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) {
245 const char kTestJson[] = 245 const char kTestJson[] =
246 "gdata/delta_file_moved_from_directory_to_root.json"; 246 "gdata/delta_file_moved_from_directory_to_root.json";
247 247
248 ChangeListProcessor::ResourceEntryMap entry_map; 248 ChangeListProcessor::ResourceEntryMap entry_map;
249 ChangeListProcessor::ConvertToMap( 249 ChangeListProcessor::ConvertToMap(
250 ParseChangeList(kTestJson), &entry_map, NULL); 250 ParseChangeList(kTestJson), &entry_map, NULL);
251 251
252 const std::string kRootId("fake_root");
253 const std::string kMovedId("file:subdirectory_file_1_id"); 252 const std::string kMovedId("file:subdirectory_file_1_id");
254 const std::string kSrcId("folder:1_folder_resource_id"); 253 const std::string kSrcId("folder:1_folder_resource_id");
255 254
256 // Check the content of parsed ResourceEntryMap. 255 // Check the content of parsed ResourceEntryMap.
257 EXPECT_EQ(2U, entry_map.size()); 256 EXPECT_EQ(2U, entry_map.size());
258 EXPECT_TRUE(entry_map.count(kMovedId)); 257 EXPECT_TRUE(entry_map.count(kMovedId));
259 EXPECT_TRUE(entry_map.count(kSrcId)); 258 EXPECT_TRUE(entry_map.count(kSrcId));
260 EXPECT_EQ(kRootId, entry_map[kMovedId].parent_local_id()); 259 EXPECT_EQ(kRootId, entry_map[kMovedId].parent_local_id());
261 260
262 // Apply the changelist and check the effect. 261 // Apply the changelist and check the effect.
(...skipping 15 matching lines...) Expand all
278 } 277 }
279 278
280 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) { 279 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) {
281 const char kTestJson[] = 280 const char kTestJson[] =
282 "gdata/delta_file_renamed_in_directory.json"; 281 "gdata/delta_file_renamed_in_directory.json";
283 282
284 ChangeListProcessor::ResourceEntryMap entry_map; 283 ChangeListProcessor::ResourceEntryMap entry_map;
285 ChangeListProcessor::ConvertToMap( 284 ChangeListProcessor::ConvertToMap(
286 ParseChangeList(kTestJson), &entry_map, NULL); 285 ParseChangeList(kTestJson), &entry_map, NULL);
287 286
288 const std::string kRootId("fake_root");
289 const std::string kRenamedId("file:subdirectory_file_1_id"); 287 const std::string kRenamedId("file:subdirectory_file_1_id");
290 const std::string kParentId("folder:1_folder_resource_id"); 288 const std::string kParentId("folder:1_folder_resource_id");
291 289
292 // Check the content of parsed ResourceEntryMap. 290 // Check the content of parsed ResourceEntryMap.
293 EXPECT_EQ(2U, entry_map.size()); 291 EXPECT_EQ(2U, entry_map.size());
294 EXPECT_TRUE(entry_map.count(kRenamedId)); 292 EXPECT_TRUE(entry_map.count(kRenamedId));
295 EXPECT_TRUE(entry_map.count(kParentId)); 293 EXPECT_TRUE(entry_map.count(kParentId));
296 EXPECT_EQ(kParentId, entry_map[kRenamedId].parent_local_id()); 294 EXPECT_EQ(kParentId, entry_map[kRenamedId].parent_local_id());
297 EXPECT_EQ("New SubDirectory File 1.txt", entry_map[kRenamedId].title()); 295 EXPECT_EQ("New SubDirectory File 1.txt", entry_map[kRenamedId].title());
298 296
(...skipping 15 matching lines...) Expand all
314 EXPECT_TRUE(changed_dirs.count( 312 EXPECT_TRUE(changed_dirs.count(
315 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1"))); 313 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
316 } 314 }
317 315
318 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) { 316 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) {
319 const char kTestJsonAdd[] = 317 const char kTestJsonAdd[] =
320 "gdata/delta_file_added_in_root.json"; 318 "gdata/delta_file_added_in_root.json";
321 const char kTestJsonDelete[] = 319 const char kTestJsonDelete[] =
322 "gdata/delta_file_deleted_in_root.json"; 320 "gdata/delta_file_deleted_in_root.json";
323 321
324 const std::string kParentId("fake_root"); 322 const std::string kParentId(kRootId);
325 const std::string kFileId("document:added_in_root_id"); 323 const std::string kFileId("document:added_in_root_id");
326 324
327 ChangeListProcessor::ResourceEntryMap entry_map; 325 ChangeListProcessor::ResourceEntryMap entry_map;
328 326
329 // Check the content of kTestJsonAdd. 327 // Check the content of kTestJsonAdd.
330 ChangeListProcessor::ConvertToMap( 328 ChangeListProcessor::ConvertToMap(
331 ParseChangeList(kTestJsonAdd), &entry_map, NULL); 329 ParseChangeList(kTestJsonAdd), &entry_map, NULL);
332 EXPECT_EQ(1U, entry_map.size()); 330 EXPECT_EQ(1U, entry_map.size());
333 EXPECT_TRUE(entry_map.count(kFileId)); 331 EXPECT_TRUE(entry_map.count(kFileId));
334 EXPECT_EQ(kParentId, entry_map[kFileId].parent_local_id()); 332 EXPECT_EQ(kParentId, entry_map[kFileId].parent_local_id());
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 // 1) A new PDF file is added to a new directory 422 // 1) A new PDF file is added to a new directory
425 // 2) but the new directory is marked "deleted" (i.e. moved to Trash) 423 // 2) but the new directory is marked "deleted" (i.e. moved to Trash)
426 // Hence, the PDF file should be just ignored. 424 // Hence, the PDF file should be just ignored.
427 const char kTestJson[] = 425 const char kTestJson[] =
428 "gdata/delta_file_added_in_new_but_deleted_directory.json"; 426 "gdata/delta_file_added_in_new_but_deleted_directory.json";
429 427
430 ChangeListProcessor::ResourceEntryMap entry_map; 428 ChangeListProcessor::ResourceEntryMap entry_map;
431 ChangeListProcessor::ConvertToMap( 429 ChangeListProcessor::ConvertToMap(
432 ParseChangeList(kTestJson), &entry_map, NULL); 430 ParseChangeList(kTestJson), &entry_map, NULL);
433 431
434 const std::string kRootId("fake_root");
435 const std::string kDirId("folder:new_folder_resource_id"); 432 const std::string kDirId("folder:new_folder_resource_id");
436 const std::string kFileId("pdf:file_added_in_deleted_dir_id"); 433 const std::string kFileId("pdf:file_added_in_deleted_dir_id");
437 434
438 // Check the content of parsed ResourceEntryMap. 435 // Check the content of parsed ResourceEntryMap.
439 EXPECT_EQ(2U, entry_map.size()); 436 EXPECT_EQ(2U, entry_map.size());
440 EXPECT_TRUE(entry_map.count(kDirId)); 437 EXPECT_TRUE(entry_map.count(kDirId));
441 EXPECT_TRUE(entry_map.count(kFileId)); 438 EXPECT_TRUE(entry_map.count(kFileId));
442 EXPECT_EQ(kDirId, entry_map[kFileId].parent_local_id()); 439 EXPECT_EQ(kDirId, entry_map[kFileId].parent_local_id());
443 EXPECT_TRUE(entry_map[kDirId].deleted()); 440 EXPECT_TRUE(entry_map[kDirId].deleted());
444 441
445 // Apply the changelist and check the effect. 442 // Apply the changelist and check the effect.
446 ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)); 443 ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
447 std::set<base::FilePath> changed_dirs = 444 std::set<base::FilePath> changed_dirs =
448 ApplyChangeList(ParseChangeList(kTestJson)); 445 ApplyChangeList(ParseChangeList(kTestJson));
449 446
450 // The value is written in kTestJson. 447 // The value is written in kTestJson.
451 EXPECT_EQ(16730, metadata_->GetLargestChangestamp()); 448 EXPECT_EQ(16730, metadata_->GetLargestChangestamp());
452 EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf")); 449 EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf"));
453 450
454 EXPECT_TRUE(changed_dirs.empty()); 451 EXPECT_TRUE(changed_dirs.empty());
455 } 452 }
456 453
454 TEST_F(ChangeListProcessorTest, RefreshDirectory) {
455 // Prepare metadata.
456 ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
457
458 // Create a map.
459 ChangeListProcessor::ResourceEntryMap entry_map;
460
461 // Add a new file to the map.
462 ResourceEntry new_file;
463 new_file.set_title("new_file");
464 new_file.set_resource_id("new_file_id");
465 new_file.set_parent_local_id(kRootId);
466 entry_map["new_file_id"] = new_file;
467
468 // Add "Directory 1" to the map with a new name.
469 ResourceEntry dir1;
470 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
471 util::GetDriveMyDriveRootPath().AppendASCII("Directory 1"), &dir1));
472 dir1.set_title(dir1.title() + " (renamed)");
473 entry_map[dir1.resource_id()] = dir1;
474
475 // Update the directory with the map.
476 const int64 kNewChangestamp = 12345;
477 base::FilePath file_path;
478 EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory(
479 metadata_.get(),
480 DirectoryFetchInfo(kRootId, kNewChangestamp),
481 entry_map,
482 &file_path));
483 EXPECT_EQ(util::GetDriveMyDriveRootPath().value(), file_path.value());
484
485 // The new changestamp should be set.
486 ResourceEntry entry;
487 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
488 util::GetDriveMyDriveRootPath(), &entry));
489 EXPECT_EQ(kNewChangestamp, entry.directory_specific_info().changestamp());
490
491 // "new_file" should be added.
492 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
493 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
494
495 // "Directory 1" should be renamed.
496 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
497 util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry));
498 }
499
500 TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) {
501 // Prepare metadata.
502 ApplyFullResourceList(ParseChangeList(kBaseResourceListFile));
503
504 // Create a map and add a new file to it.
505 ChangeListProcessor::ResourceEntryMap entry_map;
506 ResourceEntry new_file;
507 new_file.set_title("new_file");
508 new_file.set_resource_id("new_file_id");
509 // This entry should not be added because the parent ID does not match.
510 new_file.set_parent_local_id("some-random-resource-id");
511 entry_map["new_file_id"] = new_file;
512
513 // Update the directory with the map.
514 const int64 kNewChangestamp = 12345;
515 base::FilePath file_path;
516 EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory(
517 metadata_.get(),
518 DirectoryFetchInfo(kRootId, kNewChangestamp),
519 entry_map,
520 &file_path));
521 EXPECT_EQ(util::GetDriveMyDriveRootPath().value(), file_path.value());
522
523 // "new_file" should not be added.
524 ResourceEntry entry;
525 EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath(
526 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
527 }
528
457 } // namespace internal 529 } // namespace internal
458 } // namespace drive 530 } // namespace drive
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/drive/change_list_processor.cc ('k') | chrome/browser/chromeos/drive/file_system.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698