Chromium Code Reviews| 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 |