| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |