| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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/geolocation/location_arbitrator.h" | 5 #include "chrome/browser/geolocation/location_arbitrator.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/non_thread_safe.h" | 10 #include "base/non_thread_safe.h" |
| 11 #include "base/ref_counted.h" | 11 #include "base/ref_counted.h" |
| 12 #include "base/scoped_ptr.h" | 12 #include "base/scoped_ptr.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "chrome/browser/net/url_request_context_getter.h" | 14 #include "chrome/browser/net/url_request_context_getter.h" |
| 15 #include "chrome/browser/geolocation/access_token_store.h" | 15 #include "chrome/browser/geolocation/access_token_store.h" |
| 16 #include "chrome/browser/geolocation/location_provider.h" | 16 #include "chrome/browser/geolocation/location_provider.h" |
| 17 #include "chrome/browser/profile.h" |
| 17 #include "chrome/common/geoposition.h" | 18 #include "chrome/common/geoposition.h" |
| 18 #include "googleurl/src/gurl.h" | 19 #include "googleurl/src/gurl.h" |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 const char* kDefaultNetworkProviderUrl = "https://www.google.com/loc/json"; | 22 const char* kDefaultNetworkProviderUrl = "https://www.google.com/loc/json"; |
| 23 bool g_use_mock_provider = false; |
| 24 static GeolocationArbitrator* g_instance_ = NULL; |
| 22 } // namespace | 25 } // namespace |
| 23 | 26 |
| 24 class GeolocationArbitratorImpl | 27 class GeolocationArbitratorImpl |
| 25 : public GeolocationArbitrator, | 28 : public GeolocationArbitrator, |
| 26 public LocationProviderBase::ListenerInterface, | 29 public LocationProviderBase::ListenerInterface, |
| 27 public NonThreadSafe { | 30 public NonThreadSafe { |
| 28 public: | 31 public: |
| 29 GeolocationArbitratorImpl(AccessTokenStore* access_token_store, | 32 GeolocationArbitratorImpl(AccessTokenStore* access_token_store, |
| 30 URLRequestContextGetter* context_getter); | 33 URLRequestContextGetter* context_getter); |
| 31 virtual ~GeolocationArbitratorImpl(); | 34 virtual ~GeolocationArbitratorImpl(); |
| 32 | 35 |
| 33 // GeolocationArbitrator | 36 // GeolocationArbitrator |
| 34 virtual void AddObserver(GeolocationArbitrator::Delegate* delegate, | 37 virtual void AddObserver(GeolocationArbitrator::Delegate* delegate, |
| 35 const UpdateOptions& update_options); | 38 const UpdateOptions& update_options); |
| 36 virtual bool RemoveObserver(GeolocationArbitrator::Delegate* delegate); | 39 virtual bool RemoveObserver(GeolocationArbitrator::Delegate* delegate); |
| 37 virtual void SetUseMockProvider(bool use_mock); | |
| 38 | 40 |
| 39 // ListenerInterface | 41 // ListenerInterface |
| 40 virtual void LocationUpdateAvailable(LocationProviderBase* provider); | 42 virtual void LocationUpdateAvailable(LocationProviderBase* provider); |
| 41 virtual void MovementDetected(LocationProviderBase* provider); | 43 virtual void MovementDetected(LocationProviderBase* provider); |
| 42 | 44 |
| 43 void OnAccessTokenStoresLoaded( | 45 void OnAccessTokenStoresLoaded( |
| 44 AccessTokenStore::AccessTokenSet access_token_store); | 46 AccessTokenStore::AccessTokenSet access_token_store); |
| 45 | 47 |
| 46 private: | 48 private: |
| 47 void CreateProviders(); | 49 void CreateProviders(); |
| 48 bool HasHighAccuracyObserver(); | 50 bool HasHighAccuracyObserver(); |
| 49 | 51 |
| 50 scoped_refptr<AccessTokenStore> access_token_store_; | 52 scoped_refptr<AccessTokenStore> access_token_store_; |
| 51 scoped_refptr<URLRequestContextGetter> context_getter_; | 53 scoped_refptr<URLRequestContextGetter> context_getter_; |
| 52 | 54 |
| 53 const GURL default_url_; | 55 const GURL default_url_; |
| 54 scoped_ptr<LocationProviderBase> provider_; | 56 scoped_ptr<LocationProviderBase> provider_; |
| 55 | 57 |
| 56 typedef std::map<GeolocationArbitrator::Delegate*, UpdateOptions> DelegateMap; | 58 typedef std::map<GeolocationArbitrator::Delegate*, UpdateOptions> DelegateMap; |
| 57 DelegateMap observers_; | 59 DelegateMap observers_; |
| 58 | 60 |
| 59 // The current best estimate of our position. | 61 // The current best estimate of our position. |
| 60 Geoposition position_; | 62 Geoposition position_; |
| 61 | 63 |
| 62 CancelableRequestConsumer request_consumer_; | 64 CancelableRequestConsumer request_consumer_; |
| 63 bool use_mock_; | |
| 64 }; | 65 }; |
| 65 | 66 |
| 66 GeolocationArbitratorImpl::GeolocationArbitratorImpl( | 67 GeolocationArbitratorImpl::GeolocationArbitratorImpl( |
| 67 AccessTokenStore* access_token_store, | 68 AccessTokenStore* access_token_store, |
| 68 URLRequestContextGetter* context_getter) | 69 URLRequestContextGetter* context_getter) |
| 69 : access_token_store_(access_token_store), | 70 : access_token_store_(access_token_store), |
| 70 context_getter_(context_getter), | 71 context_getter_(context_getter), |
| 71 default_url_(kDefaultNetworkProviderUrl), | 72 default_url_(kDefaultNetworkProviderUrl) { |
| 72 use_mock_(false) { | |
| 73 DCHECK(default_url_.is_valid()); | 73 DCHECK(default_url_.is_valid()); |
| 74 DCHECK(NULL == g_instance_); |
| 75 g_instance_ = this; |
| 74 } | 76 } |
| 75 | 77 |
| 76 GeolocationArbitratorImpl::~GeolocationArbitratorImpl() { | 78 GeolocationArbitratorImpl::~GeolocationArbitratorImpl() { |
| 77 DCHECK(CalledOnValidThread()); | 79 DCHECK(CalledOnValidThread()); |
| 78 DCHECK(observers_.empty()) << "Not all observers have unregistered"; | 80 DCHECK(observers_.empty()) << "Not all observers have unregistered"; |
| 81 DCHECK(this == g_instance_); |
| 82 g_instance_ = NULL; |
| 79 } | 83 } |
| 80 | 84 |
| 81 void GeolocationArbitratorImpl::AddObserver( | 85 void GeolocationArbitratorImpl::AddObserver( |
| 82 GeolocationArbitrator::Delegate* delegate, | 86 GeolocationArbitrator::Delegate* delegate, |
| 83 const UpdateOptions& update_options) { | 87 const UpdateOptions& update_options) { |
| 84 DCHECK(CalledOnValidThread()); | 88 DCHECK(CalledOnValidThread()); |
| 85 observers_[delegate] = update_options; | 89 observers_[delegate] = update_options; |
| 86 if (provider_ == NULL) { | 90 if (provider_ == NULL) { |
| 87 CreateProviders(); | 91 CreateProviders(); |
| 88 } else if (position_.IsInitialized()) { | 92 } else if (position_.IsInitialized()) { |
| 89 delegate->OnLocationUpdate(position_); | 93 delegate->OnLocationUpdate(position_); |
| 90 } | 94 } |
| 91 } | 95 } |
| 92 | 96 |
| 93 bool GeolocationArbitratorImpl::RemoveObserver( | 97 bool GeolocationArbitratorImpl::RemoveObserver( |
| 94 GeolocationArbitrator::Delegate* delegate) { | 98 GeolocationArbitrator::Delegate* delegate) { |
| 95 DCHECK(CalledOnValidThread()); | 99 DCHECK(CalledOnValidThread()); |
| 96 size_t remove = observers_.erase(delegate); | 100 size_t remove = observers_.erase(delegate); |
| 97 if (observers_.empty() && provider_ != NULL) { | 101 if (observers_.empty() && provider_ != NULL) { |
| 98 // TODO(joth): Delayed callback to linger before destroying the provider. | 102 // TODO(joth): Delayed callback to linger before destroying the provider. |
| 99 provider_->UnregisterListener(this); | 103 provider_->UnregisterListener(this); |
| 100 provider_.reset(); | 104 provider_.reset(); |
| 101 } | 105 } |
| 102 return remove > 0; | 106 return remove > 0; |
| 103 } | 107 } |
| 104 | 108 |
| 105 void GeolocationArbitratorImpl::SetUseMockProvider(bool use_mock) { | |
| 106 DCHECK(CalledOnValidThread()); | |
| 107 DCHECK(provider_ == NULL); | |
| 108 use_mock_ = use_mock; | |
| 109 } | |
| 110 | |
| 111 void GeolocationArbitratorImpl::LocationUpdateAvailable( | 109 void GeolocationArbitratorImpl::LocationUpdateAvailable( |
| 112 LocationProviderBase* provider) { | 110 LocationProviderBase* provider) { |
| 113 DCHECK(CalledOnValidThread()); | 111 DCHECK(CalledOnValidThread()); |
| 114 DCHECK(provider); | 112 DCHECK(provider); |
| 115 provider->GetPosition(&position_); | 113 provider->GetPosition(&position_); |
| 116 DCHECK(position_.IsInitialized()); | 114 DCHECK(position_.IsInitialized()); |
| 117 // TODO(joth): Arbitrate. | 115 // TODO(joth): Arbitrate. |
| 118 DelegateMap::const_iterator it = observers_.begin(); | 116 DelegateMap::const_iterator it = observers_.begin(); |
| 119 while (it != observers_.end()) { | 117 while (it != observers_.end()) { |
| 120 // Advance iterator before callback to guard against synchronous deregister. | 118 // Advance iterator before callback to guard against synchronous deregister. |
| 121 Delegate* delegate = it->first; | 119 Delegate* delegate = it->first; |
| 122 ++it; | 120 ++it; |
| 123 delegate->OnLocationUpdate(position_); | 121 delegate->OnLocationUpdate(position_); |
| 124 } | 122 } |
| 125 } | 123 } |
| 126 | 124 |
| 127 void GeolocationArbitratorImpl::MovementDetected( | 125 void GeolocationArbitratorImpl::MovementDetected( |
| 128 LocationProviderBase* provider) { | 126 LocationProviderBase* provider) { |
| 129 DCHECK(CalledOnValidThread()); | 127 DCHECK(CalledOnValidThread()); |
| 130 } | 128 } |
| 131 | 129 |
| 132 void GeolocationArbitratorImpl::OnAccessTokenStoresLoaded( | 130 void GeolocationArbitratorImpl::OnAccessTokenStoresLoaded( |
| 133 AccessTokenStore::AccessTokenSet access_token_set) { | 131 AccessTokenStore::AccessTokenSet access_token_set) { |
| 134 DCHECK(provider_ == NULL) | 132 DCHECK(provider_ == NULL) |
| 135 << "OnAccessTokenStoresLoaded : has existing location " | 133 << "OnAccessTokenStoresLoaded : has existing location " |
| 136 << "provider. Race condition caused repeat load of tokens?"; | 134 << "provider. Race condition caused repeat load of tokens?"; |
| 137 if (use_mock_) { | 135 if (g_use_mock_provider) { |
| 138 provider_.reset(NewMockLocationProvider()); | 136 provider_.reset(NewMockLocationProvider()); |
| 139 } else { | 137 } else { |
| 140 // TODO(joth): Once we have arbitration implementation, iterate the whole | 138 // TODO(joth): Once we have arbitration implementation, iterate the whole |
| 141 // set rather than cherry-pick our defaul url. | 139 // set rather than cherry-pick our defaul url. |
| 142 const AccessTokenStore::AccessTokenSet::const_iterator token = | 140 const AccessTokenStore::AccessTokenSet::const_iterator token = |
| 143 access_token_set.find(default_url_); | 141 access_token_set.find(default_url_); |
| 144 // TODO(joth): Follow up with GLS folks if they have a plan for replacing | 142 // TODO(joth): Follow up with GLS folks if they have a plan for replacing |
| 145 // the hostname field. Sending chromium.org is a stop-gap. | 143 // the hostname field. Sending chromium.org is a stop-gap. |
| 146 provider_.reset(NewNetworkLocationProvider( | 144 provider_.reset(NewNetworkLocationProvider( |
| 147 access_token_store_.get(), context_getter_.get(), default_url_, | 145 access_token_store_.get(), context_getter_.get(), default_url_, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 171 DCHECK(CalledOnValidThread()); | 169 DCHECK(CalledOnValidThread()); |
| 172 for (DelegateMap::const_iterator it = observers_.begin(); | 170 for (DelegateMap::const_iterator it = observers_.begin(); |
| 173 it != observers_.end(); ++it) { | 171 it != observers_.end(); ++it) { |
| 174 if (it->second.use_high_accuracy) | 172 if (it->second.use_high_accuracy) |
| 175 return true; | 173 return true; |
| 176 } | 174 } |
| 177 return false; | 175 return false; |
| 178 } | 176 } |
| 179 | 177 |
| 180 GeolocationArbitrator* GeolocationArbitrator::Create( | 178 GeolocationArbitrator* GeolocationArbitrator::Create( |
| 181 URLRequestContextGetter* context_getter) { | |
| 182 return new GeolocationArbitratorImpl(NewChromePrefsAccessTokenStore(), | |
| 183 context_getter); | |
| 184 } | |
| 185 | |
| 186 GeolocationArbitrator* GeolocationArbitrator::Create( | |
| 187 AccessTokenStore* access_token_store, | 179 AccessTokenStore* access_token_store, |
| 188 URLRequestContextGetter* context_getter) { | 180 URLRequestContextGetter* context_getter) { |
| 181 DCHECK(!g_instance_); |
| 189 return new GeolocationArbitratorImpl(access_token_store, | 182 return new GeolocationArbitratorImpl(access_token_store, |
| 190 context_getter); | 183 context_getter); |
| 191 } | 184 } |
| 192 | 185 |
| 186 GeolocationArbitrator* GeolocationArbitrator::GetInstance() { |
| 187 if (!g_instance_) { |
| 188 // Construct the arbitrator using default token store and url context. We |
| 189 // get the url context getter from the default profile as it's not |
| 190 // particularly important which profile it is attached to: the network |
| 191 // request implementation disables cookies anyhow. |
| 192 Create(NewChromePrefsAccessTokenStore(), |
| 193 Profile::GetDefaultRequestContext()); |
| 194 DCHECK(g_instance_); |
| 195 } |
| 196 return g_instance_; |
| 197 } |
| 198 |
| 199 void GeolocationArbitrator::SetUseMockProvider(bool use_mock) { |
| 200 g_use_mock_provider = use_mock; |
| 201 } |
| 202 |
| 203 GeolocationArbitrator::GeolocationArbitrator() { |
| 204 } |
| 205 |
| 193 GeolocationArbitrator::~GeolocationArbitrator() { | 206 GeolocationArbitrator::~GeolocationArbitrator() { |
| 194 } | 207 } |
| OLD | NEW |