| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2010 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/geolocation/geolocation_provider.h" |  | 
| 6 |  | 
| 7 #include "base/singleton.h" |  | 
| 8 #include "base/threading/thread_restrictions.h" |  | 
| 9 #include "content/browser/geolocation/location_arbitrator.h" |  | 
| 10 |  | 
| 11 // This class is guaranteed to outlive its internal thread, so ref counting |  | 
| 12 // is not required. |  | 
| 13 DISABLE_RUNNABLE_METHOD_REFCOUNT(GeolocationProvider); |  | 
| 14 |  | 
| 15 GeolocationProvider* GeolocationProvider::GetInstance() { |  | 
| 16   return Singleton<GeolocationProvider>::get(); |  | 
| 17 } |  | 
| 18 |  | 
| 19 GeolocationProvider::GeolocationProvider() |  | 
| 20     : base::Thread("Geolocation"), |  | 
| 21       client_loop_(base::MessageLoopProxy::CreateForCurrentThread()), |  | 
| 22       arbitrator_(NULL) { |  | 
| 23 } |  | 
| 24 |  | 
| 25 GeolocationProvider::~GeolocationProvider() { |  | 
| 26   DCHECK(observers_.empty());  // observers must unregister. |  | 
| 27   Stop(); |  | 
| 28   DCHECK(!arbitrator_); |  | 
| 29 } |  | 
| 30 |  | 
| 31 void GeolocationProvider::AddObserver(GeolocationObserver* observer, |  | 
| 32     const GeolocationObserverOptions& update_options) { |  | 
| 33   DCHECK(OnClientThread()); |  | 
| 34   observers_[observer] = update_options; |  | 
| 35   OnObserversChanged(); |  | 
| 36   if (position_.IsInitialized()) |  | 
| 37     observer->OnLocationUpdate(position_); |  | 
| 38 } |  | 
| 39 |  | 
| 40 bool GeolocationProvider::RemoveObserver(GeolocationObserver* observer) { |  | 
| 41   DCHECK(OnClientThread()); |  | 
| 42   size_t remove = observers_.erase(observer); |  | 
| 43   OnObserversChanged(); |  | 
| 44   return remove > 0; |  | 
| 45 } |  | 
| 46 |  | 
| 47 void GeolocationProvider::OnObserversChanged() { |  | 
| 48   DCHECK(OnClientThread()); |  | 
| 49   Task* task = NULL; |  | 
| 50   if (observers_.empty()) { |  | 
| 51     DCHECK(IsRunning()); |  | 
| 52     task = NewRunnableMethod(this, &GeolocationProvider::StopProviders); |  | 
| 53   } else { |  | 
| 54     if (!IsRunning()) { |  | 
| 55       Start(); |  | 
| 56       if (HasPermissionBeenGranted()) |  | 
| 57         InformProvidersPermissionGranted(most_recent_authorized_frame_); |  | 
| 58     } |  | 
| 59     // The high accuracy requirement may have changed. |  | 
| 60     task = NewRunnableMethod( |  | 
| 61         this, |  | 
| 62         &GeolocationProvider::StartProviders, |  | 
| 63         GeolocationObserverOptions::Collapse(observers_)); |  | 
| 64   } |  | 
| 65   message_loop()->PostTask(FROM_HERE, task); |  | 
| 66 } |  | 
| 67 |  | 
| 68 void GeolocationProvider::NotifyObservers(const Geoposition& position) { |  | 
| 69   DCHECK(OnClientThread()); |  | 
| 70   DCHECK(position.IsInitialized()); |  | 
| 71   position_ = position; |  | 
| 72   ObserverMap::const_iterator it = observers_.begin(); |  | 
| 73   while (it != observers_.end()) { |  | 
| 74     // Advance iterator before callback to guard against synchronous unregister. |  | 
| 75     GeolocationObserver* observer = it->first; |  | 
| 76     ++it; |  | 
| 77     observer->OnLocationUpdate(position_); |  | 
| 78   } |  | 
| 79 } |  | 
| 80 |  | 
| 81 void GeolocationProvider::StartProviders( |  | 
| 82     const GeolocationObserverOptions& options) { |  | 
| 83   DCHECK(OnGeolocationThread()); |  | 
| 84   DCHECK(arbitrator_); |  | 
| 85   arbitrator_->StartProviders(options); |  | 
| 86 } |  | 
| 87 |  | 
| 88 void GeolocationProvider::StopProviders() { |  | 
| 89   DCHECK(OnGeolocationThread()); |  | 
| 90   DCHECK(arbitrator_); |  | 
| 91   arbitrator_->StopProviders(); |  | 
| 92 } |  | 
| 93 |  | 
| 94 void GeolocationProvider::OnPermissionGranted(const GURL& requesting_frame) { |  | 
| 95   DCHECK(OnClientThread()); |  | 
| 96   most_recent_authorized_frame_ = requesting_frame; |  | 
| 97   if (IsRunning()) |  | 
| 98     InformProvidersPermissionGranted(requesting_frame); |  | 
| 99 } |  | 
| 100 |  | 
| 101 void GeolocationProvider::InformProvidersPermissionGranted( |  | 
| 102     const GURL& requesting_frame) { |  | 
| 103   DCHECK(IsRunning()); |  | 
| 104   DCHECK(requesting_frame.is_valid()); |  | 
| 105   if (!OnGeolocationThread()) { |  | 
| 106     Task* task = NewRunnableMethod( |  | 
| 107         this, |  | 
| 108         &GeolocationProvider::InformProvidersPermissionGranted, |  | 
| 109         requesting_frame); |  | 
| 110     message_loop()->PostTask(FROM_HERE, task); |  | 
| 111     return; |  | 
| 112   } |  | 
| 113   DCHECK(OnGeolocationThread()); |  | 
| 114   DCHECK(arbitrator_); |  | 
| 115   arbitrator_->OnPermissionGranted(requesting_frame); |  | 
| 116 } |  | 
| 117 |  | 
| 118 void GeolocationProvider::Init() { |  | 
| 119   DCHECK(OnGeolocationThread()); |  | 
| 120   DCHECK(!arbitrator_); |  | 
| 121   arbitrator_ = GeolocationArbitrator::Create(this); |  | 
| 122 } |  | 
| 123 |  | 
| 124 void GeolocationProvider::CleanUp() { |  | 
| 125   DCHECK(OnGeolocationThread()); |  | 
| 126   delete arbitrator_; |  | 
| 127   arbitrator_ = NULL; |  | 
| 128 } |  | 
| 129 |  | 
| 130 void GeolocationProvider::OnLocationUpdate(const Geoposition& position) { |  | 
| 131   DCHECK(OnGeolocationThread()); |  | 
| 132   Task* task = NewRunnableMethod(this, |  | 
| 133                                  &GeolocationProvider::NotifyObservers, |  | 
| 134                                  position); |  | 
| 135   client_loop_->PostTask(FROM_HERE, task); |  | 
| 136 } |  | 
| 137 |  | 
| 138 bool GeolocationProvider::HasPermissionBeenGranted() const { |  | 
| 139   DCHECK(OnClientThread()); |  | 
| 140   return most_recent_authorized_frame_.is_valid(); |  | 
| 141 } |  | 
| 142 |  | 
| 143 bool GeolocationProvider::OnClientThread() const { |  | 
| 144   return client_loop_->BelongsToCurrentThread(); |  | 
| 145 } |  | 
| 146 |  | 
| 147 bool GeolocationProvider::OnGeolocationThread() const { |  | 
| 148   return MessageLoop::current() == message_loop(); |  | 
| 149 } |  | 
| OLD | NEW | 
|---|