location_arbitrator.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright (c) 2012 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. #include "services/device/geolocation/location_arbitrator.h"
  5. #include <map>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/bind.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/memory/ptr_util.h"
  11. #include "build/build_config.h"
  12. #include "services/device/geolocation/network_location_provider.h"
  13. #include "services/device/geolocation/wifi_polling_policy.h"
  14. #include "services/device/public/cpp/geolocation/geoposition.h"
  15. #include "services/network/public/cpp/shared_url_loader_factory.h"
  16. namespace device {
  17. // To avoid oscillations, set this to twice the expected update interval of a
  18. // a GPS-type location provider (in case it misses a beat) plus a little.
  19. const base::TimeDelta LocationArbitrator::kFixStaleTimeoutTimeDelta =
  20. base::Seconds(11);
  21. LocationArbitrator::LocationArbitrator(
  22. const CustomLocationProviderCallback& custom_location_provider_getter,
  23. GeolocationManager* geolocation_manager,
  24. const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
  25. const scoped_refptr<network::SharedURLLoaderFactory>& url_loader_factory,
  26. const std::string& api_key,
  27. std::unique_ptr<PositionCache> position_cache)
  28. : custom_location_provider_getter_(custom_location_provider_getter),
  29. geolocation_manager_(geolocation_manager),
  30. main_task_runner_(main_task_runner),
  31. url_loader_factory_(url_loader_factory),
  32. api_key_(api_key),
  33. position_provider_(nullptr),
  34. is_permission_granted_(false),
  35. position_cache_(std::move(position_cache)),
  36. is_running_(false) {}
  37. LocationArbitrator::~LocationArbitrator() {
  38. // Release the global wifi polling policy state.
  39. WifiPollingPolicy::Shutdown();
  40. }
  41. bool LocationArbitrator::HasPermissionBeenGrantedForTest() const {
  42. return is_permission_granted_;
  43. }
  44. void LocationArbitrator::OnPermissionGranted() {
  45. is_permission_granted_ = true;
  46. for (const auto& provider : providers_)
  47. provider->OnPermissionGranted();
  48. }
  49. void LocationArbitrator::StartProvider(bool enable_high_accuracy) {
  50. is_running_ = true;
  51. enable_high_accuracy_ = enable_high_accuracy;
  52. if (providers_.empty()) {
  53. RegisterProviders();
  54. }
  55. DoStartProviders();
  56. }
  57. void LocationArbitrator::DoStartProviders() {
  58. if (providers_.empty()) {
  59. // If no providers are available, we report an error to avoid
  60. // callers waiting indefinitely for a reply.
  61. mojom::Geoposition position;
  62. position.error_code = mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
  63. arbitrator_update_callback_.Run(this, position);
  64. return;
  65. }
  66. for (const auto& provider : providers_) {
  67. provider->StartProvider(enable_high_accuracy_);
  68. }
  69. }
  70. void LocationArbitrator::StopProvider() {
  71. // Reset the reference location state (provider+position)
  72. // so that future starts use fresh locations from
  73. // the newly constructed providers.
  74. position_provider_ = nullptr;
  75. position_ = mojom::Geoposition();
  76. providers_.clear();
  77. is_running_ = false;
  78. }
  79. void LocationArbitrator::RegisterProvider(
  80. std::unique_ptr<LocationProvider> provider) {
  81. if (!provider)
  82. return;
  83. provider->SetUpdateCallback(base::BindRepeating(
  84. &LocationArbitrator::OnLocationUpdate, base::Unretained(this)));
  85. if (is_permission_granted_)
  86. provider->OnPermissionGranted();
  87. providers_.push_back(std::move(provider));
  88. }
  89. void LocationArbitrator::RegisterProviders() {
  90. if (custom_location_provider_getter_) {
  91. auto custom_provider = custom_location_provider_getter_.Run();
  92. if (custom_provider) {
  93. RegisterProvider(std::move(custom_provider));
  94. return;
  95. }
  96. }
  97. auto system_provider = NewSystemLocationProvider();
  98. if (system_provider) {
  99. RegisterProvider(std::move(system_provider));
  100. return;
  101. }
  102. if (url_loader_factory_)
  103. RegisterProvider(NewNetworkLocationProvider(url_loader_factory_, api_key_));
  104. }
  105. void LocationArbitrator::OnLocationUpdate(
  106. const LocationProvider* provider,
  107. const mojom::Geoposition& new_position) {
  108. DCHECK(ValidateGeoposition(new_position) ||
  109. new_position.error_code != mojom::Geoposition::ErrorCode::NONE);
  110. if (!IsNewPositionBetter(position_, new_position,
  111. provider == position_provider_))
  112. return;
  113. position_provider_ = provider;
  114. position_ = new_position;
  115. arbitrator_update_callback_.Run(this, position_);
  116. }
  117. const mojom::Geoposition& LocationArbitrator::GetPosition() {
  118. return position_;
  119. }
  120. void LocationArbitrator::SetUpdateCallback(
  121. const LocationProviderUpdateCallback& callback) {
  122. DCHECK(!callback.is_null());
  123. arbitrator_update_callback_ = callback;
  124. }
  125. std::unique_ptr<LocationProvider>
  126. LocationArbitrator::NewNetworkLocationProvider(
  127. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
  128. const std::string& api_key) {
  129. DCHECK(url_loader_factory);
  130. #if BUILDFLAG(IS_ANDROID)
  131. // Android uses its own SystemLocationProvider.
  132. return nullptr;
  133. #else
  134. return std::make_unique<NetworkLocationProvider>(
  135. std::move(url_loader_factory), geolocation_manager_, main_task_runner_,
  136. api_key, position_cache_.get());
  137. #endif
  138. }
  139. std::unique_ptr<LocationProvider>
  140. LocationArbitrator::NewSystemLocationProvider() {
  141. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
  142. return nullptr;
  143. #else
  144. return device::NewSystemLocationProvider(main_task_runner_,
  145. geolocation_manager_);
  146. #endif
  147. }
  148. base::Time LocationArbitrator::GetTimeNow() const {
  149. return base::Time::Now();
  150. }
  151. bool LocationArbitrator::IsNewPositionBetter(
  152. const mojom::Geoposition& old_position,
  153. const mojom::Geoposition& new_position,
  154. bool from_same_provider) const {
  155. // Updates location_info if it's better than what we currently have,
  156. // or if it's a newer update from the same provider.
  157. if (!ValidateGeoposition(old_position)) {
  158. // Older location wasn't locked.
  159. return true;
  160. }
  161. if (ValidateGeoposition(new_position)) {
  162. // New location is locked, let's check if it's any better.
  163. if (old_position.accuracy >= new_position.accuracy) {
  164. // Accuracy is better.
  165. return true;
  166. } else if (from_same_provider) {
  167. // Same provider, fresher location.
  168. return true;
  169. } else if (GetTimeNow() - old_position.timestamp >
  170. kFixStaleTimeoutTimeDelta) {
  171. // Existing fix is stale.
  172. return true;
  173. }
  174. }
  175. return false;
  176. }
  177. } // namespace device