Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Side by Side Diff: chrome/browser/extensions/api/location/location_manager.cc

Issue 273523007: Dispatch geolocation IPCs on the UI thread. Aside from simplifying the code to avoid a lot of threa… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: sync Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/location/location_manager.h" 5 #include "chrome/browser/extensions/api/location/location_manager.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 133
134 base::Time last_update_time_; 134 base::Time last_update_time_;
135 const double time_between_updates_ms_; 135 const double time_between_updates_ms_;
136 136
137 DISALLOW_COPY_AND_ASSIGN(TimeBasedUpdatePolicy); 137 DISALLOW_COPY_AND_ASSIGN(TimeBasedUpdatePolicy);
138 }; 138 };
139 139
140 } // namespace updatepolicy 140 } // namespace updatepolicy
141 141
142 // Request created by chrome.location.watchLocation() call. 142 // Request created by chrome.location.watchLocation() call.
143 // Lives in the IO thread, except for the constructor. 143 class LocationRequest : public base::RefCounted<LocationRequest> {
144 class LocationRequest
145 : public base::RefCountedThreadSafe<LocationRequest,
146 BrowserThread::DeleteOnIOThread> {
147 public: 144 public:
148 LocationRequest( 145 LocationRequest(
149 const base::WeakPtr<LocationManager>& location_manager, 146 LocationManager* location_manager,
150 const std::string& extension_id, 147 const std::string& extension_id,
151 const std::string& request_name, 148 const std::string& request_name,
152 const double* distance_update_threshold_meters, 149 const double* distance_update_threshold_meters,
153 const double* time_between_updates_ms); 150 const double* time_between_updates_ms);
154 151
155 // Finishes the necessary setup for this object.
156 // Call this method immediately after taking a strong reference
157 // to this object.
158 //
159 // Ideally, we would do this at construction time, but currently
160 // our refcount starts at zero. BrowserThread::PostTask will take a ref
161 // and potentially release it before we are done, destroying us in the
162 // constructor.
163 void Initialize();
164
165 const std::string& request_name() const { return request_name_; } 152 const std::string& request_name() const { return request_name_; }
166 153
167 // Grants permission for using geolocation.
168 static void GrantPermission();
169
170 private: 154 private:
171 friend class base::DeleteHelper<LocationRequest>; 155 friend class base::RefCounted<LocationRequest>;
172 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; 156 ~LocationRequest();
173
174 virtual ~LocationRequest();
175
176 void AddObserverOnIOThread();
177 157
178 void OnLocationUpdate(const content::Geoposition& position); 158 void OnLocationUpdate(const content::Geoposition& position);
179 159
180 // Determines if all policies say to send a position update. 160 // Determines if all policies say to send a position update.
181 // If there are no policies, this always says yes. 161 // If there are no policies, this always says yes.
182 bool ShouldSendUpdate(const content::Geoposition& position); 162 bool ShouldSendUpdate(const content::Geoposition& position);
183 163
184 // Updates the policies on sending a position update. 164 // Updates the policies on sending a position update.
185 void OnPositionReported(const content::Geoposition& position); 165 void OnPositionReported(const content::Geoposition& position);
186 166
187 // Request name. 167 // Request name.
188 const std::string request_name_; 168 const std::string request_name_;
189 169
190 // Id of the owner extension. 170 // Id of the owner extension.
191 const std::string extension_id_; 171 const std::string extension_id_;
192 172
193 // Owning location manager. 173 // Owning location manager.
194 const base::WeakPtr<LocationManager> location_manager_; 174 LocationManager* location_manager_;
195 175
196 // Holds Update Policies. 176 // Holds Update Policies.
197 typedef std::vector<scoped_refptr<updatepolicy::UpdatePolicy> > 177 typedef std::vector<scoped_refptr<updatepolicy::UpdatePolicy> >
198 UpdatePolicyVector; 178 UpdatePolicyVector;
199 UpdatePolicyVector update_policies_; 179 UpdatePolicyVector update_policies_;
200 180
201 content::GeolocationProvider::LocationUpdateCallback callback_; 181 scoped_ptr<content::GeolocationProvider::Subscription>
182 geolocation_subscription_;
202 183
203 DISALLOW_COPY_AND_ASSIGN(LocationRequest); 184 DISALLOW_COPY_AND_ASSIGN(LocationRequest);
204 }; 185 };
205 186
206 LocationRequest::LocationRequest( 187 LocationRequest::LocationRequest(
207 const base::WeakPtr<LocationManager>& location_manager, 188 LocationManager* location_manager,
208 const std::string& extension_id, 189 const std::string& extension_id,
209 const std::string& request_name, 190 const std::string& request_name,
210 const double* distance_update_threshold_meters, 191 const double* distance_update_threshold_meters,
211 const double* time_between_updates_ms) 192 const double* time_between_updates_ms)
212 : request_name_(request_name), 193 : request_name_(request_name),
213 extension_id_(extension_id), 194 extension_id_(extension_id),
214 location_manager_(location_manager) { 195 location_manager_(location_manager) {
215 // TODO(vadimt): use request_info. 196 // TODO(vadimt): use request_info.
216 DCHECK_CURRENTLY_ON(BrowserThread::UI);
217
218 if (time_between_updates_ms) { 197 if (time_between_updates_ms) {
219 update_policies_.push_back( 198 update_policies_.push_back(
220 new updatepolicy::TimeBasedUpdatePolicy( 199 new updatepolicy::TimeBasedUpdatePolicy(
221 *time_between_updates_ms)); 200 *time_between_updates_ms));
222 } 201 }
223 202
224 if (distance_update_threshold_meters) { 203 if (distance_update_threshold_meters) {
225 update_policies_.push_back( 204 update_policies_.push_back(
226 new updatepolicy::DistanceBasedUpdatePolicy( 205 new updatepolicy::DistanceBasedUpdatePolicy(
227 *distance_update_threshold_meters)); 206 *distance_update_threshold_meters));
228 } 207 }
229 }
230
231 void LocationRequest::Initialize() {
232 DCHECK_CURRENTLY_ON(BrowserThread::UI);
233 callback_ = base::Bind(&LocationRequest::OnLocationUpdate,
234 base::Unretained(this));
235
236 BrowserThread::PostTask(
237 BrowserThread::IO,
238 FROM_HERE,
239 base::Bind(&LocationRequest::AddObserverOnIOThread,
240 this));
241 }
242
243 void LocationRequest::GrantPermission() {
244 DCHECK_CURRENTLY_ON(BrowserThread::IO);
245 content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
246 }
247
248 LocationRequest::~LocationRequest() {
249 DCHECK_CURRENTLY_ON(BrowserThread::IO);
250 content::GeolocationProvider::GetInstance()->RemoveLocationUpdateCallback(
251 callback_);
252 }
253
254 void LocationRequest::AddObserverOnIOThread() {
255 DCHECK_CURRENTLY_ON(BrowserThread::IO);
256 208
257 // TODO(vadimt): This can get a location cached by GeolocationProvider, 209 // TODO(vadimt): This can get a location cached by GeolocationProvider,
258 // contrary to the API definition which says that creating a location watch 210 // contrary to the API definition which says that creating a location watch
259 // will get new location. 211 // will get new location.
260 content::GeolocationProvider::GetInstance()->AddLocationUpdateCallback( 212 geolocation_subscription_ = content::GeolocationProvider::GetInstance()->
261 callback_, true); 213 AddLocationUpdateCallback(
214 base::Bind(&LocationRequest::OnLocationUpdate,
215 base::Unretained(this)),
216 true);
217 }
218
219 LocationRequest::~LocationRequest() {
262 } 220 }
263 221
264 void LocationRequest::OnLocationUpdate(const content::Geoposition& position) { 222 void LocationRequest::OnLocationUpdate(const content::Geoposition& position) {
265 DCHECK_CURRENTLY_ON(BrowserThread::IO);
266 if (ShouldSendUpdate(position)) { 223 if (ShouldSendUpdate(position)) {
267 OnPositionReported(position); 224 OnPositionReported(position);
268 BrowserThread::PostTask( 225 location_manager_->SendLocationUpdate(
269 BrowserThread::UI, 226 extension_id_, request_name_, position);
270 FROM_HERE,
271 base::Bind(&LocationManager::SendLocationUpdate,
272 location_manager_,
273 extension_id_,
274 request_name_,
275 position));
276 } 227 }
277 } 228 }
278 229
279 bool LocationRequest::ShouldSendUpdate(const content::Geoposition& position) { 230 bool LocationRequest::ShouldSendUpdate(const content::Geoposition& position) {
280 DCHECK_CURRENTLY_ON(BrowserThread::IO);
281 for (UpdatePolicyVector::iterator it = update_policies_.begin(); 231 for (UpdatePolicyVector::iterator it = update_policies_.begin();
282 it != update_policies_.end(); 232 it != update_policies_.end();
283 ++it) { 233 ++it) {
284 if (!((*it)->ShouldSendUpdate(position))) { 234 if (!((*it)->ShouldSendUpdate(position))) {
285 return false; 235 return false;
286 } 236 }
287 } 237 }
288 return true; 238 return true;
289 } 239 }
290 240
291 void LocationRequest::OnPositionReported(const content::Geoposition& position) { 241 void LocationRequest::OnPositionReported(const content::Geoposition& position) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO);
293 for (UpdatePolicyVector::iterator it = update_policies_.begin(); 242 for (UpdatePolicyVector::iterator it = update_policies_.begin();
294 it != update_policies_.end(); 243 it != update_policies_.end();
295 ++it) { 244 ++it) {
296 (*it)->OnPositionReported(position); 245 (*it)->OnPositionReported(position);
297 } 246 }
298 } 247 }
299 248
300 LocationManager::LocationManager(content::BrowserContext* context) 249 LocationManager::LocationManager(content::BrowserContext* context)
301 : profile_(Profile::FromBrowserContext(context)) { 250 : profile_(Profile::FromBrowserContext(context)) {
302 registrar_.Add(this, 251 registrar_.Add(this,
303 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 252 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
304 content::Source<Profile>(profile_)); 253 content::Source<Profile>(profile_));
305 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 254 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
306 content::Source<Profile>(profile_)); 255 content::Source<Profile>(profile_));
307 } 256 }
308 257
309 void LocationManager::AddLocationRequest( 258 void LocationManager::AddLocationRequest(
310 const std::string& extension_id, 259 const std::string& extension_id,
311 const std::string& request_name, 260 const std::string& request_name,
312 const double* distance_update_threshold_meters, 261 const double* distance_update_threshold_meters,
313 const double* time_between_updates_ms) { 262 const double* time_between_updates_ms) {
314 DCHECK_CURRENTLY_ON(BrowserThread::UI); 263 DCHECK_CURRENTLY_ON(BrowserThread::UI);
315 // TODO(vadimt): Consider resuming requests after restarting the browser. 264 // TODO(vadimt): Consider resuming requests after restarting the browser.
316 265
317 // Override any old request with the same name. 266 // Override any old request with the same name.
318 RemoveLocationRequest(extension_id, request_name); 267 RemoveLocationRequest(extension_id, request_name);
319 268
320 LocationRequestPointer location_request = 269 LocationRequestPointer location_request =
321 new LocationRequest(AsWeakPtr(), 270 new LocationRequest(this,
322 extension_id, 271 extension_id,
323 request_name, 272 request_name,
324 distance_update_threshold_meters, 273 distance_update_threshold_meters,
325 time_between_updates_ms); 274 time_between_updates_ms);
326 location_request->Initialize();
327 location_requests_.insert( 275 location_requests_.insert(
328 LocationRequestMap::value_type(extension_id, location_request)); 276 LocationRequestMap::value_type(extension_id, location_request));
329 } 277 }
330 278
331 void LocationManager::RemoveLocationRequest(const std::string& extension_id, 279 void LocationManager::RemoveLocationRequest(const std::string& extension_id,
332 const std::string& name) { 280 const std::string& name) {
333 DCHECK_CURRENTLY_ON(BrowserThread::UI); 281 DCHECK_CURRENTLY_ON(BrowserThread::UI);
334 282
335 std::pair<LocationRequestMap::iterator, LocationRequestMap::iterator> 283 std::pair<LocationRequestMap::iterator, LocationRequestMap::iterator>
336 extension_range = location_requests_.equal_range(extension_id); 284 extension_range = location_requests_.equal_range(extension_id);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 DCHECK_CURRENTLY_ON(BrowserThread::UI); 352 DCHECK_CURRENTLY_ON(BrowserThread::UI);
405 353
406 switch (type) { 354 switch (type) {
407 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: { 355 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
408 // Grants permission to use geolocation once an extension with "location" 356 // Grants permission to use geolocation once an extension with "location"
409 // permission is loaded. 357 // permission is loaded.
410 const Extension* extension = 358 const Extension* extension =
411 content::Details<const Extension>(details).ptr(); 359 content::Details<const Extension>(details).ptr();
412 360
413 if (extension->HasAPIPermission(APIPermission::kLocation)) { 361 if (extension->HasAPIPermission(APIPermission::kLocation)) {
414 BrowserThread::PostTask( 362 content::GeolocationProvider::GetInstance()->
415 BrowserThread::IO, 363 UserDidOptIntoLocationServices();
416 FROM_HERE,
417 base::Bind(&LocationRequest::GrantPermission));
418 } 364 }
419 break; 365 break;
420 } 366 }
421 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: { 367 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
422 // Delete all requests from the unloaded extension. 368 // Delete all requests from the unloaded extension.
423 const Extension* extension = 369 const Extension* extension =
424 content::Details<const UnloadedExtensionInfo>(details)->extension; 370 content::Details<const UnloadedExtensionInfo>(details)->extension;
425 location_requests_.erase(extension->id()); 371 location_requests_.erase(extension->id());
426 break; 372 break;
427 } 373 }
(...skipping 11 matching lines...) Expand all
439 LocationManager::GetFactoryInstance() { 385 LocationManager::GetFactoryInstance() {
440 return g_factory.Pointer(); 386 return g_factory.Pointer();
441 } 387 }
442 388
443 // static 389 // static
444 LocationManager* LocationManager::Get(content::BrowserContext* context) { 390 LocationManager* LocationManager::Get(content::BrowserContext* context) {
445 return BrowserContextKeyedAPIFactory<LocationManager>::Get(context); 391 return BrowserContextKeyedAPIFactory<LocationManager>::Get(context);
446 } 392 }
447 393
448 } // namespace extensions 394 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698