1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h" 6 7 #include "base/bind.h" 8 #include "base/files/file_path.h" 9 #include "base/location.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "chrome/browser/sync_file_system/file_change.h" 12 #include "chrome/browser/sync_file_system/sync_file_metadata.h" 13 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "webkit/browser/fileapi/file_system_url.h" 16 #include "webkit/common/fileapi/file_system_util.h" 17 18 namespace sync_file_system { 19 20 FakeRemoteChangeProcessor::FakeRemoteChangeProcessor() { 21 } 22 23 FakeRemoteChangeProcessor::~FakeRemoteChangeProcessor() { 24 } 25 26 void FakeRemoteChangeProcessor::PrepareForProcessRemoteChange( 27 const fileapi::FileSystemURL& url, 28 const PrepareChangeCallback& callback) { 29 SyncFileMetadata local_metadata; 30 31 if (fileapi::VirtualPath::IsRootPath(url.path())) { 32 // Origin root directory case. 33 local_metadata = SyncFileMetadata( 34 SYNC_FILE_TYPE_DIRECTORY, 0, base::Time::Now()); 35 } 36 37 URLToFileMetadata::iterator found_metadata = local_file_metadata_.find(url); 38 if (found_metadata != local_file_metadata_.end()) 39 local_metadata = found_metadata->second; 40 41 // Override |local_metadata| by applied changes. 42 URLToFileChangesMap::iterator found = applied_changes_.find(url); 43 if (found != applied_changes_.end()) { 44 DCHECK(!found->second.empty()); 45 const FileChange& applied_change = found->second.back(); 46 if (applied_change.IsAddOrUpdate()) { 47 local_metadata = SyncFileMetadata( 48 applied_change.file_type(), 49 100 /* size */, 50 base::Time::Now()); 51 } 52 } 53 54 FileChangeList change_list; 55 URLToFileChangeList::iterator found_list = local_changes_.find(url); 56 if (found_list != local_changes_.end()) 57 change_list = found_list->second; 58 59 base::MessageLoopProxy::current()->PostTask( 60 FROM_HERE, 61 base::Bind(callback, SYNC_STATUS_OK, 62 local_metadata, change_list)); 63 } 64 65 void FakeRemoteChangeProcessor::ApplyRemoteChange( 66 const FileChange& change, 67 const base::FilePath& local_path, 68 const fileapi::FileSystemURL& url, 69 const SyncStatusCallback& callback) { 70 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 71 base::FilePath ancestor = fileapi::VirtualPath::DirName(url.path()); 72 while (true) { 73 fileapi::FileSystemURL ancestor_url = 74 CreateSyncableFileSystemURL(url.origin(), ancestor); 75 if (!ancestor_url.is_valid()) 76 break; 77 78 URLToFileChangeList::iterator found_list = 79 local_changes_.find(ancestor_url); 80 if (found_list != local_changes_.end()) { 81 const FileChange& local_change = found_list->second.back(); 82 if (local_change.IsAddOrUpdate() && 83 local_change.file_type() != SYNC_FILE_TYPE_DIRECTORY) { 84 status = SYNC_FILE_ERROR_NOT_A_DIRECTORY; 85 break; 86 } 87 } 88 89 base::FilePath ancestor_parent = fileapi::VirtualPath::DirName(ancestor); 90 if (ancestor == ancestor_parent) 91 break; 92 ancestor = ancestor_parent; 93 } 94 if (status == SYNC_STATUS_UNKNOWN) { 95 applied_changes_[url].push_back(change); 96 status = SYNC_STATUS_OK; 97 } 98 base::MessageLoopProxy::current()->PostTask( 99 FROM_HERE, base::Bind(callback, status)); 100 } 101 102 void FakeRemoteChangeProcessor::FinalizeRemoteSync( 103 const fileapi::FileSystemURL& url, 104 bool clear_local_changes, 105 const base::Closure& completion_callback) { 106 base::MessageLoopProxy::current()->PostTask(FROM_HERE, completion_callback); 107 } 108 109 void FakeRemoteChangeProcessor::RecordFakeLocalChange( 110 const fileapi::FileSystemURL& url, 111 const FileChange& change, 112 const SyncStatusCallback& callback) { 113 local_changes_[url].Update(change); 114 base::MessageLoopProxy::current()->PostTask( 115 FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); 116 } 117 118 void FakeRemoteChangeProcessor::UpdateLocalFileMetadata( 119 const fileapi::FileSystemURL& url, 120 const FileChange& change) { 121 if (change.IsAddOrUpdate()) { 122 local_file_metadata_[url] = SyncFileMetadata( 123 change.file_type(), 100 /* size */, base::Time::Now()); 124 } else { 125 local_file_metadata_.erase(url); 126 } 127 local_changes_[url].Update(change); 128 } 129 130 void FakeRemoteChangeProcessor::ClearLocalChanges( 131 const fileapi::FileSystemURL& url) { 132 local_changes_.erase(url); 133 } 134 135 const FakeRemoteChangeProcessor::URLToFileChangesMap& 136 FakeRemoteChangeProcessor::GetAppliedRemoteChanges() const { 137 return applied_changes_; 138 } 139 140 void FakeRemoteChangeProcessor::VerifyConsistency( 141 const URLToFileChangesMap& expected_changes) { 142 EXPECT_EQ(expected_changes.size(), applied_changes_.size()); 143 for (URLToFileChangesMap::const_iterator itr = applied_changes_.begin(); 144 itr != applied_changes_.end(); ++itr) { 145 const fileapi::FileSystemURL& url = itr->first; 146 URLToFileChangesMap::const_iterator found = expected_changes.find(url); 147 if (found == expected_changes.end()) { 148 EXPECT_TRUE(found != expected_changes.end()) 149 << "Change not expected for " << url.DebugString(); 150 continue; 151 } 152 153 const std::vector<FileChange>& applied = itr->second; 154 const std::vector<FileChange>& expected = found->second; 155 156 if (applied.empty() || expected.empty()) { 157 EXPECT_TRUE(!applied.empty()); 158 EXPECT_TRUE(!expected.empty()); 159 continue; 160 } 161 162 EXPECT_EQ(expected.size(), applied.size()); 163 164 for (size_t i = 0; i < applied.size() && i < expected.size(); ++i) { 165 EXPECT_EQ(expected[i], applied[i]) 166 << url.DebugString() 167 << " expected:" << expected[i].DebugString() 168 << " applied:" << applied[i].DebugString(); 169 } 170 } 171 } 172 173 } // namespace sync_file_system 174