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

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_file_system.cc

Issue 10408071: gdata: Fix a crash when adding a new file to a new but deleted directory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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/gdata/gdata_file_system.h" 5 #include "chrome/browser/chromeos/gdata/gdata_file_system.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include <set> 10 #include <set>
(...skipping 3625 matching lines...) Expand 10 before | Expand all | Expand 10 after
3636 &file_map, 3636 &file_map,
3637 &delta_feed_changestamp, 3637 &delta_feed_changestamp,
3638 &num_regular_files, 3638 &num_regular_files,
3639 &num_hosted_documents); 3639 &num_hosted_documents);
3640 if (error != base::PLATFORM_FILE_OK) 3640 if (error != base::PLATFORM_FILE_OK)
3641 return error; 3641 return error;
3642 3642
3643 ApplyFeedFromFileUrlMap( 3643 ApplyFeedFromFileUrlMap(
3644 is_delta_feed, 3644 is_delta_feed,
3645 is_delta_feed ? delta_feed_changestamp : root_feed_changestamp, 3645 is_delta_feed ? delta_feed_changestamp : root_feed_changestamp,
3646 file_map); 3646 &file_map);
3647 3647
3648 if (should_notify_initial_load) 3648 if (should_notify_initial_load)
3649 NotifyInitialLoadFinished(); 3649 NotifyInitialLoadFinished();
3650 3650
3651 const int num_total_files = num_hosted_documents + num_regular_files; 3651 const int num_total_files = num_hosted_documents + num_regular_files;
3652 UMA_HISTOGRAM_COUNTS("GData.NumberOfRegularFiles", num_regular_files); 3652 UMA_HISTOGRAM_COUNTS("GData.NumberOfRegularFiles", num_regular_files);
3653 UMA_HISTOGRAM_COUNTS("GData.NumberOfHostedDocuments", 3653 UMA_HISTOGRAM_COUNTS("GData.NumberOfHostedDocuments",
3654 num_hosted_documents); 3654 num_hosted_documents);
3655 UMA_HISTOGRAM_COUNTS("GData.NumberOfTotalFiles", num_total_files); 3655 UMA_HISTOGRAM_COUNTS("GData.NumberOfTotalFiles", num_total_files);
3656 return base::PLATFORM_FILE_OK; 3656 return base::PLATFORM_FILE_OK;
3657 } 3657 }
3658 3658
3659 void GDataFileSystem::ApplyFeedFromFileUrlMap( 3659 void GDataFileSystem::ApplyFeedFromFileUrlMap(
3660 bool is_delta_feed, 3660 bool is_delta_feed,
3661 int feed_changestamp, 3661 int feed_changestamp,
3662 const FileResourceIdMap& file_map) { 3662 FileResourceIdMap* file_map) {
3663 lock_.AssertAcquired(); 3663 lock_.AssertAcquired();
3664 // Don't send directory content change notification while performing 3664 // Don't send directory content change notification while performing
3665 // the initial content retrieval. 3665 // the initial content retrieval.
3666 const bool should_notify_directory_changed = is_delta_feed; 3666 const bool should_notify_directory_changed = is_delta_feed;
3667 3667
3668 std::set<FilePath> changed_dirs; 3668 std::set<FilePath> changed_dirs;
3669 3669
3670 if (!is_delta_feed) { // Full update. 3670 if (!is_delta_feed) { // Full update.
3671 root_->RemoveChildren(); 3671 root_->RemoveChildren();
3672 changed_dirs.insert(root_->GetFilePath()); 3672 changed_dirs.insert(root_->GetFilePath());
3673 } 3673 }
3674 root_->set_largest_changestamp(feed_changestamp); 3674 root_->set_largest_changestamp(feed_changestamp);
3675 3675
3676 scoped_ptr<GDataRootDirectory> orphaned_entries_dir( 3676 scoped_ptr<GDataRootDirectory> orphaned_entries_dir(
3677 new GDataRootDirectory); 3677 new GDataRootDirectory);
3678 // Go through all entires generated by the feed and apply them to the local 3678 // Go through all entires generated by the feed and apply them to the local
3679 // snapshot of the file system. 3679 // snapshot of the file system.
3680 for (FileResourceIdMap::const_iterator it = file_map.begin(); 3680 for (FileResourceIdMap::iterator it = file_map->begin();
3681 it != file_map.end(); ++it) { 3681 it != file_map->end();) {
3682 // Ensure that the entry is deleted, unless the ownership is explicitly
3683 // transferred by entry.release().
3682 scoped_ptr<GDataEntry> entry(it->second); 3684 scoped_ptr<GDataEntry> entry(it->second);
3683 DCHECK_EQ(it->first, entry->resource_id()); 3685 DCHECK_EQ(it->first, entry->resource_id());
3686 // Erase the entry so the deleted entry won't be referenced.
3687 file_map->erase(it++);
3688
3684 GDataEntry* old_entry = root_->GetEntryByResourceId(entry->resource_id()); 3689 GDataEntry* old_entry = root_->GetEntryByResourceId(entry->resource_id());
3685 GDataDirectory* dest_dir = NULL; 3690 GDataDirectory* dest_dir = NULL;
3686 if (entry->is_deleted()) { // Deleted file/directory. 3691 if (entry->is_deleted()) { // Deleted file/directory.
3687 DVLOG(1) << "Removing file " << entry->file_name(); 3692 DVLOG(1) << "Removing file " << entry->file_name();
3688 if (!old_entry) 3693 if (!old_entry)
3689 continue; 3694 continue;
3690 3695
3691 dest_dir = old_entry->parent(); 3696 dest_dir = old_entry->parent();
3692 if (!dest_dir) { 3697 if (!dest_dir) {
3693 NOTREACHED(); 3698 NOTREACHED();
(...skipping 15 matching lines...) Expand all
3709 entry->AsGDataDirectory()->TakeOverEntries( 3714 entry->AsGDataDirectory()->TakeOverEntries(
3710 old_entry->AsGDataDirectory()); 3715 old_entry->AsGDataDirectory());
3711 } 3716 }
3712 // Remove the old instance of this entry. 3717 // Remove the old instance of this entry.
3713 RemoveEntryFromDirectoryAndCollectChangedDirectories( 3718 RemoveEntryFromDirectoryAndCollectChangedDirectories(
3714 dest_dir, old_entry, &changed_dirs); 3719 dest_dir, old_entry, &changed_dirs);
3715 // Did we actually move the new file to another directory? 3720 // Did we actually move the new file to another directory?
3716 if (dest_dir->resource_id() != entry->parent_resource_id()) { 3721 if (dest_dir->resource_id() != entry->parent_resource_id()) {
3717 changed_dirs.insert(dest_dir->GetFilePath()); 3722 changed_dirs.insert(dest_dir->GetFilePath());
3718 dest_dir = FindDirectoryForNewEntry(entry.get(), 3723 dest_dir = FindDirectoryForNewEntry(entry.get(),
3719 file_map, 3724 *file_map,
3720 orphaned_entries_dir.get()); 3725 orphaned_entries_dir.get());
3721 } 3726 }
3722 DCHECK(dest_dir); 3727 DCHECK(dest_dir);
3723 AddEntryToDirectoryAndCollectChangedDirectories( 3728 AddEntryToDirectoryAndCollectChangedDirectories(
3724 entry.release(), 3729 entry.release(),
3725 dest_dir, 3730 dest_dir,
3726 orphaned_entries_dir.get(), 3731 orphaned_entries_dir.get(),
3727 &changed_dirs); 3732 &changed_dirs);
3728 } else { // Adding a new file. 3733 } else { // Adding a new file.
3729 dest_dir = FindDirectoryForNewEntry(entry.get(), 3734 dest_dir = FindDirectoryForNewEntry(entry.get(),
3730 file_map, 3735 *file_map,
3731 orphaned_entries_dir.get()); 3736 orphaned_entries_dir.get());
3732 DCHECK(dest_dir); 3737 DCHECK(dest_dir);
3733 AddEntryToDirectoryAndCollectChangedDirectories( 3738 AddEntryToDirectoryAndCollectChangedDirectories(
3734 entry.release(), 3739 entry.release(),
3735 dest_dir, 3740 dest_dir,
3736 orphaned_entries_dir.get(), 3741 orphaned_entries_dir.get(),
3737 &changed_dirs); 3742 &changed_dirs);
3738 } 3743 }
3739 3744
3740 // Record changed directory if this was a delta feed and the parent 3745 // Record changed directory if this was a delta feed and the parent
3741 // directory is already properly rooted within its parent. 3746 // directory is already properly rooted within its parent.
3742 if (dest_dir && (dest_dir->parent() || dest_dir == root_.get()) && 3747 if (dest_dir && (dest_dir->parent() || dest_dir == root_.get()) &&
3743 dest_dir != orphaned_entries_dir.get() && is_delta_feed) { 3748 dest_dir != orphaned_entries_dir.get() && is_delta_feed) {
3744 changed_dirs.insert(dest_dir->GetFilePath()); 3749 changed_dirs.insert(dest_dir->GetFilePath());
3745 } 3750 }
3746 } 3751 }
3752 // All entry must be erased from the map.
3753 DCHECK(file_map->empty());
3747 3754
3748 if (should_notify_directory_changed) { 3755 if (should_notify_directory_changed) {
3749 for (std::set<FilePath>::iterator dir_iter = changed_dirs.begin(); 3756 for (std::set<FilePath>::iterator dir_iter = changed_dirs.begin();
3750 dir_iter != changed_dirs.end(); ++dir_iter) { 3757 dir_iter != changed_dirs.end(); ++dir_iter) {
3751 NotifyDirectoryChanged(*dir_iter); 3758 NotifyDirectoryChanged(*dir_iter);
3752 } 3759 }
3753 } 3760 }
3754 } 3761 }
3755 3762
3756 GDataDirectory* GDataFileSystem::FindDirectoryForNewEntry( 3763 GDataDirectory* GDataFileSystem::FindDirectoryForNewEntry(
3757 GDataEntry* new_entry, 3764 GDataEntry* new_entry,
3758 const FileResourceIdMap& file_map, 3765 const FileResourceIdMap& file_map,
3759 GDataRootDirectory* orphaned_entries_dir) { 3766 GDataRootDirectory* orphaned_entries_dir) {
3760 GDataDirectory* dir = NULL; 3767 GDataDirectory* dir = NULL;
3761 // Added file. 3768 // Added file.
3762 const std::string& parent_id = new_entry->parent_resource_id(); 3769 const std::string& parent_id = new_entry->parent_resource_id();
3763 if (parent_id.empty()) { 3770 if (parent_id.empty()) {
3764 dir = root_.get(); 3771 dir = root_.get();
3765 DVLOG(1) << "Root parent for " << new_entry->file_name(); 3772 DVLOG(1) << "Root parent for " << new_entry->file_name();
3766 } else { 3773 } else {
3767 GDataEntry* entry = root_->GetEntryByResourceId(parent_id); 3774 GDataEntry* entry = root_->GetEntryByResourceId(parent_id);
3768 dir = entry ? entry->AsGDataDirectory() : NULL; 3775 dir = entry ? entry->AsGDataDirectory() : NULL;
3769 if (!dir) { 3776 if (!dir) {
3770 // The parent directory was also added with this set of feeds. 3777 // The parent directory was also added with this set of feeds.
3771 FileResourceIdMap::const_iterator find_iter = 3778 FileResourceIdMap::const_iterator find_iter =
3772 file_map.find(parent_id); 3779 file_map.find(parent_id);
3773 dir = (find_iter != file_map.end() && 3780 dir = (find_iter != file_map.end() &&
3774 find_iter->second) ? 3781 find_iter->second) ?
3775 find_iter->second->AsGDataDirectory() : NULL; 3782 find_iter->second->AsGDataDirectory() : NULL;
3776 DVLOG(1) << "Found parent for " << new_entry->file_name() 3783 if (dir) {
3777 << " in map " << parent_id; 3784 DVLOG(1) << "Found parent for " << new_entry->file_name()
3778 if (!dir) { 3785 << " in file_map " << parent_id;
3786 } else {
3779 DVLOG(1) << "Adding orphan " << new_entry->GetFilePath().value(); 3787 DVLOG(1) << "Adding orphan " << new_entry->GetFilePath().value();
3780 dir = orphaned_entries_dir; 3788 dir = orphaned_entries_dir;
3781 } 3789 }
3782 } 3790 }
3783 } 3791 }
3784 return dir; 3792 return dir;
3785 } 3793 }
3786 3794
3787 base::PlatformFileError GDataFileSystem::FeedToFileResourceMap( 3795 base::PlatformFileError GDataFileSystem::FeedToFileResourceMap(
3788 const std::vector<DocumentFeed*>& feed_list, 3796 const std::vector<DocumentFeed*>& feed_list,
(...skipping 1464 matching lines...) Expand 10 before | Expand all | Expand 10 after
5253 pref_registrar_->Init(profile_->GetPrefs()); 5261 pref_registrar_->Init(profile_->GetPrefs());
5254 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); 5262 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this);
5255 } 5263 }
5256 5264
5257 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { 5265 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) {
5258 delete global_free_disk_getter_for_testing; // Safe to delete NULL; 5266 delete global_free_disk_getter_for_testing; // Safe to delete NULL;
5259 global_free_disk_getter_for_testing = getter; 5267 global_free_disk_getter_for_testing = getter;
5260 } 5268 }
5261 5269
5262 } // namespace gdata 5270 } // namespace gdata
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_file_system.h ('k') | chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698