Revert 270226 "Componentize GCM Part 1: create GCM component and..."
[chromium-blink-merge.git] / chrome / browser / extensions / extension_gcm_app_handler_unittest.cc
blob8e9f3cc0f2fa11bb93bfd3cd3153d62aea52a79b
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/extensions/extension_gcm_app_handler.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h"
18 #include "base/values.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/extensions/test_extension_service.h"
21 #include "chrome/browser/extensions/test_extension_system.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/services/gcm/fake_gcm_client_factory.h"
24 #include "chrome/browser/services/gcm/fake_signin_manager.h"
25 #include "chrome/browser/services/gcm/gcm_client_factory.h"
26 #include "chrome/browser/services/gcm/gcm_client_mock.h"
27 #include "chrome/browser/services/gcm/gcm_profile_service.h"
28 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
29 #include "chrome/browser/signin/signin_manager_factory.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/test/base/testing_profile.h"
32 #include "components/keyed_service/core/keyed_service.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/test/test_browser_thread_bundle.h"
36 #include "extensions/browser/extension_system.h"
37 #include "extensions/common/extension.h"
38 #include "extensions/common/manifest.h"
39 #include "extensions/common/manifest_constants.h"
40 #include "extensions/common/permissions/api_permission.h"
41 #include "testing/gtest/include/gtest/gtest.h"
43 #if !defined(OS_ANDROID)
44 #include "chrome/browser/extensions/api/gcm/gcm_api.h"
45 #endif
47 #if defined(OS_CHROMEOS)
48 #include "chrome/browser/chromeos/login/user_manager.h"
49 #include "chrome/browser/chromeos/settings/cros_settings.h"
50 #include "chrome/browser/chromeos/settings/device_settings_service.h"
51 #endif
53 namespace extensions {
55 namespace {
57 const char kTestExtensionName[] = "FooBar";
58 const char kTestingUsername[] = "user1@example.com";
60 } // namespace
62 // Helper class for asynchronous waiting.
63 class Waiter {
64 public:
65 Waiter() {}
66 ~Waiter() {}
68 // Waits until the asynchronous operation finishes.
69 void WaitUntilCompleted() {
70 run_loop_.reset(new base::RunLoop);
71 run_loop_->Run();
74 // Signals that the asynchronous operation finishes.
75 void SignalCompleted() {
76 if (run_loop_ && run_loop_->running())
77 run_loop_->Quit();
80 // Runs until UI loop becomes idle.
81 void PumpUILoop() {
82 base::MessageLoop::current()->RunUntilIdle();
85 // Runs until IO loop becomes idle.
86 void PumpIOLoop() {
87 content::BrowserThread::PostTask(
88 content::BrowserThread::IO,
89 FROM_HERE,
90 base::Bind(&Waiter::OnIOLoopPump, base::Unretained(this)));
92 WaitUntilCompleted();
95 private:
96 void PumpIOLoopCompleted() {
97 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
99 SignalCompleted();
102 void OnIOLoopPump() {
103 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
105 content::BrowserThread::PostTask(
106 content::BrowserThread::IO,
107 FROM_HERE,
108 base::Bind(&Waiter::OnIOLoopPumpCompleted, base::Unretained(this)));
111 void OnIOLoopPumpCompleted() {
112 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
114 content::BrowserThread::PostTask(
115 content::BrowserThread::UI,
116 FROM_HERE,
117 base::Bind(&Waiter::PumpIOLoopCompleted, base::Unretained(this)));
120 scoped_ptr<base::RunLoop> run_loop_;
122 DISALLOW_COPY_AND_ASSIGN(Waiter);
125 class FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler {
126 public:
127 FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter)
128 : ExtensionGCMAppHandler(profile),
129 waiter_(waiter),
130 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) {
133 virtual ~FakeExtensionGCMAppHandler() {
136 virtual void OnMessage(
137 const std::string& app_id,
138 const gcm::GCMClient::IncomingMessage& message) OVERRIDE {
141 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE {
144 virtual void OnSendError(
145 const std::string& app_id,
146 const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE {
149 virtual void OnUnregisterCompleted(const std::string& app_id,
150 gcm::GCMClient::Result result) OVERRIDE {
151 unregistration_result_ = result;
152 waiter_->SignalCompleted();
155 gcm::GCMClient::Result unregistration_result() const {
156 return unregistration_result_;
159 private:
160 Waiter* waiter_;
161 gcm::GCMClient::Result unregistration_result_;
163 DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler);
166 class ExtensionGCMAppHandlerTest : public testing::Test {
167 public:
168 static KeyedService* BuildGCMProfileService(
169 content::BrowserContext* context) {
170 return new gcm::GCMProfileService(static_cast<Profile*>(context));
173 ExtensionGCMAppHandlerTest()
174 : extension_service_(NULL),
175 registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
176 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) {
179 virtual ~ExtensionGCMAppHandlerTest() {
182 // Overridden from test::Test:
183 virtual void SetUp() OVERRIDE {
184 // Make BrowserThread work in unittest.
185 thread_bundle_.reset(new content::TestBrowserThreadBundle(
186 content::TestBrowserThreadBundle::REAL_IO_THREAD));
188 // This is needed to create extension service under CrOS.
189 #if defined(OS_CHROMEOS)
190 test_user_manager_.reset(new chromeos::ScopedTestUserManager());
191 #endif
193 // Create a new profile.
194 TestingProfile::Builder builder;
195 builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
196 gcm::FakeSigninManager::Build);
197 profile_ = builder.Build();
198 signin_manager_ = static_cast<gcm::FakeSigninManager*>(
199 SigninManagerFactory::GetInstance()->GetForProfile(profile_.get()));
201 // Create extension service in order to uninstall the extension.
202 TestExtensionSystem* extension_system(
203 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile())));
204 extension_system->CreateExtensionService(
205 CommandLine::ForCurrentProcess(), base::FilePath(), false);
206 extension_service_ = extension_system->Get(profile())->extension_service();
208 // Enable GCM such that tests could be run on all channels.
209 profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
211 // Create GCMProfileService that talks with fake GCMClient.
212 gcm::GCMProfileService* gcm_profile_service =
213 static_cast<gcm::GCMProfileService*>(
214 gcm::GCMProfileServiceFactory::GetInstance()->
215 SetTestingFactoryAndUse(
216 profile(),
217 &ExtensionGCMAppHandlerTest::BuildGCMProfileService));
218 scoped_ptr<gcm::GCMClientFactory> gcm_client_factory(
219 new gcm::FakeGCMClientFactory(gcm::GCMClientMock::NO_DELAY_START));
220 gcm_profile_service->Initialize(gcm_client_factory.Pass());
222 // Create a fake version of ExtensionGCMAppHandler.
223 gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_));
226 virtual void TearDown() OVERRIDE {
227 #if defined(OS_CHROMEOS)
228 test_user_manager_.reset();
229 #endif
231 waiter_.PumpUILoop();
234 // Returns a barebones test extension.
235 scoped_refptr<Extension> CreateExtension() {
236 #if defined(OS_WIN)
237 base::FilePath path(FILE_PATH_LITERAL("c:\\foo"));
238 #elif defined(OS_POSIX)
239 base::FilePath path(FILE_PATH_LITERAL("/foo"));
240 #endif
242 base::DictionaryValue manifest;
243 manifest.SetString(manifest_keys::kVersion, "1.0.0.0");
244 manifest.SetString(manifest_keys::kName, kTestExtensionName);
245 base::ListValue* permission_list = new base::ListValue;
246 permission_list->Append(base::Value::CreateStringValue("gcm"));
247 manifest.Set(manifest_keys::kPermissions, permission_list);
249 std::string error;
250 scoped_refptr<Extension> extension = Extension::Create(
251 path.AppendASCII(kTestExtensionName),
252 Manifest::INVALID_LOCATION,
253 manifest,
254 Extension::NO_FLAGS,
255 &error);
256 EXPECT_TRUE(extension.get()) << error;
257 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kGcm));
259 return extension;
262 void LoadExtension(const Extension* extension) {
263 extension_service_->AddExtension(extension);
266 void DisableExtension(const Extension* extension) {
267 extension_service_->DisableExtension(
268 extension->id(), Extension::DISABLE_USER_ACTION);
271 void EnableExtension(const Extension* extension) {
272 extension_service_->EnableExtension(extension->id());
275 void UninstallExtension(const Extension* extension) {
276 extension_service_->UninstallExtension(extension->id(), false, NULL);
279 void SignIn(const std::string& username) {
280 signin_manager_->SignIn(username);
281 waiter_.PumpIOLoop();
284 void SignOut() {
285 signin_manager_->SignOut();
286 waiter_.PumpIOLoop();
289 void Register(const std::string& app_id,
290 const std::vector<std::string>& sender_ids) {
291 GetGCMProfileService()->Register(
292 app_id,
293 sender_ids,
294 base::Bind(&ExtensionGCMAppHandlerTest::RegisterCompleted,
295 base::Unretained(this)));
298 void RegisterCompleted(const std::string& registration_id,
299 gcm::GCMClient::Result result) {
300 registration_result_ = result;
301 waiter_.SignalCompleted();
304 gcm::GCMProfileService* GetGCMProfileService() const {
305 return gcm::GCMProfileServiceFactory::GetForProfile(profile());
308 bool HasAppHandlers(const std::string& app_id) const {
309 return GetGCMProfileService()->app_handlers_.count(app_id);
312 Profile* profile() const { return profile_.get(); }
313 Waiter* waiter() { return &waiter_; }
314 FakeExtensionGCMAppHandler* gcm_app_handler() const {
315 return gcm_app_handler_.get();
317 gcm::GCMClient::Result registration_result() const {
318 return registration_result_;
320 gcm::GCMClient::Result unregistration_result() const {
321 return unregistration_result_;
324 private:
325 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
326 scoped_ptr<TestingProfile> profile_;
327 ExtensionService* extension_service_; // Not owned.
328 gcm::FakeSigninManager* signin_manager_; // Not owned.
330 // This is needed to create extension service under CrOS.
331 #if defined(OS_CHROMEOS)
332 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
333 chromeos::ScopedTestCrosSettings test_cros_settings_;
334 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
335 #endif
337 Waiter waiter_;
338 scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_;
339 gcm::GCMClient::Result registration_result_;
340 gcm::GCMClient::Result unregistration_result_;
342 DISALLOW_COPY_AND_ASSIGN(ExtensionGCMAppHandlerTest);
345 TEST_F(ExtensionGCMAppHandlerTest, AddAndRemoveAppHandler) {
346 scoped_refptr<Extension> extension(CreateExtension());
348 // App handler is added when extension is loaded.
349 LoadExtension(extension);
350 waiter()->PumpUILoop();
351 EXPECT_TRUE(HasAppHandlers(extension->id()));
353 // App handler is removed when extension is unloaded.
354 DisableExtension(extension);
355 waiter()->PumpUILoop();
356 EXPECT_FALSE(HasAppHandlers(extension->id()));
358 // App handler is added when extension is reloaded.
359 EnableExtension(extension);
360 waiter()->PumpUILoop();
361 EXPECT_TRUE(HasAppHandlers(extension->id()));
363 // App handler is removed when extension is uninstalled.
364 UninstallExtension(extension);
365 waiter()->PumpUILoop();
366 EXPECT_FALSE(HasAppHandlers(extension->id()));
369 TEST_F(ExtensionGCMAppHandlerTest, UnregisterOnExtensionUninstall) {
370 scoped_refptr<Extension> extension(CreateExtension());
371 LoadExtension(extension);
373 // Sign-in is needed for registration.
374 SignIn(kTestingUsername);
376 // Kick off registration.
377 std::vector<std::string> sender_ids;
378 sender_ids.push_back("sender1");
379 Register(extension->id(), sender_ids);
380 waiter()->WaitUntilCompleted();
381 EXPECT_EQ(gcm::GCMClient::SUCCESS, registration_result());
383 // Unregistration should be triggered when the extension is uninstalled.
384 UninstallExtension(extension);
385 waiter()->WaitUntilCompleted();
386 EXPECT_EQ(gcm::GCMClient::SUCCESS,
387 gcm_app_handler()->unregistration_result());
390 } // namespace extensions