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 #include "content/browser/geofencing/geofencing_service.h" | |
6 | |
7 #include "base/memory/singleton.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "content/browser/geofencing/geofencing_provider.h" | |
10 #include "content/browser/geofencing/geofencing_registration_delegate.h" | |
11 #include "content/public/browser/browser_thread.h" | |
12 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h" | |
13 | |
14 namespace content { | |
15 | |
16 namespace { | |
17 | |
18 void RunSoon(const base::Closure& callback) { | |
19 if (!callback.is_null()) | |
20 base::MessageLoop::current()->PostTask(FROM_HERE, callback); | |
21 } | |
22 | |
23 } // namespace | |
24 | |
25 struct GeofencingService::Registration { | |
26 Registration(); | |
27 Registration(const blink::WebCircularGeofencingRegion& region, | |
28 int64 geofencing_registration_id, | |
29 GeofencingRegistrationDelegate* delegate); | |
30 | |
31 blink::WebCircularGeofencingRegion region; | |
32 int64 geofencing_registration_id; | |
33 GeofencingRegistrationDelegate* delegate; | |
34 | |
35 enum RegistrationState { | |
36 // In progress of being registered with provider. | |
37 STATE_REGISTERING, | |
38 // Currently registered with provider. | |
39 STATE_REGISTERED, | |
40 // In progress of being registered with provider, but should be unregistered | |
41 // and deleted. | |
42 STATE_SHOULD_UNREGISTER_AND_DELETE, | |
43 // Not currently registered with provider, but still an active registration. | |
44 STATE_UNREGISTERED | |
45 }; | |
46 RegistrationState state; | |
47 }; | |
48 | |
49 GeofencingService::Registration::Registration() | |
50 : geofencing_registration_id(-1), | |
51 delegate(nullptr), | |
52 state(STATE_UNREGISTERED) { | |
53 } | |
54 | |
55 GeofencingService::Registration::Registration( | |
56 const blink::WebCircularGeofencingRegion& region, | |
57 int64 geofencing_registration_id, | |
58 GeofencingRegistrationDelegate* delegate) | |
59 : region(region), | |
60 geofencing_registration_id(geofencing_registration_id), | |
61 delegate(delegate), | |
62 state(STATE_REGISTERING) { | |
63 } | |
64 | |
65 GeofencingService::GeofencingService() : next_registration_id_(0) { | |
66 } | |
67 | |
68 GeofencingService::~GeofencingService() { | |
69 } | |
70 | |
71 GeofencingService* GeofencingService::GetInstance() { | |
72 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
73 return Singleton<GeofencingService>::get(); | |
74 } | |
75 | |
76 bool GeofencingService::IsServiceAvailable() { | |
77 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
78 return EnsureProvider(); | |
79 } | |
80 | |
81 int64 GeofencingService::RegisterRegion( | |
82 const blink::WebCircularGeofencingRegion& region, | |
83 GeofencingRegistrationDelegate* delegate) { | |
84 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
85 | |
86 int64 geofencing_registration_id = GetNextId(); | |
87 registrations_[geofencing_registration_id] = | |
88 Registration(region, geofencing_registration_id, delegate); | |
89 | |
90 if (!EnsureProvider()) { | |
91 RunSoon( | |
92 base::Bind(&GeofencingService::NotifyRegistrationFinished, | |
93 base::Unretained(this), | |
94 geofencing_registration_id, | |
95 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE)); | |
96 return geofencing_registration_id; | |
Michael van Ouwerkerk
2014/10/21 11:46:41
Minting a new id seems pointless if the operation
Marijn Kruisselbrink
2014/10/21 23:50:07
I'd rather not handle different failure cases diff
| |
97 } | |
98 | |
99 provider_->RegisterRegion( | |
100 geofencing_registration_id, | |
101 region, | |
102 base::Bind(&GeofencingService::NotifyRegistrationFinished, | |
103 base::Unretained(this), | |
104 geofencing_registration_id)); | |
105 return geofencing_registration_id; | |
106 } | |
107 | |
108 void GeofencingService::UnregisterRegion(int64 geofencing_registration_id) { | |
109 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
110 | |
111 RegistrationsMap::iterator registration_iterator = | |
112 registrations_.find(geofencing_registration_id); | |
113 DCHECK(registration_iterator != registrations_.end()); | |
114 | |
115 if (!EnsureProvider()) | |
116 return; | |
117 | |
118 switch (registration_iterator->second.state) { | |
119 case Registration::STATE_REGISTERED: | |
120 provider_->UnregisterRegion(geofencing_registration_id); | |
121 // fallthru | |
122 case Registration::STATE_UNREGISTERED: | |
123 registrations_.erase(registration_iterator); | |
124 break; | |
125 case Registration::STATE_REGISTERING: | |
126 // Update state, NotifyRegistrationFinished will take care of actually | |
127 // unregistering. | |
128 registration_iterator->second.state = | |
129 Registration::STATE_SHOULD_UNREGISTER_AND_DELETE; | |
130 break; | |
131 case Registration::STATE_SHOULD_UNREGISTER_AND_DELETE: | |
132 // Should not happen. | |
133 NOTREACHED(); | |
134 break; | |
135 } | |
136 } | |
137 | |
138 void GeofencingService::SetProviderForTests( | |
139 scoped_ptr<GeofencingProvider> provider) { | |
140 DCHECK(!provider_.get()); | |
141 provider_ = provider.Pass(); | |
142 } | |
143 | |
144 int GeofencingService::RegistrationCountForTests() { | |
145 return registrations_.size(); | |
146 } | |
147 | |
148 bool GeofencingService::EnsureProvider() { | |
149 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
150 | |
151 if (!provider_) { | |
152 // TODO(mek): Create platform specific provider. | |
153 return false; | |
154 } | |
155 return true; | |
156 } | |
157 | |
158 int64 GeofencingService::GetNextId() { | |
159 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
160 | |
161 return next_registration_id_++; | |
162 } | |
163 | |
164 void GeofencingService::NotifyRegistrationFinished( | |
165 int64 geofencing_registration_id, | |
166 GeofencingStatus status) { | |
167 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
168 | |
169 RegistrationsMap::iterator registration_iterator = | |
170 registrations_.find(geofencing_registration_id); | |
171 DCHECK(registration_iterator != registrations_.end()); | |
172 DCHECK(registration_iterator->second.state == | |
173 Registration::STATE_REGISTERING || | |
174 registration_iterator->second.state == | |
175 Registration::STATE_SHOULD_UNREGISTER_AND_DELETE); | |
176 | |
177 if (registration_iterator->second.state == | |
178 Registration::STATE_SHOULD_UNREGISTER_AND_DELETE) { | |
179 // Don't call delegate, but unregister with provider if registration was | |
180 // succesfull. | |
181 if (status == GEOFENCING_STATUS_OK) { | |
182 provider_->UnregisterRegion(geofencing_registration_id); | |
183 } | |
184 registrations_.erase(registration_iterator); | |
185 return; | |
186 } | |
187 | |
188 // Normal case, mark as registered and call delegate. | |
189 registration_iterator->second.state = Registration::STATE_REGISTERED; | |
190 registration_iterator->second.delegate->RegistrationFinished( | |
191 geofencing_registration_id, status); | |
192 | |
193 if (status != GEOFENCING_STATUS_OK) { | |
194 // Registration failed, remove from our book-keeping. | |
195 registrations_.erase(registration_iterator); | |
196 } | |
197 } | |
198 | |
199 } // namespace content | |
OLD | NEW |