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 "base/callback.h"
6 #include "base/message_loop/message_loop.h"
7 #include "content/browser/geofencing/geofencing_manager.h"
8 #include "content/browser/geofencing/geofencing_service.h"
9 #include "content/browser/service_worker/embedded_worker_test_helper.h"
10 #include "content/browser/service_worker/service_worker_context_wrapper.h"
11 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "content/public/test/test_utils.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
17 using blink::WebCircularGeofencingRegion
;
18 typedef std::map
<std::string
, WebCircularGeofencingRegion
> RegionMap
;
22 static const int kRenderProcessId
= 99;
23 static const char* kTestRegionId
= "region-id";
24 static const int64 kTestGeofencingRegistrationId
= 42;
25 static const int64 kTestGeofencingRegistrationId2
= 43;
27 bool RegionsMatch(const WebCircularGeofencingRegion
& expected
,
28 const WebCircularGeofencingRegion
& arg
) {
29 return testing::Matches(expected
.latitude
)(arg
.latitude
) &&
30 testing::Matches(expected
.longitude
)(arg
.longitude
) &&
31 testing::Matches(expected
.radius
)(arg
.radius
);
37 class TestGeofencingService
: public GeofencingService
{
39 TestGeofencingService() : is_available_(false) {}
41 bool IsServiceAvailable() override
{ return is_available_
; }
43 void SetIsServiceAvailable(bool is_available
) {
44 is_available_
= is_available
;
47 MOCK_METHOD2(RegisterRegion
,
48 int64(const WebCircularGeofencingRegion
& region
,
49 GeofencingRegistrationDelegate
* delegate
));
50 MOCK_METHOD1(UnregisterRegion
, void(int64 geofencing_registration_id
));
56 ACTION_P(SaveDelegate
, delegate
) {
60 ACTION_P(QuitRunner
, runner
) {
64 MATCHER_P(WebCircularGeofencingRegionEq
, expected
, "") {
65 return RegionsMatch(expected
, arg
);
70 StatusCatcher() : was_called_(false), runner_(new MessageLoopRunner()) {}
72 void Done(GeofencingStatus status
) {
79 GeofencingStatus
Wait() {
87 GeofencingStatus result_
;
88 scoped_refptr
<MessageLoopRunner
> runner_
;
91 void SaveResponseCallback(bool* called
,
92 int64
* store_registration_id
,
93 ServiceWorkerStatusCode status
,
94 const std::string
& status_message
,
95 int64 registration_id
) {
96 EXPECT_EQ(SERVICE_WORKER_OK
, status
) << ServiceWorkerStatusToString(status
);
98 *store_registration_id
= registration_id
;
101 ServiceWorkerContextCore::RegistrationCallback
MakeRegisteredCallback(
103 int64
* store_registration_id
) {
104 return base::Bind(&SaveResponseCallback
, called
, store_registration_id
);
107 void CallCompletedCallback(bool* called
, ServiceWorkerStatusCode
) {
111 ServiceWorkerContextCore::UnregistrationCallback
MakeUnregisteredCallback(
113 return base::Bind(&CallCompletedCallback
, called
);
116 class GeofencingManagerTest
: public testing::Test
{
118 GeofencingManagerTest() : service_(nullptr) {
119 test_region_
.latitude
= 37.421999;
120 test_region_
.longitude
= -122.084015;
121 test_region_
.radius
= 100;
122 expected_regions_
[kTestRegionId
] = test_region_
;
125 void SetUp() override
{
127 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId
));
128 service_
= new TestGeofencingService();
129 manager_
= new GeofencingManager(helper_
->context_wrapper());
130 manager_
->SetServiceForTesting(service_
);
133 worker1_
= RegisterServiceWorker("1");
134 worker2_
= RegisterServiceWorker("2");
137 void TearDown() override
{
146 void SetHasProviderForTests() { service_
->SetIsServiceAvailable(true); }
148 scoped_refptr
<ServiceWorkerRegistration
> RegisterServiceWorker(
149 const std::string
& name
) {
150 GURL
pattern("http://www.example.com/" + name
);
151 GURL
script_url("http://www.example.com/service_worker.js");
152 int64 registration_id
= kInvalidServiceWorkerRegistrationId
;
154 helper_
->context()->RegisterServiceWorker(
155 pattern
, script_url
, nullptr,
156 MakeRegisteredCallback(&called
, ®istration_id
));
158 EXPECT_FALSE(called
);
159 base::RunLoop().RunUntilIdle();
161 scoped_refptr
<ServiceWorkerRegistration
> worker(
162 new ServiceWorkerRegistration(pattern
, registration_id
,
163 helper_
->context()->AsWeakPtr()));
164 // ServiceWorkerRegistration posts a notification task on construction.
165 base::RunLoop().RunUntilIdle();
169 void UnregisterServiceWorker(
170 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
172 helper_
->context()->UnregisterServiceWorker(
173 registration
->pattern(), MakeUnregisteredCallback(&called
));
175 EXPECT_FALSE(called
);
176 base::RunLoop().RunUntilIdle();
180 GeofencingStatus
RegisterRegionSync(
181 int64 service_worker_registration_id
,
182 const std::string
& id
,
183 const WebCircularGeofencingRegion
& region
) {
184 StatusCatcher result
;
185 manager_
->RegisterRegion(
186 service_worker_registration_id
,
189 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
190 return result
.Wait();
193 GeofencingStatus
RegisterRegionSyncWithServiceResult(
194 int64 service_worker_registration_id
,
195 const std::string
& id
,
196 const WebCircularGeofencingRegion
& region
,
197 GeofencingStatus service_status
,
198 int64 geofencing_registration_id
) {
199 StatusCatcher result
;
200 GeofencingRegistrationDelegate
* delegate
= 0;
203 RegisterRegion(WebCircularGeofencingRegionEq(region
), testing::_
))
204 .WillOnce(testing::DoAll(SaveDelegate(&delegate
),
205 testing::Return(geofencing_registration_id
)));
206 manager_
->RegisterRegion(
207 service_worker_registration_id
,
210 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
212 delegate
->RegistrationFinished(geofencing_registration_id
, service_status
);
213 return result
.Wait();
216 GeofencingStatus
UnregisterRegionSync(int64 service_worker_registration_id
,
217 const std::string
& id
,
218 bool should_call_service
,
219 int64 geofencing_registration_id
= 0) {
220 StatusCatcher result
;
221 if (should_call_service
) {
222 EXPECT_CALL(*service_
, UnregisterRegion(geofencing_registration_id
));
224 manager_
->UnregisterRegion(
225 service_worker_registration_id
,
227 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
228 return result
.Wait();
231 void VerifyRegions(int64 service_worker_registration_id
,
232 const RegionMap
& expected_regions
) {
234 EXPECT_EQ(GEOFENCING_STATUS_OK
,
235 manager_
->GetRegisteredRegions(service_worker_registration_id
,
237 EXPECT_EQ(expected_regions
.size(), regions
.size());
238 for (RegionMap::const_iterator it
= expected_regions
.begin();
239 it
!= expected_regions
.end();
241 EXPECT_THAT(regions
[it
->first
],
242 WebCircularGeofencingRegionEq(it
->second
));
247 TestBrowserThreadBundle threads_
;
248 scoped_ptr
<EmbeddedWorkerTestHelper
> helper_
;
249 TestGeofencingService
* service_
;
250 scoped_refptr
<GeofencingManager
> manager_
;
252 WebCircularGeofencingRegion test_region_
;
253 RegionMap expected_regions_
;
255 scoped_refptr
<ServiceWorkerRegistration
> worker1_
;
256 scoped_refptr
<ServiceWorkerRegistration
> worker2_
;
259 TEST_F(GeofencingManagerTest
, RegisterRegion_NoService
) {
260 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
261 RegisterRegionSync(worker1_
->id(), kTestRegionId
, test_region_
));
264 TEST_F(GeofencingManagerTest
, UnregisterRegion_NoService
) {
265 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
266 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
269 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_NoService
) {
271 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
272 manager_
->GetRegisteredRegions(worker1_
->id(), ®ions
));
273 EXPECT_TRUE(regions
.empty());
276 TEST_F(GeofencingManagerTest
, RegisterRegion_FailsInService
) {
277 SetHasProviderForTests();
278 EXPECT_EQ(GEOFENCING_STATUS_ERROR
,
279 RegisterRegionSyncWithServiceResult(worker1_
->id(), kTestRegionId
,
281 GEOFENCING_STATUS_ERROR
, -1));
284 TEST_F(GeofencingManagerTest
, RegisterRegion_SucceedsInService
) {
285 SetHasProviderForTests();
286 EXPECT_EQ(GEOFENCING_STATUS_OK
,
287 RegisterRegionSyncWithServiceResult(
288 worker1_
->id(), kTestRegionId
, test_region_
,
289 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
290 VerifyRegions(worker1_
->id(), expected_regions_
);
293 TEST_F(GeofencingManagerTest
, RegisterRegion_AlreadyRegistered
) {
294 SetHasProviderForTests();
295 EXPECT_EQ(GEOFENCING_STATUS_OK
,
296 RegisterRegionSyncWithServiceResult(
297 worker1_
->id(), kTestRegionId
, test_region_
,
298 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
299 VerifyRegions(worker1_
->id(), expected_regions_
);
301 WebCircularGeofencingRegion region2
;
302 region2
.latitude
= 43.2;
303 region2
.longitude
= 1.45;
304 region2
.radius
= 8.5;
305 EXPECT_EQ(GEOFENCING_STATUS_ERROR
,
306 RegisterRegionSync(worker1_
->id(), kTestRegionId
, region2
));
307 VerifyRegions(worker1_
->id(), expected_regions_
);
310 TEST_F(GeofencingManagerTest
, UnregisterRegion_NotRegistered
) {
311 SetHasProviderForTests();
312 EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED
,
313 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
316 TEST_F(GeofencingManagerTest
, UnregisterRegion_Success
) {
317 SetHasProviderForTests();
319 EXPECT_EQ(GEOFENCING_STATUS_OK
,
320 RegisterRegionSyncWithServiceResult(
321 worker1_
->id(), kTestRegionId
, test_region_
,
322 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
324 EXPECT_EQ(GEOFENCING_STATUS_OK
,
325 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, true,
326 kTestGeofencingRegistrationId
));
327 VerifyRegions(worker1_
->id(), RegionMap());
330 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_RegistrationInProgress
) {
331 SetHasProviderForTests();
332 StatusCatcher result
;
333 GeofencingRegistrationDelegate
* delegate
= nullptr;
337 RegisterRegion(WebCircularGeofencingRegionEq(test_region_
), testing::_
))
338 .WillOnce(testing::DoAll(SaveDelegate(&delegate
),
339 testing::Return(kTestGeofencingRegistrationId
)));
340 manager_
->RegisterRegion(
341 worker1_
->id(), kTestRegionId
, test_region_
,
342 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
344 // At this point the manager should have tried registering the region with
345 // the service, resulting in |delegate| being set. Until the callback is
346 // called the registration is not complete though.
347 EXPECT_NE(delegate
, nullptr);
348 VerifyRegions(worker1_
->id(), RegionMap());
350 // Now call the callback, and verify the registration completed succesfully.
351 delegate
->RegistrationFinished(kTestGeofencingRegistrationId
,
352 GEOFENCING_STATUS_OK
);
353 EXPECT_EQ(GEOFENCING_STATUS_OK
, result
.Wait());
354 VerifyRegions(worker1_
->id(), expected_regions_
);
357 TEST_F(GeofencingManagerTest
, UnregisterRegion_RegistrationInProgress
) {
358 SetHasProviderForTests();
359 StatusCatcher result
;
360 GeofencingRegistrationDelegate
* delegate
= nullptr;
364 RegisterRegion(WebCircularGeofencingRegionEq(test_region_
), testing::_
))
365 .WillOnce(testing::DoAll(SaveDelegate(&delegate
),
366 testing::Return(kTestGeofencingRegistrationId
)));
367 manager_
->RegisterRegion(
368 worker1_
->id(), kTestRegionId
, test_region_
,
369 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
371 // At this point the manager should have tried registering the region with
372 // the service, resulting in |delegate| being set. Until the callback is
373 // called the registration is not complete though.
374 EXPECT_NE(delegate
, nullptr);
376 EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED
,
377 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
380 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_NoRegions
) {
381 SetHasProviderForTests();
382 VerifyRegions(worker1_
->id(), RegionMap());
385 TEST_F(GeofencingManagerTest
, RegisterRegion_SeparateServiceWorkers
) {
386 SetHasProviderForTests();
388 EXPECT_EQ(GEOFENCING_STATUS_OK
,
389 RegisterRegionSyncWithServiceResult(
390 worker1_
->id(), kTestRegionId
, test_region_
,
391 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
393 VerifyRegions(worker1_
->id(), expected_regions_
);
394 VerifyRegions(worker2_
->id(), RegionMap());
396 EXPECT_EQ(GEOFENCING_STATUS_OK
,
397 RegisterRegionSyncWithServiceResult(
398 worker2_
->id(), kTestRegionId
, test_region_
,
399 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId2
));
401 VerifyRegions(worker1_
->id(), expected_regions_
);
402 VerifyRegions(worker2_
->id(), expected_regions_
);
405 TEST_F(GeofencingManagerTest
, UnregisterRegion_SeparateServiceWorkers
) {
406 SetHasProviderForTests();
408 EXPECT_EQ(GEOFENCING_STATUS_OK
,
409 RegisterRegionSyncWithServiceResult(
410 worker1_
->id(), kTestRegionId
, test_region_
,
411 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
412 EXPECT_EQ(GEOFENCING_STATUS_OK
,
413 RegisterRegionSyncWithServiceResult(
414 worker2_
->id(), kTestRegionId
, test_region_
,
415 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId2
));
417 EXPECT_EQ(GEOFENCING_STATUS_OK
,
418 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, true,
419 kTestGeofencingRegistrationId
));
421 VerifyRegions(worker1_
->id(), RegionMap());
422 VerifyRegions(worker2_
->id(), expected_regions_
);
424 EXPECT_EQ(GEOFENCING_STATUS_OK
,
425 UnregisterRegionSync(worker2_
->id(), kTestRegionId
, true,
426 kTestGeofencingRegistrationId2
));
428 VerifyRegions(worker1_
->id(), RegionMap());
429 VerifyRegions(worker2_
->id(), RegionMap());
432 TEST_F(GeofencingManagerTest
, ShutdownCleansRegistrations
) {
433 SetHasProviderForTests();
434 scoped_refptr
<MessageLoopRunner
> runner(new MessageLoopRunner());
435 EXPECT_EQ(GEOFENCING_STATUS_OK
,
436 RegisterRegionSyncWithServiceResult(
437 worker1_
->id(), kTestRegionId
, test_region_
,
438 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
440 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId
))
441 .WillOnce(QuitRunner(runner
));
442 manager_
->Shutdown();
446 TEST_F(GeofencingManagerTest
, OnRegistrationDeleted
) {
447 SetHasProviderForTests();
449 EXPECT_EQ(GEOFENCING_STATUS_OK
,
450 RegisterRegionSyncWithServiceResult(
451 worker1_
->id(), kTestRegionId
, test_region_
,
452 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
453 EXPECT_EQ(GEOFENCING_STATUS_OK
,
454 RegisterRegionSyncWithServiceResult(
455 worker2_
->id(), kTestRegionId
, test_region_
,
456 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId2
));
458 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId
));
459 UnregisterServiceWorker(worker1_
);
460 VerifyRegions(worker1_
->id(), RegionMap());
461 VerifyRegions(worker2_
->id(), expected_regions_
);
463 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId2
));
464 UnregisterServiceWorker(worker2_
);
465 VerifyRegions(worker1_
->id(), RegionMap());
466 VerifyRegions(worker2_
->id(), RegionMap());
469 TEST_F(GeofencingManagerTest
, RegisterRegion_MockedNoService
) {
470 manager_
->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE
);
472 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
473 RegisterRegionSync(worker1_
->id(), kTestRegionId
, test_region_
));
476 TEST_F(GeofencingManagerTest
, UnregisterRegion_MockedNoService
) {
477 manager_
->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE
);
479 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
480 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
483 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_MockedNoService
) {
484 manager_
->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE
);
487 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
488 manager_
->GetRegisteredRegions(worker1_
->id(), ®ions
));
489 EXPECT_TRUE(regions
.empty());
492 TEST_F(GeofencingManagerTest
, RegisterRegion_MockedService
) {
493 manager_
->SetMockProvider(GeofencingMockState::SERVICE_AVAILABLE
);
495 // Make sure real service doesn't get called.
496 EXPECT_CALL(*service_
, RegisterRegion(testing::_
, testing::_
)).Times(0);
498 EXPECT_EQ(GEOFENCING_STATUS_OK
,
499 RegisterRegionSync(worker1_
->id(), kTestRegionId
, test_region_
));
500 VerifyRegions(worker1_
->id(), expected_regions_
);
503 TEST_F(GeofencingManagerTest
, SetMockProviderClearsRegistrations
) {
504 SetHasProviderForTests();
505 EXPECT_EQ(GEOFENCING_STATUS_OK
,
506 RegisterRegionSyncWithServiceResult(
507 worker1_
->id(), kTestRegionId
, test_region_
,
508 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
509 VerifyRegions(worker1_
->id(), expected_regions_
);
511 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId
));
513 manager_
->SetMockProvider(GeofencingMockState::SERVICE_AVAILABLE
);
514 VerifyRegions(worker1_
->id(), RegionMap());
517 } // namespace content