OLD | NEW |
| (Empty) |
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. | |
4 | |
5 // MSVC++ requires this to be set before any other includes to get M_PI. | |
6 #define _USE_MATH_DEFINES | |
7 | |
8 #include "content/browser/geofencing/mock_geofencing_service.h" | |
9 | |
10 #include <cmath> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/location.h" | |
14 #include "base/single_thread_task_runner.h" | |
15 #include "base/threading/thread_task_runner_handle.h" | |
16 #include "content/browser/geofencing/geofencing_registration_delegate.h" | |
17 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h" | |
18 | |
19 namespace content { | |
20 | |
21 namespace { | |
22 | |
23 void RegisterRegionResult(GeofencingRegistrationDelegate* delegate, | |
24 int64_t geofencing_registration_id, | |
25 GeofencingStatus status) { | |
26 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
27 FROM_HERE, | |
28 base::Bind(&GeofencingRegistrationDelegate::RegistrationFinished, | |
29 base::Unretained(delegate), geofencing_registration_id, | |
30 status)); | |
31 } | |
32 | |
33 double DegreesToRadians(float degrees) { | |
34 return (M_PI * degrees) / 180.f; | |
35 } | |
36 | |
37 double Haversin(double theta) { | |
38 double temp = sin(theta / 2); | |
39 return temp * temp; | |
40 } | |
41 | |
42 // Calculates the distance in meters between two points with coordinates in | |
43 // degrees. | |
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)); | |
52 } | |
53 | |
54 // Returns true iff the provided coordinate is inside the region. | |
55 bool PositionInRegion(double latitude, | |
56 double longitude, | |
57 const blink::WebCircularGeofencingRegion& region) { | |
58 return Distance(latitude, longitude, region.latitude, region.longitude) <= | |
59 region.radius; | |
60 } | |
61 } | |
62 | |
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. | |
67 bool is_inside; | |
68 }; | |
69 | |
70 MockGeofencingService::MockGeofencingService(bool service_available) | |
71 : available_(service_available), | |
72 next_id_(0), | |
73 has_position_(false), | |
74 last_latitude_(0), | |
75 last_longitude_(0) { | |
76 } | |
77 | |
78 MockGeofencingService::~MockGeofencingService() { | |
79 } | |
80 | |
81 void MockGeofencingService::SetMockPosition(double latitude, double longitude) { | |
82 has_position_ = true; | |
83 last_latitude_ = latitude; | |
84 last_longitude_ = longitude; | |
85 for (auto& registration : registrations_) { | |
86 bool is_inside = | |
87 PositionInRegion(latitude, longitude, registration.second.region); | |
88 if (is_inside != registration.second.is_inside) { | |
89 if (is_inside) | |
90 registration.second.delegate->RegionEntered(registration.first); | |
91 else | |
92 registration.second.delegate->RegionExited(registration.first); | |
93 } | |
94 registration.second.is_inside = is_inside; | |
95 } | |
96 } | |
97 | |
98 bool MockGeofencingService::IsServiceAvailable() { | |
99 return available_; | |
100 } | |
101 | |
102 int64_t MockGeofencingService::RegisterRegion( | |
103 const blink::WebCircularGeofencingRegion& region, | |
104 GeofencingRegistrationDelegate* delegate) { | |
105 int64_t id = next_id_++; | |
106 Registration& registration = registrations_[id]; | |
107 registration.region = region; | |
108 registration.delegate = delegate; | |
109 registration.is_inside = | |
110 has_position_ && | |
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)); | |
117 } | |
118 return id; | |
119 } | |
120 | |
121 void MockGeofencingService::UnregisterRegion( | |
122 int64_t geofencing_registration_id) { | |
123 registrations_.erase(geofencing_registration_id); | |
124 } | |
125 | |
126 } // namespace content | |
OLD | NEW |