| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_gcm_app_handler.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 5 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" |
| 6 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 7 #include "base/prefs/pref_service.h" | 12 #include "base/files/file_path.h" |
| 8 #include "chrome/browser/extensions/extension_gcm_app_handler.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" |
| 9 #include "chrome/browser/extensions/test_extension_service.h" | 20 #include "chrome/browser/extensions/test_extension_service.h" |
| 10 #include "chrome/browser/extensions/test_extension_system.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" |
| 11 #include "chrome/browser/services/gcm/gcm_client_mock.h" | 26 #include "chrome/browser/services/gcm/gcm_client_mock.h" |
| 12 #include "chrome/browser/services/gcm/gcm_profile_service.h" | 27 #include "chrome/browser/services/gcm/gcm_profile_service.h" |
| 13 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" | 28 #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" | 29 #include "chrome/browser/signin/signin_manager_factory.h" |
| 16 #include "chrome/common/pref_names.h" | 30 #include "chrome/common/pref_names.h" |
| 17 #include "chrome/test/base/testing_profile.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" |
| 18 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
| 19 #include "content/public/test/test_browser_thread_bundle.h" | 35 #include "content/public/test/test_browser_thread_bundle.h" |
| 36 #include "extensions/browser/extension_system.h" |
| 20 #include "extensions/common/extension.h" | 37 #include "extensions/common/extension.h" |
| 38 #include "extensions/common/manifest.h" |
| 21 #include "extensions/common/manifest_constants.h" | 39 #include "extensions/common/manifest_constants.h" |
| 40 #include "extensions/common/permissions/api_permission.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 41 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 42 |
| 43 #if !defined(OS_ANDROID) |
| 44 #include "chrome/browser/extensions/api/gcm/gcm_api.h" |
| 45 #endif |
| 46 |
| 24 #if defined(OS_CHROMEOS) | 47 #if defined(OS_CHROMEOS) |
| 25 #include "chrome/browser/chromeos/login/user_manager.h" | 48 #include "chrome/browser/chromeos/login/user_manager.h" |
| 26 #include "chrome/browser/chromeos/settings/cros_settings.h" | 49 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 27 #include "chrome/browser/chromeos/settings/device_settings_service.h" | 50 #include "chrome/browser/chromeos/settings/device_settings_service.h" |
| 28 #else | |
| 29 #include "components/signin/core/browser/signin_manager.h" | |
| 30 #endif | 51 #endif |
| 31 | 52 |
| 32 using namespace gcm; | |
| 33 | |
| 34 namespace extensions { | 53 namespace extensions { |
| 35 | 54 |
| 36 namespace { | 55 namespace { |
| 37 | 56 |
| 38 const char kTestExtensionName[] = "FooBar"; | 57 const char kTestExtensionName[] = "FooBar"; |
| 39 const char kTestingUsername[] = "user1@example.com"; | 58 const char kTestingUsername[] = "user1@example.com"; |
| 40 | 59 |
| 41 } // namespace | 60 } // namespace |
| 42 | 61 |
| 62 // Helper class for asynchronous waiting. |
| 63 class Waiter { |
| 64 public: |
| 65 Waiter() {} |
| 66 ~Waiter() {} |
| 67 |
| 68 // Waits until the asynchronous operation finishes. |
| 69 void WaitUntilCompleted() { |
| 70 run_loop_.reset(new base::RunLoop); |
| 71 run_loop_->Run(); |
| 72 } |
| 73 |
| 74 // Signals that the asynchronous operation finishes. |
| 75 void SignalCompleted() { |
| 76 if (run_loop_ && run_loop_->running()) |
| 77 run_loop_->Quit(); |
| 78 } |
| 79 |
| 80 // Runs until UI loop becomes idle. |
| 81 void PumpUILoop() { |
| 82 base::MessageLoop::current()->RunUntilIdle(); |
| 83 } |
| 84 |
| 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))); |
| 91 |
| 92 WaitUntilCompleted(); |
| 93 } |
| 94 |
| 95 private: |
| 96 void PumpIOLoopCompleted() { |
| 97 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 98 |
| 99 SignalCompleted(); |
| 100 } |
| 101 |
| 102 void OnIOLoopPump() { |
| 103 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 104 |
| 105 content::BrowserThread::PostTask( |
| 106 content::BrowserThread::IO, |
| 107 FROM_HERE, |
| 108 base::Bind(&Waiter::OnIOLoopPumpCompleted, base::Unretained(this))); |
| 109 } |
| 110 |
| 111 void OnIOLoopPumpCompleted() { |
| 112 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 113 |
| 114 content::BrowserThread::PostTask( |
| 115 content::BrowserThread::UI, |
| 116 FROM_HERE, |
| 117 base::Bind(&Waiter::PumpIOLoopCompleted, base::Unretained(this))); |
| 118 } |
| 119 |
| 120 scoped_ptr<base::RunLoop> run_loop_; |
| 121 |
| 122 DISALLOW_COPY_AND_ASSIGN(Waiter); |
| 123 }; |
| 124 |
| 43 class FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler { | 125 class FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler { |
| 44 public: | 126 public: |
| 45 FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter) | 127 FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter) |
| 46 : ExtensionGCMAppHandler(profile), | 128 : ExtensionGCMAppHandler(profile), |
| 47 waiter_(waiter), | 129 waiter_(waiter), |
| 48 unregistration_result_(GCMClient::UNKNOWN_ERROR) { | 130 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) { |
| 49 } | 131 } |
| 50 | 132 |
| 51 virtual ~FakeExtensionGCMAppHandler() { | 133 virtual ~FakeExtensionGCMAppHandler() { |
| 52 } | 134 } |
| 53 | 135 |
| 54 virtual void OnMessage( | 136 virtual void OnMessage( |
| 55 const std::string& app_id, | 137 const std::string& app_id, |
| 56 const GCMClient::IncomingMessage& message)OVERRIDE { | 138 const gcm::GCMClient::IncomingMessage& message) OVERRIDE { |
| 57 } | 139 } |
| 58 | 140 |
| 59 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE { | 141 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE { |
| 60 } | 142 } |
| 61 | 143 |
| 62 virtual void OnSendError( | 144 virtual void OnSendError( |
| 63 const std::string& app_id, | 145 const std::string& app_id, |
| 64 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE { | 146 const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE { |
| 65 } | 147 } |
| 66 | 148 |
| 67 virtual void OnUnregisterCompleted(const std::string& app_id, | 149 virtual void OnUnregisterCompleted(const std::string& app_id, |
| 68 GCMClient::Result result) OVERRIDE { | 150 gcm::GCMClient::Result result) OVERRIDE { |
| 69 unregistration_result_ = result; | 151 unregistration_result_ = result; |
| 70 waiter_->SignalCompleted(); | 152 waiter_->SignalCompleted(); |
| 71 } | 153 } |
| 72 | 154 |
| 73 GCMClient::Result unregistration_result() const { | 155 gcm::GCMClient::Result unregistration_result() const { |
| 74 return unregistration_result_; | 156 return unregistration_result_; |
| 75 } | 157 } |
| 76 | 158 |
| 77 private: | 159 private: |
| 78 Waiter* waiter_; | 160 Waiter* waiter_; |
| 79 GCMClient::Result unregistration_result_; | 161 gcm::GCMClient::Result unregistration_result_; |
| 80 | 162 |
| 81 DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler); | 163 DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler); |
| 82 }; | 164 }; |
| 83 | 165 |
| 84 class ExtensionGCMAppHandlerTest : public testing::Test { | 166 class ExtensionGCMAppHandlerTest : public testing::Test { |
| 85 public: | 167 public: |
| 86 static KeyedService* BuildGCMProfileService( | 168 static KeyedService* BuildGCMProfileService( |
| 87 content::BrowserContext* context) { | 169 content::BrowserContext* context) { |
| 88 return new GCMProfileService(static_cast<Profile*>(context)); | 170 return new gcm::GCMProfileService(static_cast<Profile*>(context)); |
| 89 } | 171 } |
| 90 | 172 |
| 91 ExtensionGCMAppHandlerTest() | 173 ExtensionGCMAppHandlerTest() |
| 92 : extension_service_(NULL), | 174 : extension_service_(NULL), |
| 93 registration_result_(GCMClient::UNKNOWN_ERROR), | 175 registration_result_(gcm::GCMClient::UNKNOWN_ERROR), |
| 94 unregistration_result_(GCMClient::UNKNOWN_ERROR) { | 176 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) { |
| 95 } | 177 } |
| 96 | 178 |
| 97 virtual ~ExtensionGCMAppHandlerTest() { | 179 virtual ~ExtensionGCMAppHandlerTest() { |
| 98 } | 180 } |
| 99 | 181 |
| 100 // Overridden from test::Test: | 182 // Overridden from test::Test: |
| 101 virtual void SetUp() OVERRIDE { | 183 virtual void SetUp() OVERRIDE { |
| 102 // Make BrowserThread work in unittest. | 184 // Make BrowserThread work in unittest. |
| 103 thread_bundle_.reset(new content::TestBrowserThreadBundle( | 185 thread_bundle_.reset(new content::TestBrowserThreadBundle( |
| 104 content::TestBrowserThreadBundle::REAL_IO_THREAD)); | 186 content::TestBrowserThreadBundle::REAL_IO_THREAD)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 120 TestExtensionSystem* extension_system( | 202 TestExtensionSystem* extension_system( |
| 121 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))); | 203 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))); |
| 122 extension_system->CreateExtensionService( | 204 extension_system->CreateExtensionService( |
| 123 CommandLine::ForCurrentProcess(), base::FilePath(), false); | 205 CommandLine::ForCurrentProcess(), base::FilePath(), false); |
| 124 extension_service_ = extension_system->Get(profile())->extension_service(); | 206 extension_service_ = extension_system->Get(profile())->extension_service(); |
| 125 | 207 |
| 126 // Enable GCM such that tests could be run on all channels. | 208 // Enable GCM such that tests could be run on all channels. |
| 127 profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true); | 209 profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true); |
| 128 | 210 |
| 129 // Create GCMProfileService that talks with fake GCMClient. | 211 // Create GCMProfileService that talks with fake GCMClient. |
| 130 GCMProfileService* gcm_profile_service = static_cast<GCMProfileService*>( | 212 gcm::GCMProfileService* gcm_profile_service = |
| 131 GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse( | 213 static_cast<gcm::GCMProfileService*>( |
| 132 profile(), | 214 gcm::GCMProfileServiceFactory::GetInstance()-> |
| 133 &ExtensionGCMAppHandlerTest::BuildGCMProfileService)); | 215 SetTestingFactoryAndUse( |
| 134 scoped_ptr<GCMClientFactory> gcm_client_factory( | 216 profile(), |
| 135 new FakeGCMClientFactory(GCMClientMock::NO_DELAY_LOADING)); | 217 &ExtensionGCMAppHandlerTest::BuildGCMProfileService)); |
| 218 scoped_ptr<gcm::GCMClientFactory> gcm_client_factory( |
| 219 new gcm::FakeGCMClientFactory(gcm::GCMClientMock::NO_DELAY_LOADING)); |
| 136 gcm_profile_service->Initialize(gcm_client_factory.Pass()); | 220 gcm_profile_service->Initialize(gcm_client_factory.Pass()); |
| 137 | 221 |
| 138 // Create a fake version of ExtensionGCMAppHandler. | 222 // Create a fake version of ExtensionGCMAppHandler. |
| 139 gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_)); | 223 gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_)); |
| 140 } | 224 } |
| 141 | 225 |
| 142 virtual void TearDown() OVERRIDE { | 226 virtual void TearDown() OVERRIDE { |
| 143 #if defined(OS_CHROMEOS) | 227 #if defined(OS_CHROMEOS) |
| 144 test_user_manager_.reset(); | 228 test_user_manager_.reset(); |
| 145 #endif | 229 #endif |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 void Register(const std::string& app_id, | 289 void Register(const std::string& app_id, |
| 206 const std::vector<std::string>& sender_ids) { | 290 const std::vector<std::string>& sender_ids) { |
| 207 GetGCMProfileService()->Register( | 291 GetGCMProfileService()->Register( |
| 208 app_id, | 292 app_id, |
| 209 sender_ids, | 293 sender_ids, |
| 210 base::Bind(&ExtensionGCMAppHandlerTest::RegisterCompleted, | 294 base::Bind(&ExtensionGCMAppHandlerTest::RegisterCompleted, |
| 211 base::Unretained(this))); | 295 base::Unretained(this))); |
| 212 } | 296 } |
| 213 | 297 |
| 214 void RegisterCompleted(const std::string& registration_id, | 298 void RegisterCompleted(const std::string& registration_id, |
| 215 GCMClient::Result result) { | 299 gcm::GCMClient::Result result) { |
| 216 registration_result_ = result; | 300 registration_result_ = result; |
| 217 waiter_.SignalCompleted(); | 301 waiter_.SignalCompleted(); |
| 218 } | 302 } |
| 219 | 303 |
| 220 GCMProfileService* GetGCMProfileService() const { | 304 gcm::GCMProfileService* GetGCMProfileService() const { |
| 221 return GCMProfileServiceFactory::GetForProfile(profile()); | 305 return gcm::GCMProfileServiceFactory::GetForProfile(profile()); |
| 222 } | 306 } |
| 223 | 307 |
| 224 bool HasAppHandlers(const std::string& app_id) const { | 308 bool HasAppHandlers(const std::string& app_id) const { |
| 225 return GetGCMProfileService()->app_handlers_.count(app_id); | 309 return GetGCMProfileService()->app_handlers_.count(app_id); |
| 226 } | 310 } |
| 227 | 311 |
| 228 Profile* profile() const { return profile_.get(); } | 312 Profile* profile() const { return profile_.get(); } |
| 229 Waiter* waiter() { return &waiter_; } | 313 Waiter* waiter() { return &waiter_; } |
| 230 FakeExtensionGCMAppHandler* gcm_app_handler() const { | 314 FakeExtensionGCMAppHandler* gcm_app_handler() const { |
| 231 return gcm_app_handler_.get(); | 315 return gcm_app_handler_.get(); |
| 232 } | 316 } |
| 233 GCMClient::Result registration_result() const { return registration_result_; } | 317 gcm::GCMClient::Result registration_result() const { |
| 234 GCMClient::Result unregistration_result() const { | 318 return registration_result_; |
| 319 } |
| 320 gcm::GCMClient::Result unregistration_result() const { |
| 235 return unregistration_result_; | 321 return unregistration_result_; |
| 236 } | 322 } |
| 237 | 323 |
| 238 private: | 324 private: |
| 239 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; | 325 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; |
| 240 scoped_ptr<TestingProfile> profile_; | 326 scoped_ptr<TestingProfile> profile_; |
| 241 ExtensionService* extension_service_; // Not owned. | 327 ExtensionService* extension_service_; // Not owned. |
| 242 gcm::FakeSigninManager* signin_manager_; // Not owned. | 328 gcm::FakeSigninManager* signin_manager_; // Not owned. |
| 243 | 329 |
| 244 // This is needed to create extension service under CrOS. | 330 // This is needed to create extension service under CrOS. |
| 245 #if defined(OS_CHROMEOS) | 331 #if defined(OS_CHROMEOS) |
| 246 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; | 332 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; |
| 247 chromeos::ScopedTestCrosSettings test_cros_settings_; | 333 chromeos::ScopedTestCrosSettings test_cros_settings_; |
| 248 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; | 334 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; |
| 249 #endif | 335 #endif |
| 250 | 336 |
| 251 Waiter waiter_; | 337 Waiter waiter_; |
| 252 scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_; | 338 scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_; |
| 253 GCMClient::Result registration_result_; | 339 gcm::GCMClient::Result registration_result_; |
| 254 GCMClient::Result unregistration_result_; | 340 gcm::GCMClient::Result unregistration_result_; |
| 255 | 341 |
| 256 DISALLOW_COPY_AND_ASSIGN(ExtensionGCMAppHandlerTest); | 342 DISALLOW_COPY_AND_ASSIGN(ExtensionGCMAppHandlerTest); |
| 257 }; | 343 }; |
| 258 | 344 |
| 259 TEST_F(ExtensionGCMAppHandlerTest, AddAndRemoveAppHandler) { | 345 TEST_F(ExtensionGCMAppHandlerTest, AddAndRemoveAppHandler) { |
| 260 scoped_refptr<Extension> extension(CreateExtension()); | 346 scoped_refptr<Extension> extension(CreateExtension()); |
| 261 | 347 |
| 262 // App handler is added when extension is loaded. | 348 // App handler is added when extension is loaded. |
| 263 LoadExtension(extension); | 349 LoadExtension(extension); |
| 264 waiter()->PumpUILoop(); | 350 waiter()->PumpUILoop(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 285 LoadExtension(extension); | 371 LoadExtension(extension); |
| 286 | 372 |
| 287 // Sign-in is needed for registration. | 373 // Sign-in is needed for registration. |
| 288 SignIn(kTestingUsername); | 374 SignIn(kTestingUsername); |
| 289 | 375 |
| 290 // Kick off registration. | 376 // Kick off registration. |
| 291 std::vector<std::string> sender_ids; | 377 std::vector<std::string> sender_ids; |
| 292 sender_ids.push_back("sender1"); | 378 sender_ids.push_back("sender1"); |
| 293 Register(extension->id(), sender_ids); | 379 Register(extension->id(), sender_ids); |
| 294 waiter()->WaitUntilCompleted(); | 380 waiter()->WaitUntilCompleted(); |
| 295 EXPECT_EQ(GCMClient::SUCCESS, registration_result()); | 381 EXPECT_EQ(gcm::GCMClient::SUCCESS, registration_result()); |
| 296 | 382 |
| 297 // Unregistration should be triggered when the extension is uninstalled. | 383 // Unregistration should be triggered when the extension is uninstalled. |
| 298 UninstallExtension(extension); | 384 UninstallExtension(extension); |
| 299 waiter()->WaitUntilCompleted(); | 385 waiter()->WaitUntilCompleted(); |
| 300 EXPECT_EQ(GCMClient::SUCCESS, gcm_app_handler()->unregistration_result()); | 386 EXPECT_EQ(gcm::GCMClient::SUCCESS, |
| 387 gcm_app_handler()->unregistration_result()); |
| 301 } | 388 } |
| 302 | 389 |
| 303 } // namespace extensions | 390 } // namespace extensions |
| OLD | NEW |