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" | 5 #include "chrome/browser/extensions/extension_gcm_app_handler.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/file_util.h" |
12 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
| 14 #include "base/files/scoped_temp_dir.h" |
13 #include "base/location.h" | 15 #include "base/location.h" |
14 #include "base/logging.h" | 16 #include "base/logging.h" |
15 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
16 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
| 19 #include "base/path_service.h" |
17 #include "base/prefs/pref_service.h" | 20 #include "base/prefs/pref_service.h" |
18 #include "base/run_loop.h" | 21 #include "base/run_loop.h" |
19 #include "base/values.h" | 22 #include "base/values.h" |
| 23 #include "chrome/browser/chrome_notification_types.h" |
20 #include "chrome/browser/extensions/extension_service.h" | 24 #include "chrome/browser/extensions/extension_service.h" |
21 #include "chrome/browser/extensions/test_extension_service.h" | 25 #include "chrome/browser/extensions/test_extension_service.h" |
22 #include "chrome/browser/extensions/test_extension_system.h" | 26 #include "chrome/browser/extensions/test_extension_system.h" |
23 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
24 #include "chrome/browser/services/gcm/fake_signin_manager.h" | 28 #include "chrome/browser/services/gcm/fake_signin_manager.h" |
25 #include "chrome/browser/services/gcm/gcm_profile_service.h" | 29 #include "chrome/browser/services/gcm/gcm_profile_service.h" |
26 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" | 30 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" |
27 #include "chrome/browser/signin/signin_manager_factory.h" | 31 #include "chrome/browser/signin/signin_manager_factory.h" |
| 32 #include "chrome/common/chrome_paths.h" |
28 #include "chrome/common/pref_names.h" | 33 #include "chrome/common/pref_names.h" |
29 #include "chrome/test/base/testing_profile.h" | 34 #include "chrome/test/base/testing_profile.h" |
30 #include "components/gcm_driver/fake_gcm_app_handler.h" | 35 #include "components/gcm_driver/fake_gcm_app_handler.h" |
31 #include "components/gcm_driver/fake_gcm_client.h" | 36 #include "components/gcm_driver/fake_gcm_client.h" |
32 #include "components/gcm_driver/fake_gcm_client_factory.h" | 37 #include "components/gcm_driver/fake_gcm_client_factory.h" |
33 #include "components/gcm_driver/gcm_client_factory.h" | 38 #include "components/gcm_driver/gcm_client_factory.h" |
34 #include "components/gcm_driver/gcm_driver.h" | 39 #include "components/gcm_driver/gcm_driver.h" |
35 #include "components/keyed_service/core/keyed_service.h" | 40 #include "components/keyed_service/core/keyed_service.h" |
36 #include "content/public/browser/browser_context.h" | 41 #include "content/public/browser/browser_context.h" |
37 #include "content/public/browser/browser_thread.h" | 42 #include "content/public/browser/browser_thread.h" |
38 #include "content/public/test/test_browser_thread_bundle.h" | 43 #include "content/public/test/test_browser_thread_bundle.h" |
| 44 #include "content/public/test/test_utils.h" |
39 #include "extensions/browser/extension_system.h" | 45 #include "extensions/browser/extension_system.h" |
40 #include "extensions/common/extension.h" | 46 #include "extensions/common/extension.h" |
41 #include "extensions/common/manifest.h" | 47 #include "extensions/common/manifest.h" |
42 #include "extensions/common/manifest_constants.h" | 48 #include "extensions/common/manifest_constants.h" |
43 #include "extensions/common/permissions/api_permission.h" | 49 #include "extensions/common/permissions/api_permission.h" |
44 #include "extensions/common/permissions/permissions_data.h" | 50 #include "extensions/common/permissions/permissions_data.h" |
45 #include "testing/gtest/include/gtest/gtest.h" | 51 #include "testing/gtest/include/gtest/gtest.h" |
46 | 52 |
47 #if !defined(OS_ANDROID) | 53 #if !defined(OS_ANDROID) |
48 #include "chrome/browser/extensions/api/gcm/gcm_api.h" | 54 #include "chrome/browser/extensions/api/gcm/gcm_api.h" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 scoped_ptr<base::RunLoop> run_loop_; | 130 scoped_ptr<base::RunLoop> run_loop_; |
125 | 131 |
126 DISALLOW_COPY_AND_ASSIGN(Waiter); | 132 DISALLOW_COPY_AND_ASSIGN(Waiter); |
127 }; | 133 }; |
128 | 134 |
129 class FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler { | 135 class FakeExtensionGCMAppHandler : public ExtensionGCMAppHandler { |
130 public: | 136 public: |
131 FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter) | 137 FakeExtensionGCMAppHandler(Profile* profile, Waiter* waiter) |
132 : ExtensionGCMAppHandler(profile), | 138 : ExtensionGCMAppHandler(profile), |
133 waiter_(waiter), | 139 waiter_(waiter), |
134 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) { | 140 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR), |
| 141 app_handler_count_drop_to_zero_(false) { |
135 } | 142 } |
136 | 143 |
137 virtual ~FakeExtensionGCMAppHandler() { | 144 virtual ~FakeExtensionGCMAppHandler() { |
138 } | 145 } |
139 | 146 |
140 virtual void OnMessage( | 147 virtual void OnMessage( |
141 const std::string& app_id, | 148 const std::string& app_id, |
142 const gcm::GCMClient::IncomingMessage& message) OVERRIDE { | 149 const gcm::GCMClient::IncomingMessage& message) OVERRIDE { |
143 } | 150 } |
144 | 151 |
145 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE { | 152 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE { |
146 } | 153 } |
147 | 154 |
148 virtual void OnSendError( | 155 virtual void OnSendError( |
149 const std::string& app_id, | 156 const std::string& app_id, |
150 const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE { | 157 const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE { |
151 } | 158 } |
152 | 159 |
153 virtual void OnUnregisterCompleted(const std::string& app_id, | 160 virtual void OnUnregisterCompleted(const std::string& app_id, |
154 gcm::GCMClient::Result result) OVERRIDE { | 161 gcm::GCMClient::Result result) OVERRIDE { |
155 unregistration_result_ = result; | 162 unregistration_result_ = result; |
156 waiter_->SignalCompleted(); | 163 waiter_->SignalCompleted(); |
157 } | 164 } |
158 | 165 |
| 166 virtual void RemoveAppHandler(const std::string& app_id) OVERRIDE{ |
| 167 ExtensionGCMAppHandler::RemoveAppHandler(app_id); |
| 168 if (!GetGCMDriver()->app_handlers().size()) |
| 169 app_handler_count_drop_to_zero_ = true; |
| 170 } |
| 171 |
159 gcm::GCMClient::Result unregistration_result() const { | 172 gcm::GCMClient::Result unregistration_result() const { |
160 return unregistration_result_; | 173 return unregistration_result_; |
161 } | 174 } |
| 175 bool app_handler_count_drop_to_zero() const { |
| 176 return app_handler_count_drop_to_zero_; |
| 177 } |
162 | 178 |
163 private: | 179 private: |
164 Waiter* waiter_; | 180 Waiter* waiter_; |
165 gcm::GCMClient::Result unregistration_result_; | 181 gcm::GCMClient::Result unregistration_result_; |
| 182 bool app_handler_count_drop_to_zero_; |
166 | 183 |
167 DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler); | 184 DISALLOW_COPY_AND_ASSIGN(FakeExtensionGCMAppHandler); |
168 }; | 185 }; |
169 | 186 |
170 class ExtensionGCMAppHandlerTest : public testing::Test { | 187 class ExtensionGCMAppHandlerTest : public testing::Test { |
171 public: | 188 public: |
172 static KeyedService* BuildGCMProfileService( | 189 static KeyedService* BuildGCMProfileService( |
173 content::BrowserContext* context) { | 190 content::BrowserContext* context) { |
174 return new gcm::GCMProfileService( | 191 return new gcm::GCMProfileService( |
175 Profile::FromBrowserContext(context), | 192 Profile::FromBrowserContext(context), |
176 scoped_ptr<gcm::GCMClientFactory>(new gcm::FakeGCMClientFactory( | 193 scoped_ptr<gcm::GCMClientFactory>(new gcm::FakeGCMClientFactory( |
177 gcm::FakeGCMClient::NO_DELAY_START, | 194 gcm::FakeGCMClient::NO_DELAY_START, |
178 content::BrowserThread::GetMessageLoopProxyForThread( | 195 content::BrowserThread::GetMessageLoopProxyForThread( |
179 content::BrowserThread::UI), | 196 content::BrowserThread::UI), |
180 content::BrowserThread::GetMessageLoopProxyForThread( | 197 content::BrowserThread::GetMessageLoopProxyForThread( |
181 content::BrowserThread::IO)))); | 198 content::BrowserThread::IO)))); |
182 } | 199 } |
183 | 200 |
184 ExtensionGCMAppHandlerTest() | 201 ExtensionGCMAppHandlerTest() |
185 : extension_service_(NULL), | 202 : extension_service_(NULL), |
186 registration_result_(gcm::GCMClient::UNKNOWN_ERROR), | 203 registration_result_(gcm::GCMClient::UNKNOWN_ERROR), |
187 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) { | 204 unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) { |
188 } | 205 } |
189 | 206 |
190 virtual ~ExtensionGCMAppHandlerTest() { | 207 virtual ~ExtensionGCMAppHandlerTest() { |
191 } | 208 } |
192 | 209 |
193 // Overridden from test::Test: | 210 // Overridden from test::Test: |
194 virtual void SetUp() OVERRIDE { | 211 virtual void SetUp() OVERRIDE { |
| 212 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 213 |
195 // Make BrowserThread work in unittest. | 214 // Make BrowserThread work in unittest. |
196 thread_bundle_.reset(new content::TestBrowserThreadBundle( | 215 thread_bundle_.reset(new content::TestBrowserThreadBundle( |
197 content::TestBrowserThreadBundle::REAL_IO_THREAD)); | 216 content::TestBrowserThreadBundle::REAL_IO_THREAD)); |
198 | 217 |
| 218 // Allow extension update to unpack crx in process. |
| 219 in_process_utility_thread_helper_.reset( |
| 220 new content::InProcessUtilityThreadHelper); |
| 221 |
199 // This is needed to create extension service under CrOS. | 222 // This is needed to create extension service under CrOS. |
200 #if defined(OS_CHROMEOS) | 223 #if defined(OS_CHROMEOS) |
201 test_user_manager_.reset(new chromeos::ScopedTestUserManager()); | 224 test_user_manager_.reset(new chromeos::ScopedTestUserManager()); |
202 #endif | 225 #endif |
203 | 226 |
204 // Create a new profile. | 227 // Create a new profile. |
205 TestingProfile::Builder builder; | 228 TestingProfile::Builder builder; |
206 builder.AddTestingFactory(SigninManagerFactory::GetInstance(), | 229 builder.AddTestingFactory(SigninManagerFactory::GetInstance(), |
207 gcm::FakeSigninManager::Build); | 230 gcm::FakeSigninManager::Build); |
208 profile_ = builder.Build(); | 231 profile_ = builder.Build(); |
209 signin_manager_ = static_cast<gcm::FakeSigninManager*>( | 232 signin_manager_ = static_cast<gcm::FakeSigninManager*>( |
210 SigninManagerFactory::GetInstance()->GetForProfile(profile_.get())); | 233 SigninManagerFactory::GetInstance()->GetForProfile(profile_.get())); |
211 | 234 |
212 // Create extension service in order to uninstall the extension. | 235 // Create extension service in order to uninstall the extension. |
213 TestExtensionSystem* extension_system( | 236 TestExtensionSystem* extension_system( |
214 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))); | 237 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))); |
| 238 base::FilePath extensions_install_dir = |
| 239 temp_dir_.path().Append(FILE_PATH_LITERAL("Extensions")); |
215 extension_system->CreateExtensionService( | 240 extension_system->CreateExtensionService( |
216 CommandLine::ForCurrentProcess(), base::FilePath(), false); | 241 CommandLine::ForCurrentProcess(), extensions_install_dir, false); |
217 extension_service_ = extension_system->Get(profile())->extension_service(); | 242 extension_service_ = extension_system->Get(profile())->extension_service(); |
| 243 extension_service_->set_extensions_enabled(true); |
| 244 extension_service_->set_show_extensions_prompts(false); |
| 245 extension_service_->set_install_updates_when_idle_for_test(false); |
218 | 246 |
219 // Enable GCM such that tests could be run on all channels. | 247 // Enable GCM such that tests could be run on all channels. |
220 profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true); | 248 profile()->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true); |
221 | 249 |
222 // Create GCMProfileService that talks with fake GCMClient. | 250 // Create GCMProfileService that talks with fake GCMClient. |
223 gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse( | 251 gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse( |
224 profile(), &ExtensionGCMAppHandlerTest::BuildGCMProfileService); | 252 profile(), &ExtensionGCMAppHandlerTest::BuildGCMProfileService); |
225 | 253 |
226 // Create a fake version of ExtensionGCMAppHandler. | 254 // Create a fake version of ExtensionGCMAppHandler. |
227 gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_)); | 255 gcm_app_handler_.reset(new FakeExtensionGCMAppHandler(profile(), &waiter_)); |
228 } | 256 } |
229 | 257 |
230 virtual void TearDown() OVERRIDE { | 258 virtual void TearDown() OVERRIDE { |
231 #if defined(OS_CHROMEOS) | 259 #if defined(OS_CHROMEOS) |
232 test_user_manager_.reset(); | 260 test_user_manager_.reset(); |
233 #endif | 261 #endif |
234 | 262 |
235 waiter_.PumpUILoop(); | 263 waiter_.PumpUILoop(); |
236 } | 264 } |
237 | 265 |
238 // Returns a barebones test extension. | 266 // Returns a barebones test extension. |
239 scoped_refptr<Extension> CreateExtension() { | 267 scoped_refptr<Extension> CreateExtension() { |
240 #if defined(OS_WIN) | |
241 base::FilePath path(FILE_PATH_LITERAL("c:\\foo")); | |
242 #elif defined(OS_POSIX) | |
243 base::FilePath path(FILE_PATH_LITERAL("/foo")); | |
244 #endif | |
245 | |
246 base::DictionaryValue manifest; | 268 base::DictionaryValue manifest; |
247 manifest.SetString(manifest_keys::kVersion, "1.0.0.0"); | 269 manifest.SetString(manifest_keys::kVersion, "1.0.0.0"); |
248 manifest.SetString(manifest_keys::kName, kTestExtensionName); | 270 manifest.SetString(manifest_keys::kName, kTestExtensionName); |
249 base::ListValue* permission_list = new base::ListValue; | 271 base::ListValue* permission_list = new base::ListValue; |
250 permission_list->Append(base::Value::CreateStringValue("gcm")); | 272 permission_list->Append(base::Value::CreateStringValue("gcm")); |
251 manifest.Set(manifest_keys::kPermissions, permission_list); | 273 manifest.Set(manifest_keys::kPermissions, permission_list); |
252 | 274 |
253 std::string error; | 275 std::string error; |
254 scoped_refptr<Extension> extension = Extension::Create( | 276 scoped_refptr<Extension> extension = Extension::Create( |
255 path.AppendASCII(kTestExtensionName), | 277 temp_dir_.path(), |
256 Manifest::INVALID_LOCATION, | 278 Manifest::UNPACKED, |
257 manifest, | 279 manifest, |
258 Extension::NO_FLAGS, | 280 Extension::NO_FLAGS, |
| 281 "ldnnhddmnhbkjipkidpdiheffobcpfmf", |
259 &error); | 282 &error); |
260 EXPECT_TRUE(extension.get()) << error; | 283 EXPECT_TRUE(extension.get()) << error; |
261 EXPECT_TRUE( | 284 EXPECT_TRUE( |
262 extension->permissions_data()->HasAPIPermission(APIPermission::kGcm)); | 285 extension->permissions_data()->HasAPIPermission(APIPermission::kGcm)); |
263 | 286 |
264 return extension; | 287 return extension; |
265 } | 288 } |
266 | 289 |
267 void LoadExtension(const Extension* extension) { | 290 void LoadExtension(const Extension* extension) { |
268 extension_service_->AddExtension(extension); | 291 extension_service_->AddExtension(extension); |
269 } | 292 } |
270 | 293 |
| 294 static bool IsCrxInstallerDone(extensions::CrxInstaller** installer, |
| 295 const content::NotificationSource& source, |
| 296 const content::NotificationDetails& details) { |
| 297 return content::Source<extensions::CrxInstaller>(source).ptr() == |
| 298 *installer; |
| 299 } |
| 300 |
| 301 void UpdateExtension(const Extension* extension, |
| 302 const std::string& update_crx) { |
| 303 base::FilePath data_dir; |
| 304 if (!PathService::Get(chrome::DIR_TEST_DATA, &data_dir)) { |
| 305 ADD_FAILURE(); |
| 306 return; |
| 307 } |
| 308 data_dir = data_dir.AppendASCII("extensions"); |
| 309 data_dir = data_dir.AppendASCII(update_crx); |
| 310 |
| 311 base::FilePath path = temp_dir_.path(); |
| 312 path = path.Append(data_dir.BaseName()); |
| 313 ASSERT_TRUE(base::CopyFile(data_dir, path)); |
| 314 |
| 315 extensions::CrxInstaller* installer = NULL; |
| 316 content::WindowedNotificationObserver observer( |
| 317 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 318 base::Bind(&IsCrxInstallerDone, &installer)); |
| 319 extension_service_->UpdateExtension( |
| 320 extension->id(), path, true, &installer); |
| 321 |
| 322 if (installer) |
| 323 observer.Wait(); |
| 324 } |
| 325 |
271 void DisableExtension(const Extension* extension) { | 326 void DisableExtension(const Extension* extension) { |
272 extension_service_->DisableExtension( | 327 extension_service_->DisableExtension( |
273 extension->id(), Extension::DISABLE_USER_ACTION); | 328 extension->id(), Extension::DISABLE_USER_ACTION); |
274 } | 329 } |
275 | 330 |
276 void EnableExtension(const Extension* extension) { | 331 void EnableExtension(const Extension* extension) { |
277 extension_service_->EnableExtension(extension->id()); | 332 extension_service_->EnableExtension(extension->id()); |
278 } | 333 } |
279 | 334 |
280 void UninstallExtension(const Extension* extension) { | 335 void UninstallExtension(const Extension* extension) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 } | 376 } |
322 gcm::GCMClient::Result registration_result() const { | 377 gcm::GCMClient::Result registration_result() const { |
323 return registration_result_; | 378 return registration_result_; |
324 } | 379 } |
325 gcm::GCMClient::Result unregistration_result() const { | 380 gcm::GCMClient::Result unregistration_result() const { |
326 return unregistration_result_; | 381 return unregistration_result_; |
327 } | 382 } |
328 | 383 |
329 private: | 384 private: |
330 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; | 385 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; |
| 386 scoped_ptr<content::InProcessUtilityThreadHelper> |
| 387 in_process_utility_thread_helper_; |
331 scoped_ptr<TestingProfile> profile_; | 388 scoped_ptr<TestingProfile> profile_; |
332 ExtensionService* extension_service_; // Not owned. | 389 ExtensionService* extension_service_; // Not owned. |
333 gcm::FakeSigninManager* signin_manager_; // Not owned. | 390 gcm::FakeSigninManager* signin_manager_; // Not owned. |
| 391 base::ScopedTempDir temp_dir_; |
334 | 392 |
335 // This is needed to create extension service under CrOS. | 393 // This is needed to create extension service under CrOS. |
336 #if defined(OS_CHROMEOS) | 394 #if defined(OS_CHROMEOS) |
337 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; | 395 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; |
338 chromeos::ScopedTestCrosSettings test_cros_settings_; | 396 chromeos::ScopedTestCrosSettings test_cros_settings_; |
339 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; | 397 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; |
340 #endif | 398 #endif |
341 | 399 |
342 Waiter waiter_; | 400 Waiter waiter_; |
343 scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_; | 401 scoped_ptr<FakeExtensionGCMAppHandler> gcm_app_handler_; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 // Unregistration should be triggered when the extension is uninstalled. | 451 // Unregistration should be triggered when the extension is uninstalled. |
394 UninstallExtension(extension); | 452 UninstallExtension(extension); |
395 waiter()->WaitUntilCompleted(); | 453 waiter()->WaitUntilCompleted(); |
396 EXPECT_EQ(gcm::GCMClient::SUCCESS, | 454 EXPECT_EQ(gcm::GCMClient::SUCCESS, |
397 gcm_app_handler()->unregistration_result()); | 455 gcm_app_handler()->unregistration_result()); |
398 | 456 |
399 // Clean up. | 457 // Clean up. |
400 GetGCMDriver()->RemoveAppHandler("Foo"); | 458 GetGCMDriver()->RemoveAppHandler("Foo"); |
401 } | 459 } |
402 | 460 |
| 461 TEST_F(ExtensionGCMAppHandlerTest, UpdateExtensionWithGcmPermissionKept) { |
| 462 scoped_refptr<Extension> extension(CreateExtension()); |
| 463 |
| 464 // App handler is added when the extension is loaded. |
| 465 LoadExtension(extension); |
| 466 waiter()->PumpUILoop(); |
| 467 EXPECT_TRUE(HasAppHandlers(extension->id())); |
| 468 |
| 469 // App handler count should not drop to zero when the extension is updated. |
| 470 UpdateExtension(extension, "gcm2.crx"); |
| 471 waiter()->PumpUILoop(); |
| 472 EXPECT_FALSE(gcm_app_handler()->app_handler_count_drop_to_zero()); |
| 473 EXPECT_TRUE(HasAppHandlers(extension->id())); |
| 474 } |
| 475 |
| 476 TEST_F(ExtensionGCMAppHandlerTest, UpdateExtensionWithGcmPermissionRemoved) { |
| 477 scoped_refptr<Extension> extension(CreateExtension()); |
| 478 |
| 479 // App handler is added when the extension is loaded. |
| 480 LoadExtension(extension); |
| 481 waiter()->PumpUILoop(); |
| 482 EXPECT_TRUE(HasAppHandlers(extension->id())); |
| 483 |
| 484 // App handler is removed when the extension is updated to the version that |
| 485 // has GCM permission removed. |
| 486 UpdateExtension(extension, "good2.crx"); |
| 487 waiter()->PumpUILoop(); |
| 488 EXPECT_TRUE(gcm_app_handler()->app_handler_count_drop_to_zero()); |
| 489 EXPECT_FALSE(HasAppHandlers(extension->id())); |
| 490 } |
| 491 |
403 } // namespace extensions | 492 } // namespace extensions |
OLD | NEW |