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 "chrome/browser/drive/drive_uploader.h"
     11 #include "chrome/browser/drive/fake_drive_service.h"
     12 #include "chrome/browser/extensions/test_extension_service.h"
     13 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
     14 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
     15 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
     16 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
     17 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
     18 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
     19 #include "content/public/test/test_browser_thread_bundle.h"
     20 #include "extensions/common/extension.h"
     21 #include "extensions/common/extension_builder.h"
     22 #include "extensions/common/extension_set.h"
     23 #include "extensions/common/value_builder.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
     26 #include "third_party/leveldatabase/src/include/leveldb/env.h"
     27 
     28 namespace sync_file_system {
     29 namespace drive_backend {
     30 
     31 namespace {
     32 
     33 const char kAppID[] = "app_id";
     34 
     35 void EmptyTask(SyncStatusCode status, const SyncStatusCallback& callback) {
     36   base::MessageLoop::current()->PostTask(
     37       FROM_HERE, base::Bind(callback, status));
     38 }
     39 
     40 }  // namespace
     41 
     42 class MockSyncTask : public ExclusiveTask {
     43  public:
     44   explicit MockSyncTask(bool used_network) {
     45     set_used_network(used_network);
     46   }
     47   virtual ~MockSyncTask() {}
     48 
     49   virtual void RunExclusive(const SyncStatusCallback& callback) OVERRIDE {
     50     callback.Run(SYNC_STATUS_OK);
     51   }
     52 
     53  private:
     54   DISALLOW_COPY_AND_ASSIGN(MockSyncTask);
     55 };
     56 
     57 class MockExtensionService : public TestExtensionService {
     58  public:
     59   MockExtensionService() {}
     60   virtual ~MockExtensionService() {}
     61 
     62   virtual const extensions::ExtensionSet* extensions() const OVERRIDE {
     63     return &extensions_;
     64   }
     65 
     66   virtual void AddExtension(const extensions::Extension* extension) OVERRIDE {
     67     extensions_.Insert(make_scoped_refptr(extension));
     68   }
     69 
     70   virtual const extensions::Extension* GetInstalledExtension(
     71       const std::string& extension_id) const OVERRIDE {
     72     return extensions_.GetByID(extension_id);
     73   }
     74 
     75   virtual bool IsExtensionEnabled(
     76       const std::string& extension_id) const OVERRIDE {
     77     return extensions_.Contains(extension_id) &&
     78         !disabled_extensions_.Contains(extension_id);
     79   }
     80 
     81   void UninstallExtension(const std::string& extension_id) {
     82     extensions_.Remove(extension_id);
     83     disabled_extensions_.Remove(extension_id);
     84   }
     85 
     86   void DisableExtension(const std::string& extension_id) {
     87     if (!IsExtensionEnabled(extension_id))
     88       return;
     89     const extensions::Extension* extension = extensions_.GetByID(extension_id);
     90     disabled_extensions_.Insert(make_scoped_refptr(extension));
     91   }
     92 
     93  private:
     94   extensions::ExtensionSet extensions_;
     95   extensions::ExtensionSet disabled_extensions_;
     96 
     97   DISALLOW_COPY_AND_ASSIGN(MockExtensionService);
     98 };
     99 
    100 class SyncWorkerTest : public testing::Test,
    101                        public base::SupportsWeakPtr<SyncWorkerTest> {
    102  public:
    103   SyncWorkerTest() {}
    104   virtual ~SyncWorkerTest() {}
    105 
    106   virtual void SetUp() OVERRIDE {
    107     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
    108     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
    109 
    110     extension_service_.reset(new MockExtensionService);
    111     scoped_ptr<drive::DriveServiceInterface>
    112         fake_drive_service(new drive::FakeDriveService);
    113 
    114     scoped_ptr<SyncEngineContext>
    115         sync_engine_context(new SyncEngineContext(
    116             fake_drive_service.Pass(),
    117             scoped_ptr<drive::DriveUploaderInterface>(),
    118             NULL /* task_logger */,
    119             base::MessageLoopProxy::current() /* ui_task_runner */,
    120             base::MessageLoopProxy::current() /* worker_task_runner */,
    121             base::MessageLoopProxy::current() /* file_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_->GetSyncTaskManager();
    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   void SetHasRefreshToken(bool has_refresh_token) {
    162     sync_worker_->has_refresh_token_ = has_refresh_token;
    163   }
    164 
    165  private:
    166   content::TestBrowserThreadBundle browser_threads_;
    167   base::ScopedTempDir profile_dir_;
    168   scoped_ptr<leveldb::Env> in_memory_env_;
    169 
    170   scoped_ptr<MockExtensionService> extension_service_;
    171   scoped_ptr<SyncWorker> sync_worker_;
    172 
    173   DISALLOW_COPY_AND_ASSIGN(SyncWorkerTest);
    174 };
    175 
    176 TEST_F(SyncWorkerTest, EnableOrigin) {
    177   FileTracker tracker;
    178   SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
    179   GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
    180 
    181   sync_worker()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
    182   base::RunLoop().RunUntilIdle();
    183   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    184   ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
    185   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    186 
    187   sync_worker()->DisableOrigin(origin, CreateResultReceiver(&sync_status));
    188   base::RunLoop().RunUntilIdle();
    189   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    190   ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
    191   EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
    192 
    193   sync_worker()->EnableOrigin(origin, CreateResultReceiver(&sync_status));
    194   base::RunLoop().RunUntilIdle();
    195   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    196   ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
    197   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    198 
    199   sync_worker()->UninstallOrigin(
    200       origin,
    201       RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
    202       CreateResultReceiver(&sync_status));
    203   base::RunLoop().RunUntilIdle();
    204   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    205   ASSERT_FALSE(metadata_database()->FindAppRootTracker(kAppID, &tracker));
    206 }
    207 
    208 TEST_F(SyncWorkerTest, UpdateRegisteredApps) {
    209   SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
    210   for (int i = 0; i < 3; i++) {
    211     scoped_refptr<const extensions::Extension> extension =
    212         extensions::ExtensionBuilder()
    213         .SetManifest(extensions::DictionaryBuilder()
    214                      .Set("name", "foo")
    215                      .Set("version", "1.0")
    216                      .Set("manifest_version", 2))
    217         .SetID(base::StringPrintf("app_%d", i))
    218         .Build();
    219     extension_service()->AddExtension(extension.get());
    220     GURL origin = extensions::Extension::GetBaseURLFromExtensionId(
    221         extension->id());
    222     sync_status = SYNC_STATUS_UNKNOWN;
    223     sync_worker()->RegisterOrigin(origin, CreateResultReceiver(&sync_status));
    224     base::RunLoop().RunUntilIdle();
    225     EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    226   }
    227 
    228   FileTracker tracker;
    229 
    230   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker));
    231   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    232 
    233   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker));
    234   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    235 
    236   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_2", &tracker));
    237   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    238 
    239   extension_service()->DisableExtension("app_1");
    240   extension_service()->UninstallExtension("app_2");
    241   ASSERT_FALSE(extension_service()->GetInstalledExtension("app_2"));
    242   UpdateRegisteredApps();
    243   base::RunLoop().RunUntilIdle();
    244 
    245   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_0", &tracker));
    246   EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind());
    247 
    248   ASSERT_TRUE(metadata_database()->FindAppRootTracker("app_1", &tracker));
    249   EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind());
    250 
    251   ASSERT_FALSE(metadata_database()->FindAppRootTracker("app_2", &tracker));
    252 }
    253 
    254 TEST_F(SyncWorkerTest, GetOriginStatusMap) {
    255   FileTracker tracker;
    256   SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
    257   GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
    258 
    259   sync_worker()->RegisterOrigin(GURL("chrome-extension://app_0"),
    260                                 CreateResultReceiver(&sync_status));
    261   base::RunLoop().RunUntilIdle();
    262   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    263 
    264   sync_worker()->RegisterOrigin(GURL("chrome-extension://app_1"),
    265                                 CreateResultReceiver(&sync_status));
    266   base::RunLoop().RunUntilIdle();
    267   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    268 
    269   scoped_ptr<RemoteFileSyncService::OriginStatusMap> status_map;
    270   sync_worker()->GetOriginStatusMap(CreateResultReceiver(&status_map));
    271   base::RunLoop().RunUntilIdle();
    272   ASSERT_EQ(2u, status_map->size());
    273   EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_0")]);
    274   EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_1")]);
    275 
    276   sync_worker()->DisableOrigin(GURL("chrome-extension://app_1"),
    277                                CreateResultReceiver(&sync_status));
    278   base::RunLoop().RunUntilIdle();
    279   EXPECT_EQ(SYNC_STATUS_OK, sync_status);
    280 
    281   sync_worker()->GetOriginStatusMap(CreateResultReceiver(&status_map));
    282   base::RunLoop().RunUntilIdle();
    283   ASSERT_EQ(2u, status_map->size());
    284   EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_0")]);
    285   EXPECT_EQ("Disabled", (*status_map)[GURL("chrome-extension://app_1")]);
    286 }
    287 
    288 TEST_F(SyncWorkerTest, UpdateServiceState) {
    289   EXPECT_EQ(REMOTE_SERVICE_OK, sync_worker()->GetCurrentState());
    290 
    291   // Assume an user is in login state.
    292   SetHasRefreshToken(true);
    293 
    294   GetSyncTaskManager()->ScheduleTask(
    295       FROM_HERE,
    296       base::Bind(&EmptyTask, SYNC_STATUS_AUTHENTICATION_FAILED),
    297       SyncTaskManager::PRIORITY_MED,
    298       base::Bind(&SyncWorkerTest::CheckServiceState,
    299                  AsWeakPtr(),
    300                  SYNC_STATUS_AUTHENTICATION_FAILED,
    301                  REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
    302 
    303   GetSyncTaskManager()->ScheduleTask(
    304       FROM_HERE,
    305       base::Bind(&EmptyTask, SYNC_STATUS_ACCESS_FORBIDDEN),
    306       SyncTaskManager::PRIORITY_MED,
    307       base::Bind(&SyncWorkerTest::CheckServiceState,
    308                  AsWeakPtr(),
    309                  SYNC_STATUS_ACCESS_FORBIDDEN,
    310                  REMOTE_SERVICE_AUTHENTICATION_REQUIRED));
    311 
    312   GetSyncTaskManager()->ScheduleTask(
    313       FROM_HERE,
    314       base::Bind(&EmptyTask, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE),
    315       SyncTaskManager::PRIORITY_MED,
    316       base::Bind(&SyncWorkerTest::CheckServiceState,
    317                  AsWeakPtr(),
    318                  SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE,
    319                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    320 
    321   GetSyncTaskManager()->ScheduleTask(
    322       FROM_HERE,
    323       base::Bind(&EmptyTask, SYNC_STATUS_NETWORK_ERROR),
    324       SyncTaskManager::PRIORITY_MED,
    325       base::Bind(&SyncWorkerTest::CheckServiceState,
    326                  AsWeakPtr(),
    327                  SYNC_STATUS_NETWORK_ERROR,
    328                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    329 
    330   GetSyncTaskManager()->ScheduleTask(
    331       FROM_HERE,
    332       base::Bind(&EmptyTask, SYNC_STATUS_ABORT),
    333       SyncTaskManager::PRIORITY_MED,
    334       base::Bind(&SyncWorkerTest::CheckServiceState,
    335                  AsWeakPtr(),
    336                  SYNC_STATUS_ABORT,
    337                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    338 
    339   GetSyncTaskManager()->ScheduleTask(
    340       FROM_HERE,
    341       base::Bind(&EmptyTask, SYNC_STATUS_FAILED),
    342       SyncTaskManager::PRIORITY_MED,
    343       base::Bind(&SyncWorkerTest::CheckServiceState,
    344                  AsWeakPtr(),
    345                  SYNC_STATUS_FAILED,
    346                  REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
    347 
    348   GetSyncTaskManager()->ScheduleTask(
    349       FROM_HERE,
    350       base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_CORRUPTION),
    351       SyncTaskManager::PRIORITY_MED,
    352       base::Bind(&SyncWorkerTest::CheckServiceState,
    353                  AsWeakPtr(),
    354                  SYNC_DATABASE_ERROR_CORRUPTION,
    355                  REMOTE_SERVICE_DISABLED));
    356 
    357   GetSyncTaskManager()->ScheduleTask(
    358       FROM_HERE,
    359       base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_IO_ERROR),
    360       SyncTaskManager::PRIORITY_MED,
    361       base::Bind(&SyncWorkerTest::CheckServiceState,
    362                  AsWeakPtr(),
    363                  SYNC_DATABASE_ERROR_IO_ERROR,
    364                  REMOTE_SERVICE_DISABLED));
    365 
    366   GetSyncTaskManager()->ScheduleTask(
    367       FROM_HERE,
    368       base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_FAILED),
    369       SyncTaskManager::PRIORITY_MED,
    370       base::Bind(&SyncWorkerTest::CheckServiceState,
    371                  AsWeakPtr(),
    372                  SYNC_DATABASE_ERROR_FAILED,
    373                  REMOTE_SERVICE_DISABLED));
    374 
    375   GetSyncTaskManager()->ScheduleSyncTask(
    376       FROM_HERE,
    377       scoped_ptr<SyncTask>(new MockSyncTask(false)),
    378       SyncTaskManager::PRIORITY_MED,
    379       base::Bind(&SyncWorkerTest::CheckServiceState,
    380                  AsWeakPtr(),
    381                  SYNC_STATUS_OK,
    382                  REMOTE_SERVICE_DISABLED));
    383 
    384   GetSyncTaskManager()->ScheduleSyncTask(
    385       FROM_HERE,
    386       scoped_ptr<SyncTask>(new MockSyncTask(true)),
    387       SyncTaskManager::PRIORITY_MED,
    388       base::Bind(&SyncWorkerTest::CheckServiceState,
    389                  AsWeakPtr(),
    390                  SYNC_STATUS_OK,
    391                  REMOTE_SERVICE_OK));
    392 
    393   base::RunLoop().RunUntilIdle();
    394 }
    395 
    396 }  // namespace drive_backend
    397 }  // namespace sync_file_system
    398