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 "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/sys_info.h" | 10 #include "base/sys_info.h" |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
540 return FileMoveResult(FILE_ERROR_NO_SPACE); | 540 return FileMoveResult(FILE_ERROR_NO_SPACE); |
541 | 541 |
542 // Disallow deletion of special entries "/drive" and "/drive/other". | 542 // Disallow deletion of special entries "/drive" and "/drive/other". |
543 if (util::IsSpecialResourceId(resource_id)) | 543 if (util::IsSpecialResourceId(resource_id)) |
544 return FileMoveResult(FILE_ERROR_ACCESS_DENIED); | 544 return FileMoveResult(FILE_ERROR_ACCESS_DENIED); |
545 | 545 |
546 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(resource_id); | 546 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(resource_id); |
547 if (!entry) | 547 if (!entry) |
548 return FileMoveResult(FILE_ERROR_NOT_FOUND); | 548 return FileMoveResult(FILE_ERROR_NOT_FOUND); |
549 | 549 |
550 RemoveDirectoryChild(entry->resource_id()); | 550 if (!RemoveEntryRecursively(entry->resource_id())) |
551 return FileMoveResult(FILE_ERROR_FAILED); | |
552 | |
551 return FileMoveResult(FILE_ERROR_OK, | 553 return FileMoveResult(FILE_ERROR_OK, |
552 GetFilePath(entry->parent_resource_id())); | 554 GetFilePath(entry->parent_resource_id())); |
553 } | 555 } |
554 | 556 |
555 scoped_ptr<DriveEntryProto> DriveResourceMetadata::FindEntryByPathSync( | 557 scoped_ptr<DriveEntryProto> DriveResourceMetadata::FindEntryByPathSync( |
556 const base::FilePath& file_path) { | 558 const base::FilePath& file_path) { |
557 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 559 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
558 | 560 |
559 // Start from the root. | 561 // Start from the root. |
560 scoped_ptr<DriveEntryProto> entry = | 562 scoped_ptr<DriveEntryProto> entry = |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
672 return FILE_ERROR_INVALID_OPERATION; | 674 return FILE_ERROR_INVALID_OPERATION; |
673 | 675 |
674 // Update data. | 676 // Update data. |
675 scoped_ptr<DriveEntryProto> new_parent = | 677 scoped_ptr<DriveEntryProto> new_parent = |
676 GetDirectory(entry.parent_resource_id()); | 678 GetDirectory(entry.parent_resource_id()); |
677 | 679 |
678 if (!new_parent) | 680 if (!new_parent) |
679 return FILE_ERROR_NOT_FOUND; | 681 return FILE_ERROR_NOT_FOUND; |
680 | 682 |
681 // Remove from the old parent and add it to the new parent with the new data. | 683 // Remove from the old parent and add it to the new parent with the new data. |
682 DetachEntryFromDirectory(old_entry->resource_id()); | 684 if (!AddEntryToDirectory(CreateEntryWithProperBaseName(entry))) |
683 AddEntryToDirectory(CreateEntryWithProperBaseName(entry)); | 685 return FILE_ERROR_FAILED; |
684 | 686 |
685 if (out_file_path) | 687 if (out_file_path) |
686 *out_file_path = GetFilePath(entry.resource_id()); | 688 *out_file_path = GetFilePath(entry.resource_id()); |
687 | 689 |
688 if (out_entry) { | 690 if (out_entry) { |
689 // Note that base_name is not the same for the new entry and entry_proto. | 691 // Note that base_name is not the same for the new entry and entry_proto. |
690 scoped_ptr<DriveEntryProto> result_entry_proto = | 692 scoped_ptr<DriveEntryProto> result_entry_proto = |
691 storage_->GetEntry(entry.resource_id()); | 693 storage_->GetEntry(entry.resource_id()); |
692 DCHECK(result_entry_proto); | 694 DCHECK(result_entry_proto); |
693 *out_entry = *result_entry_proto; | 695 *out_entry = *result_entry_proto; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
732 // have a parent resource ID which does not match the target directory's. | 734 // have a parent resource ID which does not match the target directory's. |
733 // | 735 // |
734 // TODO(satorux): Move the filtering logic to somewhere more appropriate. | 736 // TODO(satorux): Move the filtering logic to somewhere more appropriate. |
735 // crbug.com/193525. | 737 // crbug.com/193525. |
736 if (entry_proto.parent_resource_id() != | 738 if (entry_proto.parent_resource_id() != |
737 directory_fetch_info.resource_id()) { | 739 directory_fetch_info.resource_id()) { |
738 DVLOG(1) << "Wrong-parent entry rejected: " << entry_proto.resource_id(); | 740 DVLOG(1) << "Wrong-parent entry rejected: " << entry_proto.resource_id(); |
739 continue; | 741 continue; |
740 } | 742 } |
741 | 743 |
742 scoped_ptr<DriveEntryProto> existing_entry = | 744 if (!AddEntryToDirectory(CreateEntryWithProperBaseName(entry_proto))) |
743 storage_->GetEntry(entry_proto.resource_id()); | 745 return FileMoveResult(FILE_ERROR_FAILED); |
744 if (existing_entry) | |
745 DetachEntryFromDirectory(entry_proto.resource_id()); | |
746 | |
747 AddEntryToDirectory(CreateEntryWithProperBaseName(entry_proto)); | |
748 } | 746 } |
749 | 747 |
750 // Go through the existing entries and remove deleted entries. | 748 // Go through the existing entries and remove deleted entries. |
751 scoped_ptr<DriveEntryProtoVector> entries = | 749 scoped_ptr<DriveEntryProtoVector> entries = |
752 DirectoryChildrenToProtoVector(directory->resource_id()); | 750 DirectoryChildrenToProtoVector(directory->resource_id()); |
753 for (size_t i = 0; i < entries->size(); ++i) { | 751 for (size_t i = 0; i < entries->size(); ++i) { |
754 if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) | 752 if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
755 return FileMoveResult(FILE_ERROR_NO_SPACE); | 753 return FileMoveResult(FILE_ERROR_NO_SPACE); |
756 | 754 |
757 const DriveEntryProto& entry_proto = entries->at(i); | 755 const DriveEntryProto& entry_proto = entries->at(i); |
758 if (entry_proto_map.count(entry_proto.resource_id()) == 0) | 756 if (entry_proto_map.count(entry_proto.resource_id()) == 0) { |
759 RemoveDirectoryChild(entry_proto.resource_id()); | 757 if (!RemoveEntryRecursively(entry_proto.resource_id())) |
758 return FileMoveResult(FILE_ERROR_FAILED); | |
759 } | |
760 } | 760 } |
761 | 761 |
762 return FileMoveResult(FILE_ERROR_OK, GetFilePath(directory->resource_id())); | 762 return FileMoveResult(FILE_ERROR_OK, GetFilePath(directory->resource_id())); |
763 } | 763 } |
764 | 764 |
765 DriveResourceMetadata::FileMoveResult | 765 DriveResourceMetadata::FileMoveResult |
766 DriveResourceMetadata::AddEntryOnBlockingPool( | 766 DriveResourceMetadata::AddEntryOnBlockingPool( |
767 const DriveEntryProto& entry_proto) { | 767 const DriveEntryProto& entry_proto) { |
768 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 768 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
769 | 769 |
770 if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) | 770 if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
771 return FileMoveResult(FILE_ERROR_NO_SPACE); | 771 return FileMoveResult(FILE_ERROR_NO_SPACE); |
772 | 772 |
773 scoped_ptr<DriveEntryProto> existing_entry = | 773 scoped_ptr<DriveEntryProto> existing_entry = |
774 storage_->GetEntry(entry_proto.resource_id()); | 774 storage_->GetEntry(entry_proto.resource_id()); |
775 if (existing_entry) | 775 if (existing_entry) |
776 return FileMoveResult(FILE_ERROR_EXISTS); | 776 return FileMoveResult(FILE_ERROR_EXISTS); |
777 | 777 |
778 scoped_ptr<DriveEntryProto> parent = | 778 scoped_ptr<DriveEntryProto> parent = |
779 GetDirectory(entry_proto.parent_resource_id()); | 779 GetDirectory(entry_proto.parent_resource_id()); |
780 if (!parent) | 780 if (!parent) |
781 return FileMoveResult(FILE_ERROR_NOT_FOUND); | 781 return FileMoveResult(FILE_ERROR_NOT_FOUND); |
782 | 782 |
783 AddEntryToDirectory(entry_proto); | 783 if (!AddEntryToDirectory(entry_proto)) |
784 return FileMoveResult(FILE_ERROR_FAILED); | |
785 | |
784 return FileMoveResult(FILE_ERROR_OK, GetFilePath(entry_proto.resource_id())); | 786 return FileMoveResult(FILE_ERROR_OK, GetFilePath(entry_proto.resource_id())); |
785 } | 787 } |
786 | 788 |
787 scoped_ptr<DriveEntryProto> DriveResourceMetadata::GetDirectory( | 789 scoped_ptr<DriveEntryProto> DriveResourceMetadata::GetDirectory( |
788 const std::string& resource_id) { | 790 const std::string& resource_id) { |
789 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 791 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
790 DCHECK(!resource_id.empty()); | 792 DCHECK(!resource_id.empty()); |
791 | 793 |
792 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(resource_id); | 794 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(resource_id); |
793 return entry && entry->file_info().is_directory() ? | 795 return entry && entry->file_info().is_directory() ? |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
840 | 842 |
841 void DriveResourceMetadata::RemoveAllOnBlockingPool() { | 843 void DriveResourceMetadata::RemoveAllOnBlockingPool() { |
842 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 844 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
843 | 845 |
844 // TODO(hashimoto): Return FILE_ERROR_NO_SPACE here. | 846 // TODO(hashimoto): Return FILE_ERROR_NO_SPACE here. |
845 if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) { | 847 if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) { |
846 LOG(ERROR) << "Required disk space not available."; | 848 LOG(ERROR) << "Required disk space not available."; |
847 return; | 849 return; |
848 } | 850 } |
849 | 851 |
850 RemoveDirectoryChildren(util::kDriveGrandRootSpecialResourceId); | 852 RemoveEntryRecursively(util::kDriveGrandRootSpecialResourceId); |
851 SetUpDefaultEntries(); | 853 SetUpDefaultEntries(); |
852 } | 854 } |
853 | 855 |
854 void DriveResourceMetadata::IterateEntriesOnBlockingPool( | 856 void DriveResourceMetadata::IterateEntriesOnBlockingPool( |
855 const IterateCallback& callback) { | 857 const IterateCallback& callback) { |
856 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 858 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
857 DCHECK(!callback.is_null()); | 859 DCHECK(!callback.is_null()); |
858 | 860 |
859 storage_->Iterate(callback); | 861 storage_->Iterate(callback); |
860 } | 862 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
899 DCHECK(!callback.is_null()); | 901 DCHECK(!callback.is_null()); |
900 DCHECK(result.get()); | 902 DCHECK(result.get()); |
901 | 903 |
902 result->second.path = second_path; | 904 result->second.path = second_path; |
903 result->second.error = error; | 905 result->second.error = error; |
904 result->second.proto = entry_proto.Pass(); | 906 result->second.proto = entry_proto.Pass(); |
905 | 907 |
906 callback.Run(result.Pass()); | 908 callback.Run(result.Pass()); |
907 } | 909 } |
908 | 910 |
909 void DriveResourceMetadata::AddEntryToDirectory(const DriveEntryProto& entry) { | 911 bool DriveResourceMetadata::AddEntryToDirectory(const DriveEntryProto& entry) { |
hidehiko
2013/04/24 07:29:45
AddEntryToDirectory sounds weird because this does
hashimoto
2013/04/24 08:05:56
Renamed to PutEntryUnderDirectory.
| |
910 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 912 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
911 | 913 |
912 DriveEntryProto updated_entry(entry); | 914 DriveEntryProto updated_entry(entry); |
913 | 915 |
914 // The entry name may have been changed due to prior name de-duplication. | 916 // The entry name may have been changed due to prior name de-duplication. |
915 // We need to first restore the file name based on the title before going | 917 // We need to first restore the file name based on the title before going |
916 // through name de-duplication again when it is added to another directory. | 918 // through name de-duplication again when it is added to another directory. |
917 SetBaseNameFromTitle(&updated_entry); | 919 SetBaseNameFromTitle(&updated_entry); |
918 | 920 |
919 // Do file name de-duplication - find files with the same name and | 921 // Do file name de-duplication - Keep changing |entry|'s name until there is |
920 // append a name modifier to the name. | 922 // no other entry with the same name under the parent. |
921 int modifier = 1; | 923 int modifier = 1; |
922 std::string new_base_name = updated_entry.base_name(); | 924 std::string new_base_name = updated_entry.base_name(); |
923 while (!storage_->GetChild(entry.parent_resource_id(), | 925 while (true) { |
924 new_base_name).empty()) { | 926 const std::string existing_entry_id = |
927 storage_->GetChild(entry.parent_resource_id(), new_base_name); | |
928 if (existing_entry_id.empty() || existing_entry_id == entry.resource_id()) | |
929 break; | |
930 | |
925 base::FilePath new_path = | 931 base::FilePath new_path = |
926 base::FilePath::FromUTF8Unsafe(updated_entry.base_name()); | 932 base::FilePath::FromUTF8Unsafe(updated_entry.base_name()); |
927 new_path = | 933 new_path = |
928 new_path.InsertBeforeExtension(base::StringPrintf(" (%d)", ++modifier)); | 934 new_path.InsertBeforeExtension(base::StringPrintf(" (%d)", ++modifier)); |
929 new_base_name = new_path.AsUTF8Unsafe(); | 935 new_base_name = new_path.AsUTF8Unsafe(); |
930 } | 936 } |
931 updated_entry.set_base_name(new_base_name); | 937 updated_entry.set_base_name(new_base_name); |
932 | 938 |
933 // Setup child and parent links. | |
934 storage_->PutChild(entry.parent_resource_id(), | |
935 updated_entry.base_name(), | |
936 updated_entry.resource_id()); | |
937 | |
938 // Add the entry to resource map. | 939 // Add the entry to resource map. |
939 storage_->PutEntry(updated_entry); | 940 return storage_->PutEntry(updated_entry); |
940 } | 941 } |
941 | 942 |
942 void DriveResourceMetadata::RemoveDirectoryChild( | 943 bool DriveResourceMetadata::RemoveEntryRecursively( |
943 const std::string& child_resource_id) { | 944 const std::string& resource_id) { |
944 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 945 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
945 | 946 |
946 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(child_resource_id); | 947 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(resource_id); |
947 DCHECK(entry); | |
948 DetachEntryFromDirectory(child_resource_id); | |
949 storage_->RemoveEntry(entry->resource_id()); | |
950 if (entry->file_info().is_directory()) | |
951 RemoveDirectoryChildren(child_resource_id); | |
952 } | |
953 | |
954 void DriveResourceMetadata::DetachEntryFromDirectory( | |
955 const std::string& child_resource_id) { | |
956 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
957 | |
958 scoped_ptr<DriveEntryProto> entry = storage_->GetEntry(child_resource_id); | |
959 DCHECK(entry); | 948 DCHECK(entry); |
960 | 949 |
961 // entry must be present in this directory. | 950 if (entry->file_info().is_directory()) { |
962 DCHECK_EQ(entry->resource_id(), | 951 std::vector<std::string> children; |
963 storage_->GetChild(entry->parent_resource_id(), | 952 storage_->GetChildren(resource_id, &children); |
964 entry->base_name())); | 953 for (size_t i = 0; i < children.size(); ++i) { |
965 | 954 if (!RemoveEntryRecursively(children[i])) |
966 storage_->RemoveChild(entry->parent_resource_id(), entry->base_name()); | 955 return false; |
967 } | 956 } |
968 | 957 } |
969 void DriveResourceMetadata::RemoveDirectoryChildren( | 958 return storage_->RemoveEntry(resource_id); |
970 const std::string& directory_resource_id) { | |
971 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
972 | |
973 std::vector<std::string> children; | |
974 storage_->GetChildren(directory_resource_id, &children); | |
975 for (size_t i = 0; i < children.size(); ++i) | |
976 RemoveDirectoryChild(children[i]); | |
977 } | 959 } |
978 | 960 |
979 scoped_ptr<DriveEntryProtoVector> | 961 scoped_ptr<DriveEntryProtoVector> |
980 DriveResourceMetadata::DirectoryChildrenToProtoVector( | 962 DriveResourceMetadata::DirectoryChildrenToProtoVector( |
981 const std::string& directory_resource_id) { | 963 const std::string& directory_resource_id) { |
982 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 964 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
983 | 965 |
984 scoped_ptr<DriveEntryProtoVector> entries(new DriveEntryProtoVector); | 966 scoped_ptr<DriveEntryProtoVector> entries(new DriveEntryProtoVector); |
985 std::vector<std::string> children; | 967 std::vector<std::string> children; |
986 storage_->GetChildren(directory_resource_id, &children); | 968 storage_->GetChildren(directory_resource_id, &children); |
987 for (size_t i = 0; i < children.size(); ++i) { | 969 for (size_t i = 0; i < children.size(); ++i) { |
988 scoped_ptr<DriveEntryProto> child = storage_->GetEntry(children[i]); | 970 scoped_ptr<DriveEntryProto> child = storage_->GetEntry(children[i]); |
989 DCHECK(child); | 971 DCHECK(child); |
990 entries->push_back(*child); | 972 entries->push_back(*child); |
991 } | 973 } |
992 return entries.Pass(); | 974 return entries.Pass(); |
993 } | 975 } |
994 | 976 |
995 } // namespace drive | 977 } // namespace drive |
OLD | NEW |