Home | History | Annotate | Download | only in drive_backend
      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 "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"
     28 
     29 namespace sync_file_system {
     30 namespace drive_backend {
     31 
     32 namespace {
     33 
     34 const char kAppID[] = "app_id";
     35 
     36 void EmptyTask(SyncStatusCode status, const SyncStatusCallback& callback) {
     37   base::MessageLoop::current()->PostTask(
     38       FROM_HERE, base::Bind(callback, status));
     39 }
     40 
     41 }  // namespace
     42 
     43 class MockSyncTask : public ExclusiveTask {
     44  public:
     45   explicit MockSyncTask(bool used_network) {
     46     set_used_network(used_network);
     47   }
     48   virtual ~MockSyncTask() {}
     49 
     50   virtual void RunExclusive(const SyncStatusCallback& callback) OVERRIDE {
     51     callback.Run(SYNC_STATUS_OK);
     52   }
     53 
     54  private:
     55   DISALLOW_COPY_AND_ASSIGN(MockSyncTask);
     56 };
     57 
     58 class MockExtensionService : public TestExtensionService {
     59  public:
     60   MockExtensionService() {}
     61   virtual ~MockExtensionService() {}
     62 
     63   virtual const extensions::ExtensionSet* extensions() const OVERRIDE {
     64     return &extensions_;
     65   }
     66 
     67   virtual void AddExtension(const extensions::Extension* extension) OVERRIDE {
     68     extensions_.Insert(make_scoped_refptr(extension));
     69   }
     70 
     71   virtual const extensions::Extension* GetInstalledExtension(
     72       const std::string& extension_id) const OVERRIDE {
     73     return extensions_.GetByID(extension_id);
     74   }
     75 
     76   virtual bool IsExtensionEnabled(
     77       const std::string& extension_id) const OVERRIDE {
     78     return extensions_.Contains(extension_id) &&
     79         !disabled_extensions_.Contains(extension_id);
     80   }
     81 
     82   void UninstallExtension(const std::string& extension_id) {
     83     extensions_.Remove(extension_id);
     84     disabled_extensions_.Remove(extension_id);
     85   }
     86 
     87   void DisableExtension(const std::string& extension_id) {
     88     if (!IsExtensionEnabled(extension_id))
     89       return;
     90     const extensions::Extension* extension = extensions_.GetByID(extension_id);
     91     disabled_extensions_.Insert(make_scoped_refptr(extension));
     92   }
     93 
     94  private:
     95   extensions::ExtensionSet extensions_;
     96   extensions::ExtensionSet disabled_extensions_;
     97 
     98   DISALLOW_COPY_AND_ASSIGN(MockExtensionService);
     99 };
    100 
    101 class SyncWorkerTest : public testing::Test,
    102                        public base::SupportsWeakPtr<SyncWorkerTest> {
    103  public:
    104   SyncWorkerTest() {}
    105   virtual ~SyncWorkerTest() {}
    106 
    107   virtual void SetUp() OVERRIDE {
    108     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
    109     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
    110 
    111     extension_service_.reset(new MockExtensionService);
    112     scoped_ptr<drive::DriveServiceInterface>
    113         fake_drive_service(new drive::FakeDriveService);
    114 
    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 */));
    122 
    123     sync_worker_.reset(new SyncWorker(
    124         profile_dir_.path(),
    125         extension_service_->AsWeakPtr(),
    126         in_memory_env_.get()));
    127     sync_worker_->Initialize(sync_engine_context.Pass());
    128 
    129     sync_worker_->SetSyncEnabled(true);
    130     base::RunLoop().RunUntilIdle();
    131   }
    132 
    133   virtual void TearDown() OVERRIDE {
    134     sync_worker_.reset();
    135     extension_service_.reset();
    136     base::RunLoop().RunUntilIdle();
    137   }
    138 
    139   MockExtensionService* extension_service() { return extension_service_.get(); }
    140   SyncWorker* sync_worker() { return sync_worker_.get(); }
    141 
    142   void UpdateRegisteredApps() {
    143     sync_worker_->UpdateRegisteredApps();
    144   }
    145 
    146   SyncTaskManager* GetSyncTaskManager() {
    147     return sync_worker_->task_manager_.get();
    148   }
    149 
    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());
    155   }
    156 
    157   MetadataDatabase* metadata_database() {
    158     return sync_worker_->GetMetadataDatabase();
    159   }
    160 
    161  private:
    162   content::TestBrowserThreadBundle browser_threads_;
    163   base::ScopedTempDir profile_dir_;
    164   scoped_ptr<leveldb::Env> in_memory_env_;
    165 
    166   scoped_ptr<MockExtensionService> extension_service_;
    167   scoped_ptr<SyncWorker> sync_worker_;
    168 
    169   DISALLOW_COPY_AND_ASSIGN(SyncWorkerTest);
    170 };
    171 
    172 TEST_F(SyncWorkerTest, EnableOrigin) {
    173   FileTracker tracker;
    174   SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
    175   GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
    176 
    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());
    182 
    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());
    188 
    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());
    194 
    195   sync_worker()->UninstallOrigin(
    196       origin,
    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));
    202 }
    203 
    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()
    210                      .Set("name", "foo")
    211                      .Set("version", "1.0")
    212                      .Set("manifest_version", 2))
    213         .SetID(base::StringPrintf("app_%d", i))
    214         .Build();
    215     extension_service()->AddExtension(extension.get());
    216     GURL origin = extensions::Extension::GetBaseURLFromExtensionId(
    217         extension->id());
    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);
    222   }
    223 
    224   FileTracker tracker;
    225 
    226   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker));
    227   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    228 
    229   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker));
    230   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    231 
    232   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_2", &tracker));
    233   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    234 
    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();
    240 
    241   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker));
    242   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    243 
    244   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker));
    245   EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
    246 
    247   ASSERT_FALSE(metadata_database()->FindAppRootTracker("app_2", &tracker));
    248 }
    249 
    250 TEST_F(SyncWorkerTest, GetOriginStatusMap) {
    251   FileTracker tracker;
    252   SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
    253   GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
    254 
    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);
    259 
    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);
    264 
    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")]);
    271 
    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);
    276 
    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")]);
    282 }
    283 
    284 TEST_F(SyncWorkerTest, UpdateServiceState) {
    285   EXPECT_EQ(REMOTE_SERVICE_OK, sync_worker()->GetCurrentState());
    286 
    287   GetSyncTaskManager()->ScheduleTask(
    288       FROM_HERE,
    289       base::Bind(&EmptyTask, SYNC_STATUS_AUTHENTICATION_FAILED),
    290       SyncTaskManager::PRIORITY_MED,
    291       base::Bind(&SyncWorkerTest::CheckServiceState,
    292                  AsWeakPtr(),
    293                  SYNC_STATUS_AUTHENTICATION_FAILED,
    294                  REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
    295 
    296   GetSyncTaskManager()->ScheduleTask(
    297       FROM_HERE,
    298       base::Bind(&EmptyTask, SYNC_STATUS_ACCESS_FORBIDDEN),
    299       SyncTaskManager::PRIORITY_MED,
    300       base::Bind(&SyncWorkerTest::CheckServiceState,
    301                  AsWeakPtr(),
    302                  SYNC_STATUS_ACCESS_FORBIDDEN,
    303                  REMOTE_SERVICE_ACCESS_FORBIDDEN));
    304 
    305   GetSyncTaskManager()->ScheduleTask(
    306       FROM_HERE,
    307       base::Bind(&EmptyTask, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE),
    308       SyncTaskManager::PRIORITY_MED,
    309       base::Bind(&SyncWorkerTest::CheckServiceState,
    310                  AsWeakPtr(),
    311                  SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE,
    312                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    313 
    314   GetSyncTaskManager()->ScheduleTask(
    315       FROM_HERE,
    316       base::Bind(&EmptyTask, SYNC_STATUS_NETWORK_ERROR),
    317       SyncTaskManager::PRIORITY_MED,
    318       base::Bind(&SyncWorkerTest::CheckServiceState,
    319                  AsWeakPtr(),
    320                  SYNC_STATUS_NETWORK_ERROR,
    321                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    322 
    323   GetSyncTaskManager()->ScheduleTask(
    324       FROM_HERE,
    325       base::Bind(&EmptyTask, SYNC_STATUS_ABORT),
    326       SyncTaskManager::PRIORITY_MED,
    327       base::Bind(&SyncWorkerTest::CheckServiceState,
    328                  AsWeakPtr(),
    329                  SYNC_STATUS_ABORT,
    330                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    331 
    332   GetSyncTaskManager()->ScheduleTask(
    333       FROM_HERE,
    334       base::Bind(&EmptyTask, SYNC_STATUS_FAILED),
    335       SyncTaskManager::PRIORITY_MED,
    336       base::Bind(&SyncWorkerTest::CheckServiceState,
    337                  AsWeakPtr(),
    338                  SYNC_STATUS_FAILED,
    339                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    340 
    341   GetSyncTaskManager()->ScheduleTask(
    342       FROM_HERE,
    343       base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_CORRUPTION),
    344       SyncTaskManager::PRIORITY_MED,
    345       base::Bind(&SyncWorkerTest::CheckServiceState,
    346                  AsWeakPtr(),
    347                  SYNC_DATABASE_ERROR_CORRUPTION,
    348                  REMOTE_SERVICE_DISABLED));
    349 
    350   GetSyncTaskManager()->ScheduleTask(
    351       FROM_HERE,
    352       base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_IO_ERROR),
    353       SyncTaskManager::PRIORITY_MED,
    354       base::Bind(&SyncWorkerTest::CheckServiceState,
    355                  AsWeakPtr(),
    356                  SYNC_DATABASE_ERROR_IO_ERROR,
    357                  REMOTE_SERVICE_DISABLED));
    358 
    359   GetSyncTaskManager()->ScheduleTask(
    360       FROM_HERE,
    361       base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_FAILED),
    362       SyncTaskManager::PRIORITY_MED,
    363       base::Bind(&SyncWorkerTest::CheckServiceState,
    364                  AsWeakPtr(),
    365                  SYNC_DATABASE_ERROR_FAILED,
    366                  REMOTE_SERVICE_DISABLED));
    367 
    368   GetSyncTaskManager()->ScheduleSyncTask(
    369       FROM_HERE,
    370       scoped_ptr<SyncTask>(new MockSyncTask(false)),
    371       SyncTaskManager::PRIORITY_MED,
    372       base::Bind(&SyncWorkerTest::CheckServiceState,
    373                  AsWeakPtr(),
    374                  SYNC_STATUS_OK,
    375                  REMOTE_SERVICE_DISABLED));
    376 
    377   GetSyncTaskManager()->ScheduleSyncTask(
    378       FROM_HERE,
    379       scoped_ptr<SyncTask>(new MockSyncTask(true)),
    380       SyncTaskManager::PRIORITY_MED,
    381       base::Bind(&SyncWorkerTest::CheckServiceState,
    382                  AsWeakPtr(),
    383                  SYNC_STATUS_OK,
    384                  REMOTE_SERVICE_OK));
    385 
    386   base::RunLoop().RunUntilIdle();
    387 }
    388 
    389 }  // namespace drive_backend
    390 }  // namespace sync_file_system
    391