1 // Copyright 2014 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/drive_backend/sync_worker.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/location.h"
12 #include "base/macros.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "chrome/browser/extensions/test_extension_service.h"
18 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
19 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
20 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
21 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
22 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
23 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
24 #include "components/drive/drive_uploader.h"
25 #include "components/drive/service/fake_drive_service.h"
26 #include "content/public/test/browser_task_environment.h"
27 #include "extensions/browser/extension_registry.h"
28 #include "extensions/common/extension.h"
29 #include "extensions/common/extension_builder.h"
30 #include "extensions/common/extension_set.h"
31 #include "extensions/common/value_builder.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/leveldatabase/leveldb_chrome.h"
34
35 namespace sync_file_system {
36 namespace drive_backend {
37
38 namespace {
39
40 const char kAppID[] = "app_id";
41
EmptyTask(SyncStatusCode status,const SyncStatusCallback & callback)42 void EmptyTask(SyncStatusCode status, const SyncStatusCallback& callback) {
43 base::ThreadTaskRunnerHandle::Get()->PostTask(
44 FROM_HERE, base::BindOnce(callback, status));
45 }
46
47 } // namespace
48
49 class MockSyncTask : public ExclusiveTask {
50 public:
MockSyncTask(bool used_network)51 explicit MockSyncTask(bool used_network) {
52 set_used_network(used_network);
53 }
~MockSyncTask()54 ~MockSyncTask() override {}
55
RunExclusive(const SyncStatusCallback & callback)56 void RunExclusive(const SyncStatusCallback& callback) override {
57 callback.Run(SYNC_STATUS_OK);
58 }
59
60 private:
61 DISALLOW_COPY_AND_ASSIGN(MockSyncTask);
62 };
63
64 class MockExtensionService : public TestExtensionService {
65 public:
MockExtensionService()66 MockExtensionService() : registry_(nullptr) {}
~MockExtensionService()67 ~MockExtensionService() override {}
68
AddExtension(const extensions::Extension * extension)69 void AddExtension(const extensions::Extension* extension) override {
70 registry_.AddEnabled(base::WrapRefCounted(extension));
71 }
72
IsExtensionEnabled(const std::string & extension_id) const73 bool IsExtensionEnabled(const std::string& extension_id) const override {
74 return registry_.enabled_extensions().Contains(extension_id);
75 }
76
UninstallExtension(const std::string & extension_id)77 void UninstallExtension(const std::string& extension_id) {
78 EXPECT_TRUE(registry_.RemoveEnabled(extension_id) ||
79 registry_.RemoveDisabled(extension_id));
80 }
81
DisableExtension(const std::string & extension_id)82 void DisableExtension(const std::string& extension_id) {
83 if (!IsExtensionEnabled(extension_id))
84 return;
85 scoped_refptr<const extensions::Extension> extension =
86 registry_.GetInstalledExtension(extension_id);
87 EXPECT_TRUE(registry_.RemoveEnabled(extension_id));
88 registry_.AddDisabled(extension);
89 }
90
registry()91 extensions::ExtensionRegistry& registry() { return registry_; }
92
93 private:
94 extensions::ExtensionRegistry registry_;
95
96 DISALLOW_COPY_AND_ASSIGN(MockExtensionService);
97 };
98
99 class SyncWorkerTest : public testing::Test,
100 public base::SupportsWeakPtr<SyncWorkerTest> {
101 public:
SyncWorkerTest()102 SyncWorkerTest() {}
~SyncWorkerTest()103 ~SyncWorkerTest() override {}
104
SetUp()105 void SetUp() override {
106 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
107 in_memory_env_ = leveldb_chrome::NewMemEnv("SyncWorkerTest");
108
109 extension_service_.reset(new MockExtensionService);
110 std::unique_ptr<drive::DriveServiceInterface> fake_drive_service(
111 new drive::FakeDriveService);
112
113 std::unique_ptr<SyncEngineContext> sync_engine_context(
114 new SyncEngineContext(
115 std::move(fake_drive_service), nullptr /* drive_uploader */,
116 nullptr /* task_logger */,
117 base::ThreadTaskRunnerHandle::Get() /* ui_task_runner */,
118 base::ThreadTaskRunnerHandle::Get() /* worker_task_runner */));
119
120 sync_worker_.reset(
121 new SyncWorker(profile_dir_.GetPath(), extension_service_->AsWeakPtr(),
122 &extension_service_->registry(), in_memory_env_.get()));
123 sync_worker_->Initialize(std::move(sync_engine_context));
124
125 sync_worker_->SetSyncEnabled(true);
126 base::RunLoop().RunUntilIdle();
127 }
128
TearDown()129 void TearDown() override {
130 sync_worker_.reset();
131 extension_service_.reset();
132 base::RunLoop().RunUntilIdle();
133 }
134
extension_service()135 MockExtensionService* extension_service() { return extension_service_.get(); }
sync_worker()136 SyncWorker* sync_worker() { return sync_worker_.get(); }
137
UpdateRegisteredApps()138 void UpdateRegisteredApps() {
139 sync_worker_->UpdateRegisteredApps();
140 }
141
GetSyncTaskManager()142 SyncTaskManager* GetSyncTaskManager() {
143 return sync_worker_->task_manager_.get();
144 }
145
CheckServiceState(SyncStatusCode expected_sync_status,RemoteServiceState expected_service_status,SyncStatusCode sync_status)146 void CheckServiceState(SyncStatusCode expected_sync_status,
147 RemoteServiceState expected_service_status,
148 SyncStatusCode sync_status) {
149 EXPECT_EQ(expected_sync_status, sync_status);
150 EXPECT_EQ(expected_service_status, sync_worker_->GetCurrentState());
151 }
152
metadata_database()153 MetadataDatabase* metadata_database() {
154 return sync_worker_->GetMetadataDatabase();
155 }
156
157 private:
158 content::BrowserTaskEnvironment task_environment_;
159 base::ScopedTempDir profile_dir_;
160 std::unique_ptr<leveldb::Env> in_memory_env_;
161
162 std::unique_ptr<MockExtensionService> extension_service_;
163 std::unique_ptr<SyncWorker> sync_worker_;
164
165 DISALLOW_COPY_AND_ASSIGN(SyncWorkerTest);
166 };
167
TEST_F(SyncWorkerTest,EnableOrigin)168 TEST_F(SyncWorkerTest, EnableOrigin) {
169 FileTracker tracker;
170 SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
171 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
172
173 sync_worker()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
174 base::RunLoop().RunUntilIdle();
175 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
176 ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
177 EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
178
179 sync_worker()->DisableOrigin(origin, CreateResultReceiver(&sync_status));
180 base::RunLoop().RunUntilIdle();
181 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
182 ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
183 EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
184
185 sync_worker()->EnableOrigin(origin, CreateResultReceiver(&sync_status));
186 base::RunLoop().RunUntilIdle();
187 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
188 ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
189 EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
190
191 sync_worker()->UninstallOrigin(
192 origin,
193 RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
194 CreateResultReceiver(&sync_status));
195 base::RunLoop().RunUntilIdle();
196 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
197 ASSERT_FALSE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
198 }
199
TEST_F(SyncWorkerTest,UpdateRegisteredApps)200 TEST_F(SyncWorkerTest, UpdateRegisteredApps) {
201 SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
202 for (int i = 0; i < 3; i++) {
203 scoped_refptr<const extensions::Extension> extension =
204 extensions::ExtensionBuilder()
205 .SetManifest(extensions::DictionaryBuilder()
206 .Set("name", "foo")
207 .Set("version", "1.0")
208 .Set("manifest_version", 2)
209 .Build())
210 .SetID(base::StringPrintf("app_%d", i))
211 .Build();
212 extension_service()->AddExtension(extension.get());
213 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(
214 extension->id());
215 sync_status = SYNC_STATUS_UNKNOWN;
216 sync_worker()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
217 base::RunLoop().RunUntilIdle();
218 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
219 }
220
221 FileTracker tracker;
222
223 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker));
224 EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
225
226 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker));
227 EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
228
229 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_2", &tracker));
230 EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
231
232 extension_service()->DisableExtension("app_1");
233 extension_service()->UninstallExtension("app_2");
234 ASSERT_FALSE(extension_service()->registry().GetInstalledExtension("app_2"));
235 UpdateRegisteredApps();
236 base::RunLoop().RunUntilIdle();
237
238 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker));
239 EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
240
241 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker));
242 EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
243
244 ASSERT_FALSE(metadata_database()->FindAppRootTracker("app_2", &tracker));
245 }
246
TEST_F(SyncWorkerTest,GetOriginStatusMap)247 TEST_F(SyncWorkerTest, GetOriginStatusMap) {
248 FileTracker tracker;
249 SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
250 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
251
252 sync_worker()->RegisterOrigin(GURL("chrome-extension://app_0"),
253 CreateResultReceiver(&sync_status));
254 base::RunLoop().RunUntilIdle();
255 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
256
257 sync_worker()->RegisterOrigin(GURL("chrome-extension://app_1"),
258 CreateResultReceiver(&sync_status));
259 base::RunLoop().RunUntilIdle();
260 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
261
262 std::unique_ptr<RemoteFileSyncService::OriginStatusMap> status_map;
263 sync_worker()->GetOriginStatusMap(CreateResultReceiver(&status_map));
264 base::RunLoop().RunUntilIdle();
265 ASSERT_EQ(2u, status_map->size());
266 EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_0")]);
267 EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_1")]);
268
269 sync_worker()->DisableOrigin(GURL("chrome-extension://app_1"),
270 CreateResultReceiver(&sync_status));
271 base::RunLoop().RunUntilIdle();
272 EXPECT_EQ(SYNC_STATUS_OK, sync_status);
273
274 sync_worker()->GetOriginStatusMap(CreateResultReceiver(&status_map));
275 base::RunLoop().RunUntilIdle();
276 ASSERT_EQ(2u, status_map->size());
277 EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_0")]);
278 EXPECT_EQ("Disabled", (*status_map)[GURL("chrome-extension://app_1")]);
279 }
280
TEST_F(SyncWorkerTest,UpdateServiceState)281 TEST_F(SyncWorkerTest, UpdateServiceState) {
282 EXPECT_EQ(REMOTE_SERVICE_OK, sync_worker()->GetCurrentState());
283
284 GetSyncTaskManager()->ScheduleTask(
285 FROM_HERE,
286 base::Bind(&EmptyTask, SYNC_STATUS_AUTHENTICATION_FAILED),
287 SyncTaskManager::PRIORITY_MED,
288 base::Bind(&SyncWorkerTest::CheckServiceState,
289 AsWeakPtr(),
290 SYNC_STATUS_AUTHENTICATION_FAILED,
291 REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
292
293 GetSyncTaskManager()->ScheduleTask(
294 FROM_HERE,
295 base::Bind(&EmptyTask, SYNC_STATUS_ACCESS_FORBIDDEN),
296 SyncTaskManager::PRIORITY_MED,
297 base::Bind(&SyncWorkerTest::CheckServiceState,
298 AsWeakPtr(),
299 SYNC_STATUS_ACCESS_FORBIDDEN,
300 REMOTE_SERVICE_ACCESS_FORBIDDEN));
301
302 GetSyncTaskManager()->ScheduleTask(
303 FROM_HERE,
304 base::Bind(&EmptyTask, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE),
305 SyncTaskManager::PRIORITY_MED,
306 base::Bind(&SyncWorkerTest::CheckServiceState,
307 AsWeakPtr(),
308 SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE,
309 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
310
311 GetSyncTaskManager()->ScheduleTask(
312 FROM_HERE,
313 base::Bind(&EmptyTask, SYNC_STATUS_NETWORK_ERROR),
314 SyncTaskManager::PRIORITY_MED,
315 base::Bind(&SyncWorkerTest::CheckServiceState,
316 AsWeakPtr(),
317 SYNC_STATUS_NETWORK_ERROR,
318 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
319
320 GetSyncTaskManager()->ScheduleTask(
321 FROM_HERE,
322 base::Bind(&EmptyTask, SYNC_STATUS_ABORT),
323 SyncTaskManager::PRIORITY_MED,
324 base::Bind(&SyncWorkerTest::CheckServiceState,
325 AsWeakPtr(),
326 SYNC_STATUS_ABORT,
327 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
328
329 GetSyncTaskManager()->ScheduleTask(
330 FROM_HERE,
331 base::Bind(&EmptyTask, SYNC_STATUS_FAILED),
332 SyncTaskManager::PRIORITY_MED,
333 base::Bind(&SyncWorkerTest::CheckServiceState,
334 AsWeakPtr(),
335 SYNC_STATUS_FAILED,
336 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
337
338 GetSyncTaskManager()->ScheduleTask(
339 FROM_HERE,
340 base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_CORRUPTION),
341 SyncTaskManager::PRIORITY_MED,
342 base::Bind(&SyncWorkerTest::CheckServiceState,
343 AsWeakPtr(),
344 SYNC_DATABASE_ERROR_CORRUPTION,
345 REMOTE_SERVICE_DISABLED));
346
347 GetSyncTaskManager()->ScheduleTask(
348 FROM_HERE,
349 base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_IO_ERROR),
350 SyncTaskManager::PRIORITY_MED,
351 base::Bind(&SyncWorkerTest::CheckServiceState,
352 AsWeakPtr(),
353 SYNC_DATABASE_ERROR_IO_ERROR,
354 REMOTE_SERVICE_DISABLED));
355
356 GetSyncTaskManager()->ScheduleTask(
357 FROM_HERE,
358 base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_FAILED),
359 SyncTaskManager::PRIORITY_MED,
360 base::Bind(&SyncWorkerTest::CheckServiceState,
361 AsWeakPtr(),
362 SYNC_DATABASE_ERROR_FAILED,
363 REMOTE_SERVICE_DISABLED));
364
365 GetSyncTaskManager()->ScheduleSyncTask(
366 FROM_HERE, std::unique_ptr<SyncTask>(new MockSyncTask(false)),
367 SyncTaskManager::PRIORITY_MED,
368 base::Bind(&SyncWorkerTest::CheckServiceState, AsWeakPtr(),
369 SYNC_STATUS_OK, REMOTE_SERVICE_DISABLED));
370
371 GetSyncTaskManager()->ScheduleSyncTask(
372 FROM_HERE, std::unique_ptr<SyncTask>(new MockSyncTask(true)),
373 SyncTaskManager::PRIORITY_MED,
374 base::Bind(&SyncWorkerTest::CheckServiceState, AsWeakPtr(),
375 SYNC_STATUS_OK, REMOTE_SERVICE_OK));
376
377 base::RunLoop().RunUntilIdle();
378 }
379
380 } // namespace drive_backend
381 } // namespace sync_file_system
382