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

Unified Diff: content/browser/geolocation/geolocation_provider_impl.cc

Issue 2188933002: Revert of Reland: Geolocation: move from content/browser to device/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/geolocation/geolocation_provider_impl.cc
diff --git a/content/browser/geolocation/geolocation_provider_impl.cc b/content/browser/geolocation/geolocation_provider_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1f263976a914460ccb26e73750177388c0b7f05e
--- /dev/null
+++ b/content/browser/geolocation/geolocation_provider_impl.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/geolocation/geolocation_provider_impl.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/singleton.h"
+#include "base/single_thread_task_runner.h"
+#include "content/browser/geolocation/location_arbitrator_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/geolocation_delegate.h"
+
+namespace content {
+
+namespace {
+base::LazyInstance<std::unique_ptr<GeolocationDelegate>>::Leaky g_delegate =
+ LAZY_INSTANCE_INITIALIZER;
+} // anonymous namespace
+
+// static
+GeolocationProvider* GeolocationProvider::GetInstance() {
+ return GeolocationProviderImpl::GetInstance();
+}
+
+// static
+void GeolocationProvider::SetGeolocationDelegate(
+ GeolocationDelegate* delegate) {
+ DCHECK(!g_delegate.Get());
+ g_delegate.Get().reset(delegate);
+}
+
+std::unique_ptr<GeolocationProvider::Subscription>
+GeolocationProviderImpl::AddLocationUpdateCallback(
+ const LocationUpdateCallback& callback,
+ bool enable_high_accuracy) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ std::unique_ptr<GeolocationProvider::Subscription> subscription;
+ if (enable_high_accuracy) {
+ subscription = high_accuracy_callbacks_.Add(callback);
+ } else {
+ subscription = low_accuracy_callbacks_.Add(callback);
+ }
+
+ OnClientsChanged();
+ if (position_.Validate() ||
+ position_.error_code != Geoposition::ERROR_CODE_NONE) {
+ callback.Run(position_);
+ }
+
+ return subscription;
+}
+
+void GeolocationProviderImpl::UserDidOptIntoLocationServices() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ bool was_permission_granted = user_did_opt_into_location_services_;
+ user_did_opt_into_location_services_ = true;
+ if (IsRunning() && !was_permission_granted)
+ InformProvidersPermissionGranted();
+}
+
+void GeolocationProviderImpl::OverrideLocationForTesting(
+ const Geoposition& position) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ignore_location_updates_ = true;
+ NotifyClients(position);
+}
+
+void GeolocationProviderImpl::OnLocationUpdate(const Geoposition& position) {
+ DCHECK(OnGeolocationThread());
+ // Will be true only in testing.
+ if (ignore_location_updates_)
+ return;
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GeolocationProviderImpl::NotifyClients,
+ base::Unretained(this), position));
+}
+
+// static
+GeolocationProviderImpl* GeolocationProviderImpl::GetInstance() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return base::Singleton<GeolocationProviderImpl>::get();
+}
+
+GeolocationProviderImpl::GeolocationProviderImpl()
+ : base::Thread("Geolocation"),
+ user_did_opt_into_location_services_(false),
+ ignore_location_updates_(false) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ high_accuracy_callbacks_.set_removal_callback(
+ base::Bind(&GeolocationProviderImpl::OnClientsChanged,
+ base::Unretained(this)));
+ low_accuracy_callbacks_.set_removal_callback(
+ base::Bind(&GeolocationProviderImpl::OnClientsChanged,
+ base::Unretained(this)));
+}
+
+GeolocationProviderImpl::~GeolocationProviderImpl() {
+ Stop();
+ DCHECK(!arbitrator_);
+}
+
+bool GeolocationProviderImpl::OnGeolocationThread() const {
+ return task_runner()->BelongsToCurrentThread();
+}
+
+void GeolocationProviderImpl::OnClientsChanged() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::Closure task;
+ if (high_accuracy_callbacks_.empty() && low_accuracy_callbacks_.empty()) {
+ DCHECK(IsRunning());
+ if (!ignore_location_updates_) {
+ // We have no more observers, so we clear the cached geoposition so that
+ // when the next observer is added we will not provide a stale position.
+ position_ = Geoposition();
+ }
+ task = base::Bind(&GeolocationProviderImpl::StopProviders,
+ base::Unretained(this));
+ } else {
+ if (!IsRunning()) {
+ Start();
+ if (user_did_opt_into_location_services_)
+ InformProvidersPermissionGranted();
+ }
+ // Determine a set of options that satisfies all clients.
+ bool enable_high_accuracy = !high_accuracy_callbacks_.empty();
+
+ // Send the current options to the providers as they may have changed.
+ task = base::Bind(&GeolocationProviderImpl::StartProviders,
+ base::Unretained(this), enable_high_accuracy);
+ }
+
+ task_runner()->PostTask(FROM_HERE, task);
+}
+
+void GeolocationProviderImpl::StopProviders() {
+ DCHECK(OnGeolocationThread());
+ DCHECK(arbitrator_);
+ arbitrator_->StopProviders();
+}
+
+void GeolocationProviderImpl::StartProviders(bool enable_high_accuracy) {
+ DCHECK(OnGeolocationThread());
+ DCHECK(arbitrator_);
+ arbitrator_->StartProviders(enable_high_accuracy);
+}
+
+void GeolocationProviderImpl::InformProvidersPermissionGranted() {
+ DCHECK(IsRunning());
+ if (!OnGeolocationThread()) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&GeolocationProviderImpl::InformProvidersPermissionGranted,
+ base::Unretained(this)));
+ return;
+ }
+ DCHECK(OnGeolocationThread());
+ DCHECK(arbitrator_);
+ arbitrator_->OnPermissionGranted();
+}
+
+void GeolocationProviderImpl::NotifyClients(const Geoposition& position) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(position.Validate() ||
+ position.error_code != Geoposition::ERROR_CODE_NONE);
+ position_ = position;
+ high_accuracy_callbacks_.Notify(position_);
+ low_accuracy_callbacks_.Notify(position_);
+}
+
+void GeolocationProviderImpl::Init() {
+ DCHECK(OnGeolocationThread());
+ DCHECK(!arbitrator_);
+ arbitrator_ = CreateArbitrator();
+}
+
+void GeolocationProviderImpl::CleanUp() {
+ DCHECK(OnGeolocationThread());
+ arbitrator_.reset();
+}
+
+std::unique_ptr<LocationArbitrator>
+GeolocationProviderImpl::CreateArbitrator() {
+ LocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
+ &GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this));
+ // Use the embedder's |g_delegate| or fall back to the default one.
+ if (!g_delegate.Get())
+ g_delegate.Get().reset(new GeolocationDelegate);
+
+ return base::WrapUnique(
+ new LocationArbitratorImpl(callback, g_delegate.Get().get()));
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698