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 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
8 #include "content/browser/geofencing/mock_geofencing_service.h"
12 #include "base/bind.h"
13 #include "base/message_loop/message_loop.h"
14 #include "content/browser/geofencing/geofencing_registration_delegate.h"
15 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
21 void RegisterRegionResult(GeofencingRegistrationDelegate
* delegate
,
22 int64 geofencing_registration_id
,
23 GeofencingStatus status
) {
24 base::MessageLoop::current()->PostTask(
26 base::Bind(&GeofencingRegistrationDelegate::RegistrationFinished
,
27 base::Unretained(delegate
), geofencing_registration_id
,
31 double DegreesToRadians(float degrees
) {
32 return (M_PI
* degrees
) / 180.f
;
35 double Haversin(double theta
) {
36 double temp
= sin(theta
/ 2);
40 // Calculates the distance in meters between two points with coordinates in
42 double Distance(double lat1
, double long1
, double lat2
, double long2
) {
43 double R
= 6371000; // radius of earth in meters
44 double phi1
= DegreesToRadians(lat1
);
45 double phi2
= DegreesToRadians(lat2
);
46 double dphi
= DegreesToRadians(lat2
- lat1
);
47 double dlambda
= DegreesToRadians(long2
- long1
);
48 double haversine
= Haversin(dphi
) + cos(phi1
) * cos(phi2
) * Haversin(dlambda
);
49 return 2 * R
* asin(sqrt(haversine
));
52 // Returns true iff the provided coordinate is inside the region.
53 bool PositionInRegion(double latitude
,
55 const blink::WebCircularGeofencingRegion
& region
) {
56 return Distance(latitude
, longitude
, region
.latitude
, region
.longitude
) <=
61 struct MockGeofencingService::Registration
{
62 blink::WebCircularGeofencingRegion region
;
63 GeofencingRegistrationDelegate
* delegate
;
64 // True iff the last event emitted for this region was a RegionEntered event.
68 MockGeofencingService::MockGeofencingService(bool service_available
)
69 : available_(service_available
),
76 MockGeofencingService::~MockGeofencingService() {
79 void MockGeofencingService::SetMockPosition(double latitude
, double longitude
) {
81 last_latitude_
= latitude
;
82 last_longitude_
= longitude
;
83 for (auto& registration
: registrations_
) {
85 PositionInRegion(latitude
, longitude
, registration
.second
.region
);
86 if (is_inside
!= registration
.second
.is_inside
) {
88 registration
.second
.delegate
->RegionEntered(registration
.first
);
90 registration
.second
.delegate
->RegionExited(registration
.first
);
92 registration
.second
.is_inside
= is_inside
;
96 bool MockGeofencingService::IsServiceAvailable() {
100 int64
MockGeofencingService::RegisterRegion(
101 const blink::WebCircularGeofencingRegion
& region
,
102 GeofencingRegistrationDelegate
* delegate
) {
103 int64 id
= next_id_
++;
104 Registration
& registration
= registrations_
[id
];
105 registration
.region
= region
;
106 registration
.delegate
= delegate
;
107 registration
.is_inside
=
109 PositionInRegion(last_latitude_
, last_longitude_
, region
);
110 RegisterRegionResult(delegate
, id
, GEOFENCING_STATUS_OK
);
111 if (registration
.is_inside
) {
112 base::MessageLoop::current()->PostTask(
113 FROM_HERE
, base::Bind(&GeofencingRegistrationDelegate::RegionEntered
,
114 base::Unretained(delegate
), id
));
119 void MockGeofencingService::UnregisterRegion(int64 geofencing_registration_id
) {
120 registrations_
.erase(geofencing_registration_id
);
123 } // namespace content