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.
5 #include "chrome/browser/sync_file_system/drive_backend/sync_worker.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chrome/browser/drive/drive_uploader.h"
12 #include "chrome/browser/drive/fake_drive_service.h"
13 #include "chrome/browser/extensions/test_extension_service.h"
14 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
15 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
16 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
17 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
18 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
19 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/extension_builder.h"
23 #include "extensions/common/extension_set.h"
24 #include "extensions/common/value_builder.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
27 #include "third_party/leveldatabase/src/include/leveldb/env.h"
29 namespace sync_file_system
{
30 namespace drive_backend
{
34 const char kAppID
[] = "app_id";
36 void EmptyTask(SyncStatusCode status
, const SyncStatusCallback
& callback
) {
37 base::MessageLoop::current()->PostTask(
38 FROM_HERE
, base::Bind(callback
, status
));
43 class MockSyncTask
: public ExclusiveTask
{
45 explicit MockSyncTask(bool used_network
) {
46 set_used_network(used_network
);
48 virtual ~MockSyncTask() {}
50 virtual void RunExclusive(const SyncStatusCallback
& callback
) OVERRIDE
{
51 callback
.Run(SYNC_STATUS_OK
);
55 DISALLOW_COPY_AND_ASSIGN(MockSyncTask
);
58 class MockExtensionService
: public TestExtensionService
{
60 MockExtensionService() {}
61 virtual ~MockExtensionService() {}
63 virtual const extensions::ExtensionSet
* extensions() const OVERRIDE
{
67 virtual void AddExtension(const extensions::Extension
* extension
) OVERRIDE
{
68 extensions_
.Insert(make_scoped_refptr(extension
));
71 virtual const extensions::Extension
* GetInstalledExtension(
72 const std::string
& extension_id
) const OVERRIDE
{
73 return extensions_
.GetByID(extension_id
);
76 virtual bool IsExtensionEnabled(
77 const std::string
& extension_id
) const OVERRIDE
{
78 return extensions_
.Contains(extension_id
) &&
79 !disabled_extensions_
.Contains(extension_id
);
82 void UninstallExtension(const std::string
& extension_id
) {
83 extensions_
.Remove(extension_id
);
84 disabled_extensions_
.Remove(extension_id
);
87 void DisableExtension(const std::string
& extension_id
) {
88 if (!IsExtensionEnabled(extension_id
))
90 const extensions::Extension
* extension
= extensions_
.GetByID(extension_id
);
91 disabled_extensions_
.Insert(make_scoped_refptr(extension
));
95 extensions::ExtensionSet extensions_
;
96 extensions::ExtensionSet disabled_extensions_
;
98 DISALLOW_COPY_AND_ASSIGN(MockExtensionService
);
101 class SyncWorkerTest
: public testing::Test
,
102 public base::SupportsWeakPtr
<SyncWorkerTest
> {
105 virtual ~SyncWorkerTest() {}
107 virtual void SetUp() OVERRIDE
{
108 ASSERT_TRUE(profile_dir_
.CreateUniqueTempDir());
109 in_memory_env_
.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
111 extension_service_
.reset(new MockExtensionService
);
112 scoped_ptr
<drive::DriveServiceInterface
>
113 fake_drive_service(new drive::FakeDriveService
);
115 scoped_ptr
<SyncEngineContext
>
116 sync_engine_context(new SyncEngineContext(
117 fake_drive_service
.Pass(),
118 scoped_ptr
<drive::DriveUploaderInterface
>(),
119 NULL
/* task_logger */,
120 base::ThreadTaskRunnerHandle::Get() /* ui_task_runner */,
121 base::ThreadTaskRunnerHandle::Get() /* worker_task_runner */));
123 sync_worker_
.reset(new SyncWorker(
125 extension_service_
->AsWeakPtr(),
126 in_memory_env_
.get()));
127 sync_worker_
->Initialize(sync_engine_context
.Pass());
129 sync_worker_
->SetSyncEnabled(true);
130 base::RunLoop().RunUntilIdle();
133 virtual void TearDown() OVERRIDE
{
134 sync_worker_
.reset();
135 extension_service_
.reset();
136 base::RunLoop().RunUntilIdle();
139 MockExtensionService
* extension_service() { return extension_service_
.get(); }
140 SyncWorker
* sync_worker() { return sync_worker_
.get(); }
142 void UpdateRegisteredApps() {
143 sync_worker_
->UpdateRegisteredApps();
146 SyncTaskManager
* GetSyncTaskManager() {
147 return sync_worker_
->task_manager_
.get();
150 void CheckServiceState(SyncStatusCode expected_sync_status
,
151 RemoteServiceState expected_service_status
,
152 SyncStatusCode sync_status
) {
153 EXPECT_EQ(expected_sync_status
, sync_status
);
154 EXPECT_EQ(expected_service_status
, sync_worker_
->GetCurrentState());
157 MetadataDatabase
* metadata_database() {
158 return sync_worker_
->GetMetadataDatabase();
162 content::TestBrowserThreadBundle browser_threads_
;
163 base::ScopedTempDir profile_dir_
;
164 scoped_ptr
<leveldb::Env
> in_memory_env_
;
166 scoped_ptr
<MockExtensionService
> extension_service_
;
167 scoped_ptr
<SyncWorker
> sync_worker_
;
169 DISALLOW_COPY_AND_ASSIGN(SyncWorkerTest
);
172 TEST_F(SyncWorkerTest
, EnableOrigin
) {
174 SyncStatusCode sync_status
= SYNC_STATUS_UNKNOWN
;
175 GURL origin
= extensions::Extension::GetBaseURLFromExtensionId(kAppID
);
177 sync_worker()->RegisterOrigin(origin
, CreateResultReceiver(&sync_status
));
178 base::RunLoop().RunUntilIdle();
179 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
180 ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID
, &tracker
));
181 EXPECT_EQ(TRACKER_KIND_APP_ROOT
, tracker
.tracker_kind());
183 sync_worker()->DisableOrigin(origin
, CreateResultReceiver(&sync_status
));
184 base::RunLoop().RunUntilIdle();
185 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
186 ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID
, &tracker
));
187 EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT
, tracker
.tracker_kind());
189 sync_worker()->EnableOrigin(origin
, CreateResultReceiver(&sync_status
));
190 base::RunLoop().RunUntilIdle();
191 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
192 ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID
, &tracker
));
193 EXPECT_EQ(TRACKER_KIND_APP_ROOT
, tracker
.tracker_kind());
195 sync_worker()->UninstallOrigin(
197 RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE
,
198 CreateResultReceiver(&sync_status
));
199 base::RunLoop().RunUntilIdle();
200 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
201 ASSERT_FALSE(metadata_database()->FindAppRootTracker(kAppID
, &tracker
));
204 TEST_F(SyncWorkerTest
, UpdateRegisteredApps
) {
205 SyncStatusCode sync_status
= SYNC_STATUS_UNKNOWN
;
206 for (int i
= 0; i
< 3; i
++) {
207 scoped_refptr
<const extensions::Extension
> extension
=
208 extensions::ExtensionBuilder()
209 .SetManifest(extensions::DictionaryBuilder()
211 .Set("version", "1.0")
212 .Set("manifest_version", 2))
213 .SetID(base::StringPrintf("app_%d", i
))
215 extension_service()->AddExtension(extension
.get());
216 GURL origin
= extensions::Extension::GetBaseURLFromExtensionId(
218 sync_status
= SYNC_STATUS_UNKNOWN
;
219 sync_worker()->RegisterOrigin(origin
, CreateResultReceiver(&sync_status
));
220 base::RunLoop().RunUntilIdle();
221 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
226 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker
));
227 EXPECT_EQ(TRACKER_KIND_APP_ROOT
, tracker
.tracker_kind());
229 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker
));
230 EXPECT_EQ(TRACKER_KIND_APP_ROOT
, tracker
.tracker_kind());
232 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_2", &tracker
));
233 EXPECT_EQ(TRACKER_KIND_APP_ROOT
, tracker
.tracker_kind());
235 extension_service()->DisableExtension("app_1");
236 extension_service()->UninstallExtension("app_2");
237 ASSERT_FALSE(extension_service()->GetInstalledExtension("app_2"));
238 UpdateRegisteredApps();
239 base::RunLoop().RunUntilIdle();
241 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker
));
242 EXPECT_EQ(TRACKER_KIND_APP_ROOT
, tracker
.tracker_kind());
244 ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker
));
245 EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT
, tracker
.tracker_kind());
247 ASSERT_FALSE(metadata_database()->FindAppRootTracker("app_2", &tracker
));
250 TEST_F(SyncWorkerTest
, GetOriginStatusMap
) {
252 SyncStatusCode sync_status
= SYNC_STATUS_UNKNOWN
;
253 GURL origin
= extensions::Extension::GetBaseURLFromExtensionId(kAppID
);
255 sync_worker()->RegisterOrigin(GURL("chrome-extension://app_0"),
256 CreateResultReceiver(&sync_status
));
257 base::RunLoop().RunUntilIdle();
258 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
260 sync_worker()->RegisterOrigin(GURL("chrome-extension://app_1"),
261 CreateResultReceiver(&sync_status
));
262 base::RunLoop().RunUntilIdle();
263 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
265 scoped_ptr
<RemoteFileSyncService::OriginStatusMap
> status_map
;
266 sync_worker()->GetOriginStatusMap(CreateResultReceiver(&status_map
));
267 base::RunLoop().RunUntilIdle();
268 ASSERT_EQ(2u, status_map
->size());
269 EXPECT_EQ("Enabled", (*status_map
)[GURL("chrome-extension://app_0")]);
270 EXPECT_EQ("Enabled", (*status_map
)[GURL("chrome-extension://app_1")]);
272 sync_worker()->DisableOrigin(GURL("chrome-extension://app_1"),
273 CreateResultReceiver(&sync_status
));
274 base::RunLoop().RunUntilIdle();
275 EXPECT_EQ(SYNC_STATUS_OK
, sync_status
);
277 sync_worker()->GetOriginStatusMap(CreateResultReceiver(&status_map
));
278 base::RunLoop().RunUntilIdle();
279 ASSERT_EQ(2u, status_map
->size());
280 EXPECT_EQ("Enabled", (*status_map
)[GURL("chrome-extension://app_0")]);
281 EXPECT_EQ("Disabled", (*status_map
)[GURL("chrome-extension://app_1")]);
284 TEST_F(SyncWorkerTest
, UpdateServiceState
) {
285 EXPECT_EQ(REMOTE_SERVICE_OK
, sync_worker()->GetCurrentState());
287 GetSyncTaskManager()->ScheduleTask(
289 base::Bind(&EmptyTask
, SYNC_STATUS_AUTHENTICATION_FAILED
),
290 SyncTaskManager::PRIORITY_MED
,
291 base::Bind(&SyncWorkerTest::CheckServiceState
,
293 SYNC_STATUS_AUTHENTICATION_FAILED
,
294 REMOTE_SERVICE_AUTHENTICATION_REQUIRED
));
296 GetSyncTaskManager()->ScheduleTask(
298 base::Bind(&EmptyTask
, SYNC_STATUS_ACCESS_FORBIDDEN
),
299 SyncTaskManager::PRIORITY_MED
,
300 base::Bind(&SyncWorkerTest::CheckServiceState
,
302 SYNC_STATUS_ACCESS_FORBIDDEN
,
303 REMOTE_SERVICE_ACCESS_FORBIDDEN
));
305 GetSyncTaskManager()->ScheduleTask(
307 base::Bind(&EmptyTask
, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE
),
308 SyncTaskManager::PRIORITY_MED
,
309 base::Bind(&SyncWorkerTest::CheckServiceState
,
311 SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE
,
312 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
));
314 GetSyncTaskManager()->ScheduleTask(
316 base::Bind(&EmptyTask
, SYNC_STATUS_NETWORK_ERROR
),
317 SyncTaskManager::PRIORITY_MED
,
318 base::Bind(&SyncWorkerTest::CheckServiceState
,
320 SYNC_STATUS_NETWORK_ERROR
,
321 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
));
323 GetSyncTaskManager()->ScheduleTask(
325 base::Bind(&EmptyTask
, SYNC_STATUS_ABORT
),
326 SyncTaskManager::PRIORITY_MED
,
327 base::Bind(&SyncWorkerTest::CheckServiceState
,
330 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
));
332 GetSyncTaskManager()->ScheduleTask(
334 base::Bind(&EmptyTask
, SYNC_STATUS_FAILED
),
335 SyncTaskManager::PRIORITY_MED
,
336 base::Bind(&SyncWorkerTest::CheckServiceState
,
339 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE
));
341 GetSyncTaskManager()->ScheduleTask(
343 base::Bind(&EmptyTask
, SYNC_DATABASE_ERROR_CORRUPTION
),
344 SyncTaskManager::PRIORITY_MED
,
345 base::Bind(&SyncWorkerTest::CheckServiceState
,
347 SYNC_DATABASE_ERROR_CORRUPTION
,
348 REMOTE_SERVICE_DISABLED
));
350 GetSyncTaskManager()->ScheduleTask(
352 base::Bind(&EmptyTask
, SYNC_DATABASE_ERROR_IO_ERROR
),
353 SyncTaskManager::PRIORITY_MED
,
354 base::Bind(&SyncWorkerTest::CheckServiceState
,
356 SYNC_DATABASE_ERROR_IO_ERROR
,
357 REMOTE_SERVICE_DISABLED
));
359 GetSyncTaskManager()->ScheduleTask(
361 base::Bind(&EmptyTask
, SYNC_DATABASE_ERROR_FAILED
),
362 SyncTaskManager::PRIORITY_MED
,
363 base::Bind(&SyncWorkerTest::CheckServiceState
,
365 SYNC_DATABASE_ERROR_FAILED
,
366 REMOTE_SERVICE_DISABLED
));
368 GetSyncTaskManager()->ScheduleSyncTask(
370 scoped_ptr
<SyncTask
>(new MockSyncTask(false)),
371 SyncTaskManager::PRIORITY_MED
,
372 base::Bind(&SyncWorkerTest::CheckServiceState
,
375 REMOTE_SERVICE_DISABLED
));
377 GetSyncTaskManager()->ScheduleSyncTask(
379 scoped_ptr
<SyncTask
>(new MockSyncTask(true)),
380 SyncTaskManager::PRIORITY_MED
,
381 base::Bind(&SyncWorkerTest::CheckServiceState
,
386 base::RunLoop().RunUntilIdle();
389 } // namespace drive_backend
390 } // namespace sync_file_system