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/location.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "content/browser/geofencing/geofencing_registration_delegate.h"
17 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
23 void RegisterRegionResult(GeofencingRegistrationDelegate
* delegate
,
24 int64 geofencing_registration_id
,
25 GeofencingStatus status
) {
26 base::ThreadTaskRunnerHandle::Get()->PostTask(
28 base::Bind(&GeofencingRegistrationDelegate::RegistrationFinished
,
29 base::Unretained(delegate
), geofencing_registration_id
,
33 double DegreesToRadians(float degrees
) {
34 return (M_PI
* degrees
) / 180.f
;
37 double Haversin(double theta
) {
38 double temp
= sin(theta
/ 2);
42 // Calculates the distance in meters between two points with coordinates in
44 double Distance(double lat1
, double long1
, double lat2
, double long2
) {
45 double R
= 6371000; // radius of earth in meters
46 double phi1
= DegreesToRadians(lat1
);
47 double phi2
= DegreesToRadians(lat2
);
48 double dphi
= DegreesToRadians(lat2
- lat1
);
49 double dlambda
= DegreesToRadians(long2
- long1
);
50 double haversine
= Haversin(dphi
) + cos(phi1
) * cos(phi2
) * Haversin(dlambda
);
51 return 2 * R
* asin(sqrt(haversine
));
54 // Returns true iff the provided coordinate is inside the region.
55 bool PositionInRegion(double latitude
,
57 const blink::WebCircularGeofencingRegion
& region
) {
58 return Distance(latitude
, longitude
, region
.latitude
, region
.longitude
) <=
63 struct MockGeofencingService::Registration
{
64 blink::WebCircularGeofencingRegion region
;
65 GeofencingRegistrationDelegate
* delegate
;
66 // True iff the last event emitted for this region was a RegionEntered event.
70 MockGeofencingService::MockGeofencingService(bool service_available
)
71 : available_(service_available
),
78 MockGeofencingService::~MockGeofencingService() {
81 void MockGeofencingService::SetMockPosition(double latitude
, double longitude
) {
83 last_latitude_
= latitude
;
84 last_longitude_
= longitude
;
85 for (auto& registration
: registrations_
) {
87 PositionInRegion(latitude
, longitude
, registration
.second
.region
);
88 if (is_inside
!= registration
.second
.is_inside
) {
90 registration
.second
.delegate
->RegionEntered(registration
.first
);
92 registration
.second
.delegate
->RegionExited(registration
.first
);
94 registration
.second
.is_inside
= is_inside
;
98 bool MockGeofencingService::IsServiceAvailable() {
102 int64
MockGeofencingService::RegisterRegion(
103 const blink::WebCircularGeofencingRegion
& region
,
104 GeofencingRegistrationDelegate
* delegate
) {
105 int64 id
= next_id_
++;
106 Registration
& registration
= registrations_
[id
];
107 registration
.region
= region
;
108 registration
.delegate
= delegate
;
109 registration
.is_inside
=
111 PositionInRegion(last_latitude_
, last_longitude_
, region
);
112 RegisterRegionResult(delegate
, id
, GEOFENCING_STATUS_OK
);
113 if (registration
.is_inside
) {
114 base::ThreadTaskRunnerHandle::Get()->PostTask(
115 FROM_HERE
, base::Bind(&GeofencingRegistrationDelegate::RegionEntered
,
116 base::Unretained(delegate
), id
));
121 void MockGeofencingService::UnregisterRegion(int64 geofencing_registration_id
) {
122 registrations_
.erase(geofencing_registration_id
);
125 } // namespace content