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
{
126 helper_
.reset(new EmbeddedWorkerTestHelper(kRenderProcessId
));
127 service_
= new TestGeofencingService();
128 manager_
= new GeofencingManager(helper_
->context_wrapper());
129 manager_
->SetServiceForTesting(service_
);
132 worker1_
= RegisterServiceWorker("1");
133 worker2_
= RegisterServiceWorker("2");
136 void TearDown() override
{
145 void SetHasProviderForTests() { service_
->SetIsServiceAvailable(true); }
147 scoped_refptr
<ServiceWorkerRegistration
> RegisterServiceWorker(
148 const std::string
& name
) {
149 GURL
pattern("http://www.example.com/" + name
);
150 GURL
script_url("http://www.example.com/service_worker.js");
151 int64 registration_id
= kInvalidServiceWorkerRegistrationId
;
153 helper_
->context()->RegisterServiceWorker(
154 pattern
, script_url
, nullptr,
155 MakeRegisteredCallback(&called
, ®istration_id
));
157 EXPECT_FALSE(called
);
158 base::RunLoop().RunUntilIdle();
161 return make_scoped_refptr(new ServiceWorkerRegistration(
162 pattern
, registration_id
, helper_
->context()->AsWeakPtr()));
165 void UnregisterServiceWorker(
166 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
168 helper_
->context()->UnregisterServiceWorker(
169 registration
->pattern(), MakeUnregisteredCallback(&called
));
171 EXPECT_FALSE(called
);
172 base::RunLoop().RunUntilIdle();
176 GeofencingStatus
RegisterRegionSync(
177 int64 service_worker_registration_id
,
178 const std::string
& id
,
179 const WebCircularGeofencingRegion
& region
) {
180 StatusCatcher result
;
181 manager_
->RegisterRegion(
182 service_worker_registration_id
,
185 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
186 return result
.Wait();
189 GeofencingStatus
RegisterRegionSyncWithServiceResult(
190 int64 service_worker_registration_id
,
191 const std::string
& id
,
192 const WebCircularGeofencingRegion
& region
,
193 GeofencingStatus service_status
,
194 int64 geofencing_registration_id
) {
195 StatusCatcher result
;
196 GeofencingRegistrationDelegate
* delegate
= 0;
199 RegisterRegion(WebCircularGeofencingRegionEq(region
), testing::_
))
200 .WillOnce(testing::DoAll(SaveDelegate(&delegate
),
201 testing::Return(geofencing_registration_id
)));
202 manager_
->RegisterRegion(
203 service_worker_registration_id
,
206 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
208 delegate
->RegistrationFinished(geofencing_registration_id
, service_status
);
209 return result
.Wait();
212 GeofencingStatus
UnregisterRegionSync(int64 service_worker_registration_id
,
213 const std::string
& id
,
214 bool should_call_service
,
215 int64 geofencing_registration_id
= 0) {
216 StatusCatcher result
;
217 if (should_call_service
) {
218 EXPECT_CALL(*service_
, UnregisterRegion(geofencing_registration_id
));
220 manager_
->UnregisterRegion(
221 service_worker_registration_id
,
223 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
224 return result
.Wait();
227 void VerifyRegions(int64 service_worker_registration_id
,
228 const RegionMap
& expected_regions
) {
230 EXPECT_EQ(GEOFENCING_STATUS_OK
,
231 manager_
->GetRegisteredRegions(service_worker_registration_id
,
233 EXPECT_EQ(expected_regions
.size(), regions
.size());
234 for (RegionMap::const_iterator it
= expected_regions
.begin();
235 it
!= expected_regions
.end();
237 EXPECT_THAT(regions
[it
->first
],
238 WebCircularGeofencingRegionEq(it
->second
));
243 TestBrowserThreadBundle threads_
;
244 scoped_ptr
<EmbeddedWorkerTestHelper
> helper_
;
245 TestGeofencingService
* service_
;
246 scoped_refptr
<GeofencingManager
> manager_
;
248 WebCircularGeofencingRegion test_region_
;
249 RegionMap expected_regions_
;
251 scoped_refptr
<ServiceWorkerRegistration
> worker1_
;
252 scoped_refptr
<ServiceWorkerRegistration
> worker2_
;
255 TEST_F(GeofencingManagerTest
, RegisterRegion_NoService
) {
256 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
257 RegisterRegionSync(worker1_
->id(), kTestRegionId
, test_region_
));
260 TEST_F(GeofencingManagerTest
, UnregisterRegion_NoService
) {
261 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
262 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
265 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_NoService
) {
267 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
268 manager_
->GetRegisteredRegions(worker1_
->id(), ®ions
));
269 EXPECT_TRUE(regions
.empty());
272 TEST_F(GeofencingManagerTest
, RegisterRegion_FailsInService
) {
273 SetHasProviderForTests();
274 EXPECT_EQ(GEOFENCING_STATUS_ERROR
,
275 RegisterRegionSyncWithServiceResult(worker1_
->id(), kTestRegionId
,
277 GEOFENCING_STATUS_ERROR
, -1));
280 TEST_F(GeofencingManagerTest
, RegisterRegion_SucceedsInService
) {
281 SetHasProviderForTests();
282 EXPECT_EQ(GEOFENCING_STATUS_OK
,
283 RegisterRegionSyncWithServiceResult(
284 worker1_
->id(), kTestRegionId
, test_region_
,
285 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
286 VerifyRegions(worker1_
->id(), expected_regions_
);
289 TEST_F(GeofencingManagerTest
, RegisterRegion_AlreadyRegistered
) {
290 SetHasProviderForTests();
291 EXPECT_EQ(GEOFENCING_STATUS_OK
,
292 RegisterRegionSyncWithServiceResult(
293 worker1_
->id(), kTestRegionId
, test_region_
,
294 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
295 VerifyRegions(worker1_
->id(), expected_regions_
);
297 WebCircularGeofencingRegion region2
;
298 region2
.latitude
= 43.2;
299 region2
.longitude
= 1.45;
300 region2
.radius
= 8.5;
301 EXPECT_EQ(GEOFENCING_STATUS_ERROR
,
302 RegisterRegionSync(worker1_
->id(), kTestRegionId
, region2
));
303 VerifyRegions(worker1_
->id(), expected_regions_
);
306 TEST_F(GeofencingManagerTest
, UnregisterRegion_NotRegistered
) {
307 SetHasProviderForTests();
308 EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED
,
309 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
312 TEST_F(GeofencingManagerTest
, UnregisterRegion_Success
) {
313 SetHasProviderForTests();
315 EXPECT_EQ(GEOFENCING_STATUS_OK
,
316 RegisterRegionSyncWithServiceResult(
317 worker1_
->id(), kTestRegionId
, test_region_
,
318 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
320 EXPECT_EQ(GEOFENCING_STATUS_OK
,
321 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, true,
322 kTestGeofencingRegistrationId
));
323 VerifyRegions(worker1_
->id(), RegionMap());
326 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_RegistrationInProgress
) {
327 SetHasProviderForTests();
328 StatusCatcher result
;
329 GeofencingRegistrationDelegate
* delegate
= nullptr;
333 RegisterRegion(WebCircularGeofencingRegionEq(test_region_
), testing::_
))
334 .WillOnce(testing::DoAll(SaveDelegate(&delegate
),
335 testing::Return(kTestGeofencingRegistrationId
)));
336 manager_
->RegisterRegion(
337 worker1_
->id(), kTestRegionId
, test_region_
,
338 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
340 // At this point the manager should have tried registering the region with
341 // the service, resulting in |delegate| being set. Until the callback is
342 // called the registration is not complete though.
343 EXPECT_NE(delegate
, nullptr);
344 VerifyRegions(worker1_
->id(), RegionMap());
346 // Now call the callback, and verify the registration completed succesfully.
347 delegate
->RegistrationFinished(kTestGeofencingRegistrationId
,
348 GEOFENCING_STATUS_OK
);
349 EXPECT_EQ(GEOFENCING_STATUS_OK
, result
.Wait());
350 VerifyRegions(worker1_
->id(), expected_regions_
);
353 TEST_F(GeofencingManagerTest
, UnregisterRegion_RegistrationInProgress
) {
354 SetHasProviderForTests();
355 StatusCatcher result
;
356 GeofencingRegistrationDelegate
* delegate
= nullptr;
360 RegisterRegion(WebCircularGeofencingRegionEq(test_region_
), testing::_
))
361 .WillOnce(testing::DoAll(SaveDelegate(&delegate
),
362 testing::Return(kTestGeofencingRegistrationId
)));
363 manager_
->RegisterRegion(
364 worker1_
->id(), kTestRegionId
, test_region_
,
365 base::Bind(&StatusCatcher::Done
, base::Unretained(&result
)));
367 // At this point the manager should have tried registering the region with
368 // the service, resulting in |delegate| being set. Until the callback is
369 // called the registration is not complete though.
370 EXPECT_NE(delegate
, nullptr);
372 EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED
,
373 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
376 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_NoRegions
) {
377 SetHasProviderForTests();
378 VerifyRegions(worker1_
->id(), RegionMap());
381 TEST_F(GeofencingManagerTest
, RegisterRegion_SeparateServiceWorkers
) {
382 SetHasProviderForTests();
384 EXPECT_EQ(GEOFENCING_STATUS_OK
,
385 RegisterRegionSyncWithServiceResult(
386 worker1_
->id(), kTestRegionId
, test_region_
,
387 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
389 VerifyRegions(worker1_
->id(), expected_regions_
);
390 VerifyRegions(worker2_
->id(), RegionMap());
392 EXPECT_EQ(GEOFENCING_STATUS_OK
,
393 RegisterRegionSyncWithServiceResult(
394 worker2_
->id(), kTestRegionId
, test_region_
,
395 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId2
));
397 VerifyRegions(worker1_
->id(), expected_regions_
);
398 VerifyRegions(worker2_
->id(), expected_regions_
);
401 TEST_F(GeofencingManagerTest
, UnregisterRegion_SeparateServiceWorkers
) {
402 SetHasProviderForTests();
404 EXPECT_EQ(GEOFENCING_STATUS_OK
,
405 RegisterRegionSyncWithServiceResult(
406 worker1_
->id(), kTestRegionId
, test_region_
,
407 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
408 EXPECT_EQ(GEOFENCING_STATUS_OK
,
409 RegisterRegionSyncWithServiceResult(
410 worker2_
->id(), kTestRegionId
, test_region_
,
411 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId2
));
413 EXPECT_EQ(GEOFENCING_STATUS_OK
,
414 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, true,
415 kTestGeofencingRegistrationId
));
417 VerifyRegions(worker1_
->id(), RegionMap());
418 VerifyRegions(worker2_
->id(), expected_regions_
);
420 EXPECT_EQ(GEOFENCING_STATUS_OK
,
421 UnregisterRegionSync(worker2_
->id(), kTestRegionId
, true,
422 kTestGeofencingRegistrationId2
));
424 VerifyRegions(worker1_
->id(), RegionMap());
425 VerifyRegions(worker2_
->id(), RegionMap());
428 TEST_F(GeofencingManagerTest
, ShutdownCleansRegistrations
) {
429 SetHasProviderForTests();
430 scoped_refptr
<MessageLoopRunner
> runner(new MessageLoopRunner());
431 EXPECT_EQ(GEOFENCING_STATUS_OK
,
432 RegisterRegionSyncWithServiceResult(
433 worker1_
->id(), kTestRegionId
, test_region_
,
434 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
436 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId
))
437 .WillOnce(QuitRunner(runner
));
438 manager_
->Shutdown();
442 TEST_F(GeofencingManagerTest
, OnRegistrationDeleted
) {
443 SetHasProviderForTests();
445 EXPECT_EQ(GEOFENCING_STATUS_OK
,
446 RegisterRegionSyncWithServiceResult(
447 worker1_
->id(), kTestRegionId
, test_region_
,
448 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
449 EXPECT_EQ(GEOFENCING_STATUS_OK
,
450 RegisterRegionSyncWithServiceResult(
451 worker2_
->id(), kTestRegionId
, test_region_
,
452 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId2
));
454 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId
));
455 UnregisterServiceWorker(worker1_
);
456 VerifyRegions(worker1_
->id(), RegionMap());
457 VerifyRegions(worker2_
->id(), expected_regions_
);
459 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId2
));
460 UnregisterServiceWorker(worker2_
);
461 VerifyRegions(worker1_
->id(), RegionMap());
462 VerifyRegions(worker2_
->id(), RegionMap());
465 TEST_F(GeofencingManagerTest
, RegisterRegion_MockedNoService
) {
466 manager_
->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE
);
468 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
469 RegisterRegionSync(worker1_
->id(), kTestRegionId
, test_region_
));
472 TEST_F(GeofencingManagerTest
, UnregisterRegion_MockedNoService
) {
473 manager_
->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE
);
475 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
476 UnregisterRegionSync(worker1_
->id(), kTestRegionId
, false));
479 TEST_F(GeofencingManagerTest
, GetRegisteredRegions_MockedNoService
) {
480 manager_
->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE
);
483 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE
,
484 manager_
->GetRegisteredRegions(worker1_
->id(), ®ions
));
485 EXPECT_TRUE(regions
.empty());
488 TEST_F(GeofencingManagerTest
, RegisterRegion_MockedService
) {
489 manager_
->SetMockProvider(GeofencingMockState::SERVICE_AVAILABLE
);
491 // Make sure real service doesn't get called.
492 EXPECT_CALL(*service_
, RegisterRegion(testing::_
, testing::_
)).Times(0);
494 EXPECT_EQ(GEOFENCING_STATUS_OK
,
495 RegisterRegionSync(worker1_
->id(), kTestRegionId
, test_region_
));
496 VerifyRegions(worker1_
->id(), expected_regions_
);
499 TEST_F(GeofencingManagerTest
, SetMockProviderClearsRegistrations
) {
500 SetHasProviderForTests();
501 EXPECT_EQ(GEOFENCING_STATUS_OK
,
502 RegisterRegionSyncWithServiceResult(
503 worker1_
->id(), kTestRegionId
, test_region_
,
504 GEOFENCING_STATUS_OK
, kTestGeofencingRegistrationId
));
505 VerifyRegions(worker1_
->id(), expected_regions_
);
507 EXPECT_CALL(*service_
, UnregisterRegion(kTestGeofencingRegistrationId
));
509 manager_
->SetMockProvider(GeofencingMockState::SERVICE_AVAILABLE
);
510 VerifyRegions(worker1_
->id(), RegionMap());
513 } // namespace content