extension_gcm_app_handler_unittest.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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 "base/bind.h" 6#include "base/command_line.h" 7#include "base/prefs/pref_service.h" 8#include "chrome/browser/extensions/extension_gcm_app_handler.h" 9#include "chrome/browser/extensions/test_extension_service.h" 10#include "chrome/browser/extensions/test_extension_system.h" 11#include "chrome/browser/services/gcm/gcm_client_mock.h" 12#include "chrome/browser/services/gcm/gcm_profile_service.h" 13#include "chrome/browser/services/gcm/gcm_profile_service_factory.h" 14#include "chrome/browser/services/gcm/gcm_profile_service_test_helper.h" 15#include "chrome/browser/signin/signin_manager_factory.h" 16#include "chrome/common/pref_names.h" 17#include "chrome/test/base/testing_profile.h" 18#include "content/public/browser/browser_thread.h" 19#include "content/public/test/test_browser_thread_bundle.h" 20#include "extensions/common/extension.h" 21#include "extensions/common/manifest_constants.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24#if defined(OS_CHROMEOS) 25#include "chrome/browser/chromeos/login/user_manager.h" 26#include "chrome/browser/chromeos/settings/cros_settings.h" 27#include "chrome/browser/chromeos/settings/device_settings_service.h" 28#else 29#include "components/signin/core/browser/signin_manager.h" 30#endif 31 32using namespace gcm; 33 34namespace extensions { 35 36namespace { 37 38const char kTestExtensionName[] = "FooBar"; 39const char kTestingUsername[] = "user1@example.com"; 40 41} // namespace 42 43class FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler { 44 public: 45 FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter) 46 : ExtensionGCMAppHandler(profile), 47 waiter_(waiter), 48 unregistration_result_(GCMClient::UNKNOWN_ERROR) { 49 } 50 51 virtual ~FakeExtensionGCMAppHandler() { 52 } 53 54 virtual void OnMessage( 55 const std::string& app_id, 56 const GCMClient::IncomingMessage& message)OVERRIDE { 57 } 58 59 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE { 60 } 61 62 virtual void OnSendError( 63 const std::string& app_id, 64 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE { 65 } 66 67 virtual void OnUnregisterCompleted(const std::string& app_id, 68 GCMClient::Result result) OVERRIDE { 69 unregistration_result_ = result; 70 waiter_->SignalCompleted(); 71 } 72 73 GCMClient::Result unregistration_result() const { 74 return unregistration_result_; 75 } 76 77 private: 78 Waiter* waiter_; 79 GCMClient::Result unregistration_result_; 80 81 DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler); 82}; 83 84class ExtensionGCMAppHandlerTest : public testing::Test { 85 public: 86 static KeyedService* BuildGCMProfileService( 87 content::BrowserContext* context) { 88 return new GCMProfileService(static_cast<Profile*>(context)); 89 } 90 91 ExtensionGCMAppHandlerTest() 92 : extension_service_(NULL), 93 registration_result_(GCMClient::UNKNOWN_ERROR), 94 unregistration_result_(GCMClient::UNKNOWN_ERROR) { 95 } 96 97 virtual ~ExtensionGCMAppHandlerTest() { 98 } 99 100 // Overridden from test::Test: 101 virtual void SetUp() OVERRIDE { 102 // Make BrowserThread work in unittest. 103 thread_bundle_.reset(new content::TestBrowserThreadBundle( 104 content::TestBrowserThreadBundle::REAL_IO_THREAD)); 105 106 // This is needed to create extension service under CrOS. 107#if defined(OS_CHROMEOS) 108 test_user_manager_.reset(new chromeos::ScopedTestUserManager()); 109#endif 110 111 // Create a new profile. 112 TestingProfile::Builder builder; 113 builder.AddTestingFactory(SigninManagerFactory::GetInstance(), 114 gcm::FakeSigninManager::Build); 115 profile_ = builder.Build(); 116 signin_manager_ = static_cast<gcm::FakeSigninManager*>( 117 SigninManagerFactory::GetInstance()->GetForProfile(profile_.get())); 118 119 // Create extension service in order to uninstall the extension. 120 TestExtensionSystem* extension_system( 121 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))); 122 extension_system->CreateExtensionService( 123 CommandLine::ForCurrentProcess(), base::FilePath(), false); 124 extension_service_ = extension_system->Get(profile())->extension_service(); 125 126 // Enable GCM such that tests could be run on all channels. 127 profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true); 128 129 // Create GCMProfileService that talks with fake GCMClient. 130 GCMProfileService* gcm_profile_service = static_cast<GCMProfileService*>( 131 GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse( 132 profile(), 133 &ExtensionGCMAppHandlerTest::BuildGCMProfileService)); 134 scoped_ptr<GCMClientFactory> gcm_client_factory( 135 new FakeGCMClientFactory(GCMClientMock::NO_DELAY_LOADING)); 136 gcm_profile_service->Initialize(gcm_client_factory.Pass()); 137 138 // Create a fake version of ExtensionGCMAppHandler. 139 gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_)); 140 } 141 142 virtual void TearDown() OVERRIDE { 143#if defined(OS_CHROMEOS) 144 test_user_manager_.reset(); 145#endif 146 147 waiter_.PumpUILoop(); 148 } 149 150 // Returns a barebones test extension. 151 scoped_refptr<Extension> CreateExtension() { 152#if defined(OS_WIN) 153 base::FilePath path(FILE_PATH_LITERAL("c:\\foo")); 154#elif defined(OS_POSIX) 155 base::FilePath path(FILE_PATH_LITERAL("/foo")); 156#endif 157 158 base::DictionaryValue manifest; 159 manifest.SetString(manifest_keys::kVersion, "1.0.0.0"); 160 manifest.SetString(manifest_keys::kName, kTestExtensionName); 161 base::ListValue* permission_list = new base::ListValue; 162 permission_list->Append(base::Value::CreateStringValue("gcm")); 163 manifest.Set(manifest_keys::kPermissions, permission_list); 164 165 std::string error; 166 scoped_refptr<Extension> extension = Extension::Create( 167 path.AppendASCII(kTestExtensionName), 168 Manifest::INVALID_LOCATION, 169 manifest, 170 Extension::NO_FLAGS, 171 &error); 172 EXPECT_TRUE(extension.get()) << error; 173 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kGcm)); 174 175 return extension; 176 } 177 178 void LoadExtension(const Extension* extension) { 179 extension_service_->AddExtension(extension); 180 } 181 182 void DisableExtension(const Extension* extension) { 183 extension_service_->DisableExtension( 184 extension->id(), Extension::DISABLE_USER_ACTION); 185 } 186 187 void EnableExtension(const Extension* extension) { 188 extension_service_->EnableExtension(extension->id()); 189 } 190 191 void UninstallExtension(const Extension* extension) { 192 extension_service_->UninstallExtension(extension->id(), false, NULL); 193 } 194 195 void SignIn(const std::string& username) { 196 signin_manager_->SignIn(username); 197 waiter_.PumpIOLoop(); 198 } 199 200 void SignOut() { 201 signin_manager_->SignOut(); 202 waiter_.PumpIOLoop(); 203 } 204 205 void Register(const std::string& app_id, 206 const std::vector<std::string>& sender_ids) { 207 GetGCMProfileService()->Register( 208 app_id, 209 sender_ids, 210 base::Bind(&ExtensionGCMAppHandlerTest::RegisterCompleted, 211 base::Unretained(this))); 212 } 213 214 void RegisterCompleted(const std::string& registration_id, 215 GCMClient::Result result) { 216 registration_result_ = result; 217 waiter_.SignalCompleted(); 218 } 219 220 GCMProfileService* GetGCMProfileService() const { 221 return GCMProfileServiceFactory::GetForProfile(profile()); 222 } 223 224 bool HasAppHandlers(const std::string& app_id) const { 225 return GetGCMProfileService()->app_handlers_.count(app_id); 226 } 227 228 Profile* profile() const { return profile_.get(); } 229 Waiter* waiter() { return &waiter_; } 230 FakeExtensionGCMAppHandler* gcm_app_handler() const { 231 return gcm_app_handler_.get(); 232 } 233 GCMClient::Result registration_result() const { return registration_result_; } 234 GCMClient::Result unregistration_result() const { 235 return unregistration_result_; 236 } 237 238 private: 239 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; 240 scoped_ptr<TestingProfile> profile_; 241 ExtensionService* extension_service_; // Not owned. 242 gcm::FakeSigninManager* signin_manager_; // Not owned. 243 244 // This is needed to create extension service under CrOS. 245#if defined(OS_CHROMEOS) 246 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 247 chromeos::ScopedTestCrosSettings test_cros_settings_; 248 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; 249#endif 250 251 Waiter waiter_; 252 scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_; 253 GCMClient::Result registration_result_; 254 GCMClient::Result unregistration_result_; 255 256 DISALLOW_COPY_AND_ASSIGN(ExtensionGCMAppHandlerTest); 257}; 258 259TEST_F(ExtensionGCMAppHandlerTest, AddAndRemoveAppHandler) { 260 scoped_refptr<Extension> extension(CreateExtension()); 261 262 // App handler is added when extension is loaded. 263 LoadExtension(extension); 264 waiter()->PumpUILoop(); 265 EXPECT_TRUE(HasAppHandlers(extension->id())); 266 267 // App handler is removed when extension is unloaded. 268 DisableExtension(extension); 269 waiter()->PumpUILoop(); 270 EXPECT_FALSE(HasAppHandlers(extension->id())); 271 272 // App handler is added when extension is reloaded. 273 EnableExtension(extension); 274 waiter()->PumpUILoop(); 275 EXPECT_TRUE(HasAppHandlers(extension->id())); 276 277 // App handler is removed when extension is uninstalled. 278 UninstallExtension(extension); 279 waiter()->PumpUILoop(); 280 EXPECT_FALSE(HasAppHandlers(extension->id())); 281} 282 283TEST_F(ExtensionGCMAppHandlerTest, UnregisterOnExtensionUninstall) { 284 scoped_refptr<Extension> extension(CreateExtension()); 285 LoadExtension(extension); 286 287 // Sign-in is needed for registration. 288 SignIn(kTestingUsername); 289 290 // Kick off registration. 291 std::vector<std::string> sender_ids; 292 sender_ids.push_back("sender1"); 293 Register(extension->id(), sender_ids); 294 waiter()->WaitUntilCompleted(); 295 EXPECT_EQ(GCMClient::SUCCESS, registration_result()); 296 297 // Unregistration should be triggered when the extension is uninstalled. 298 UninstallExtension(extension); 299 waiter()->WaitUntilCompleted(); 300 EXPECT_EQ(GCMClient::SUCCESS, gcm_app_handler()->unregistration_result()); 301} 302 303} // namespace extensions 304