15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/apps/app_browsertest_util.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/drive/fake_drive_service.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/extensions/extension_service.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/fake_signin_manager.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_engine.h"
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "extensions/test/extension_test_message_listener.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "extensions/test/result_catcher.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "storage/browser/quota/quota_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/env.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace sync_file_system {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FakeDriveServiceFactory
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : public drive_backend::SyncEngine::DriveServiceFactory {
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  explicit FakeDriveServiceFactory(
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      drive::FakeDriveService::ChangeObserver* change_observer)
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : change_observer_(change_observer) {}
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~FakeDriveServiceFactory() {}
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual scoped_ptr<drive::DriveServiceInterface> CreateDriveService(
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      OAuth2TokenService* oauth2_token_service,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLRequestContextGetter* url_request_context_getter,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SequencedTaskRunner* blocking_task_runner) OVERRIDE {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<drive::FakeDriveService> drive_service(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new drive::FakeDriveService);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drive_service->AddChangeObserver(change_observer_);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return drive_service.PassAs<drive::DriveServiceInterface>();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
46  drive::FakeDriveService::ChangeObserver* change_observer_;
47
48  DISALLOW_COPY_AND_ASSIGN(FakeDriveServiceFactory);
49};
50
51}  // namespace
52
53class SyncFileSystemTest : public extensions::PlatformAppBrowserTest,
54                           public drive::FakeDriveService::ChangeObserver {
55 public:
56  SyncFileSystemTest()
57      : fake_drive_service_(NULL),
58        local_service_(NULL),
59        remote_service_(NULL) {
60  }
61
62  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
63    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
64    real_minimum_preserved_space_ =
65        storage::QuotaManager::kMinimumPreserveForSystem;
66    storage::QuotaManager::kMinimumPreserveForSystem = 0;
67  }
68
69  virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
70    storage::QuotaManager::kMinimumPreserveForSystem =
71        real_minimum_preserved_space_;
72    ExtensionApiTest::TearDownInProcessBrowserTestFixture();
73  }
74
75  scoped_refptr<base::SequencedTaskRunner> MakeSequencedTaskRunner() {
76    scoped_refptr<base::SequencedWorkerPool> worker_pool =
77        content::BrowserThread::GetBlockingPool();
78
79    return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
80        worker_pool->GetSequenceToken(),
81        base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
82  }
83
84  virtual void SetUpOnMainThread() OVERRIDE {
85    ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
86
87    SyncFileSystemServiceFactory* factory =
88        SyncFileSystemServiceFactory::GetInstance();
89
90    content::BrowserContext* context = browser()->profile();
91    ExtensionServiceInterface* extension_service =
92        extensions::ExtensionSystem::Get(context)->extension_service();
93
94    scoped_ptr<drive_backend::SyncEngine::DriveServiceFactory>
95        drive_service_factory(new FakeDriveServiceFactory(this));
96
97    fake_signin_manager_.reset(new FakeSigninManagerForTesting(
98        browser()->profile()));
99
100    remote_service_ = new drive_backend::SyncEngine(
101        base::ThreadTaskRunnerHandle::Get(),  // ui_task_runner
102        MakeSequencedTaskRunner(),
103        MakeSequencedTaskRunner(),
104        base_dir_.path(),
105        NULL,  // task_logger
106        NULL,  // notification_manager
107        extension_service,
108        fake_signin_manager_.get(),  // signin_manager
109        NULL,  // token_service
110        NULL,  // request_context
111        drive_service_factory.Pass(),
112        in_memory_env_.get());
113    remote_service_->SetSyncEnabled(true);
114    factory->set_mock_remote_file_service(
115        scoped_ptr<RemoteFileSyncService>(remote_service_));
116  }
117
118  // drive::FakeDriveService::ChangeObserver override.
119  virtual void OnNewChangeAvailable() OVERRIDE {
120    sync_engine()->OnNotificationReceived();
121  }
122
123  SyncFileSystemService* sync_file_system_service() {
124    return SyncFileSystemServiceFactory::GetForProfile(browser()->profile());
125  }
126
127  drive_backend::SyncEngine* sync_engine() {
128    return static_cast<drive_backend::SyncEngine*>(
129        sync_file_system_service()->remote_service_.get());
130  }
131
132  LocalFileSyncService* local_file_sync_service() {
133    return sync_file_system_service()->local_service_.get();
134  }
135
136  void SignIn() {
137    fake_signin_manager_->SetAuthenticatedUsername("tester");
138    sync_engine()->GoogleSigninSucceeded("test_account", "tester", "testing");
139  }
140
141  void SetSyncEnabled(bool enabled) {
142    sync_file_system_service()->SetSyncEnabledForTesting(enabled);
143  }
144
145  void WaitUntilIdle() {
146    base::RunLoop run_loop;
147    sync_file_system_service()->CallOnIdleForTesting(run_loop.QuitClosure());
148    run_loop.Run();
149  }
150
151 private:
152  base::ScopedTempDir base_dir_;
153  scoped_ptr<leveldb::Env> in_memory_env_;
154
155  scoped_ptr<FakeSigninManagerForTesting> fake_signin_manager_;
156
157  drive::FakeDriveService* fake_drive_service_;
158  LocalFileSyncService* local_service_;
159  drive_backend::SyncEngine* remote_service_;
160
161  int64 real_minimum_preserved_space_;
162
163  DISALLOW_COPY_AND_ASSIGN(SyncFileSystemTest);
164};
165
166IN_PROC_BROWSER_TEST_F(SyncFileSystemTest, AuthorizationTest) {
167  ExtensionTestMessageListener open_failure(
168      "checkpoint: Failed to get syncfs", true);
169  ExtensionTestMessageListener bar_created(
170      "checkpoint: \"/bar\" created", true);
171  ExtensionTestMessageListener foo_created(
172      "checkpoint: \"/foo\" created", true);
173  extensions::ResultCatcher catcher;
174
175  LoadAndLaunchPlatformApp("sync_file_system/authorization_test", "Launched");
176
177  // Application sync is disabled at the initial state.  Thus first
178  // syncFilesystem.requestFileSystem call should fail.
179  ASSERT_TRUE(open_failure.WaitUntilSatisfied());
180
181  // Enable Application sync and let the app retry.
182  SignIn();
183  SetSyncEnabled(true);
184
185  open_failure.Reply("resume");
186
187  ASSERT_TRUE(foo_created.WaitUntilSatisfied());
188
189  // The app creates a file "/foo", that should successfully sync to the remote
190  // service.  Wait for the completion and resume the app.
191  WaitUntilIdle();
192
193  sync_engine()->GoogleSignedOut("test_account", std::string());
194  foo_created.Reply("resume");
195
196  ASSERT_TRUE(bar_created.WaitUntilSatisfied());
197
198  // The app creates anohter file "/bar".  Since the user signed out from chrome
199  // The synchronization should fail and the service state should be
200  // AUTHENTICATION_REQUIRED.
201
202  WaitUntilIdle();
203  EXPECT_EQ(REMOTE_SERVICE_AUTHENTICATION_REQUIRED,
204            sync_engine()->GetCurrentState());
205
206  sync_engine()->GoogleSigninSucceeded("test_account", "tester", "testing");
207  WaitUntilIdle();
208
209  bar_created.Reply("resume");
210
211  EXPECT_TRUE(catcher.GetNextResult());
212}
213
214}  // namespace sync_file_system
215