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

Side by Side Diff: content/browser/geolocation/geolocation_provider_impl.cc

Issue 2192683002: Reland 2:Geolocation: move from content/browser to device/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ignore size_t_to_int truncation warning Created 4 years, 4 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 unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "content/browser/geolocation/geolocation_provider_impl.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/lazy_instance.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/memory/singleton.h"
15 #include "base/single_thread_task_runner.h"
16 #include "content/browser/geolocation/location_arbitrator_impl.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/content_browser_client.h"
19 #include "content/public/browser/geolocation_delegate.h"
20
21 namespace content {
22
23 namespace {
24 base::LazyInstance<std::unique_ptr<GeolocationDelegate>>::Leaky g_delegate =
25 LAZY_INSTANCE_INITIALIZER;
26 } // anonymous namespace
27
28 // static
29 GeolocationProvider* GeolocationProvider::GetInstance() {
30 return GeolocationProviderImpl::GetInstance();
31 }
32
33 // static
34 void GeolocationProvider::SetGeolocationDelegate(
35 GeolocationDelegate* delegate) {
36 DCHECK(!g_delegate.Get());
37 g_delegate.Get().reset(delegate);
38 }
39
40 std::unique_ptr<GeolocationProvider::Subscription>
41 GeolocationProviderImpl::AddLocationUpdateCallback(
42 const LocationUpdateCallback& callback,
43 bool enable_high_accuracy) {
44 DCHECK_CURRENTLY_ON(BrowserThread::UI);
45 std::unique_ptr<GeolocationProvider::Subscription> subscription;
46 if (enable_high_accuracy) {
47 subscription = high_accuracy_callbacks_.Add(callback);
48 } else {
49 subscription = low_accuracy_callbacks_.Add(callback);
50 }
51
52 OnClientsChanged();
53 if (position_.Validate() ||
54 position_.error_code != Geoposition::ERROR_CODE_NONE) {
55 callback.Run(position_);
56 }
57
58 return subscription;
59 }
60
61 void GeolocationProviderImpl::UserDidOptIntoLocationServices() {
62 DCHECK_CURRENTLY_ON(BrowserThread::UI);
63 bool was_permission_granted = user_did_opt_into_location_services_;
64 user_did_opt_into_location_services_ = true;
65 if (IsRunning() && !was_permission_granted)
66 InformProvidersPermissionGranted();
67 }
68
69 void GeolocationProviderImpl::OverrideLocationForTesting(
70 const Geoposition& position) {
71 DCHECK_CURRENTLY_ON(BrowserThread::UI);
72 ignore_location_updates_ = true;
73 NotifyClients(position);
74 }
75
76 void GeolocationProviderImpl::OnLocationUpdate(const Geoposition& position) {
77 DCHECK(OnGeolocationThread());
78 // Will be true only in testing.
79 if (ignore_location_updates_)
80 return;
81 BrowserThread::PostTask(BrowserThread::UI,
82 FROM_HERE,
83 base::Bind(&GeolocationProviderImpl::NotifyClients,
84 base::Unretained(this), position));
85 }
86
87 // static
88 GeolocationProviderImpl* GeolocationProviderImpl::GetInstance() {
89 DCHECK_CURRENTLY_ON(BrowserThread::UI);
90 return base::Singleton<GeolocationProviderImpl>::get();
91 }
92
93 GeolocationProviderImpl::GeolocationProviderImpl()
94 : base::Thread("Geolocation"),
95 user_did_opt_into_location_services_(false),
96 ignore_location_updates_(false) {
97 DCHECK_CURRENTLY_ON(BrowserThread::UI);
98 high_accuracy_callbacks_.set_removal_callback(
99 base::Bind(&GeolocationProviderImpl::OnClientsChanged,
100 base::Unretained(this)));
101 low_accuracy_callbacks_.set_removal_callback(
102 base::Bind(&GeolocationProviderImpl::OnClientsChanged,
103 base::Unretained(this)));
104 }
105
106 GeolocationProviderImpl::~GeolocationProviderImpl() {
107 Stop();
108 DCHECK(!arbitrator_);
109 }
110
111 bool GeolocationProviderImpl::OnGeolocationThread() const {
112 return task_runner()->BelongsToCurrentThread();
113 }
114
115 void GeolocationProviderImpl::OnClientsChanged() {
116 DCHECK_CURRENTLY_ON(BrowserThread::UI);
117 base::Closure task;
118 if (high_accuracy_callbacks_.empty() && low_accuracy_callbacks_.empty()) {
119 DCHECK(IsRunning());
120 if (!ignore_location_updates_) {
121 // We have no more observers, so we clear the cached geoposition so that
122 // when the next observer is added we will not provide a stale position.
123 position_ = Geoposition();
124 }
125 task = base::Bind(&GeolocationProviderImpl::StopProviders,
126 base::Unretained(this));
127 } else {
128 if (!IsRunning()) {
129 Start();
130 if (user_did_opt_into_location_services_)
131 InformProvidersPermissionGranted();
132 }
133 // Determine a set of options that satisfies all clients.
134 bool enable_high_accuracy = !high_accuracy_callbacks_.empty();
135
136 // Send the current options to the providers as they may have changed.
137 task = base::Bind(&GeolocationProviderImpl::StartProviders,
138 base::Unretained(this), enable_high_accuracy);
139 }
140
141 task_runner()->PostTask(FROM_HERE, task);
142 }
143
144 void GeolocationProviderImpl::StopProviders() {
145 DCHECK(OnGeolocationThread());
146 DCHECK(arbitrator_);
147 arbitrator_->StopProviders();
148 }
149
150 void GeolocationProviderImpl::StartProviders(bool enable_high_accuracy) {
151 DCHECK(OnGeolocationThread());
152 DCHECK(arbitrator_);
153 arbitrator_->StartProviders(enable_high_accuracy);
154 }
155
156 void GeolocationProviderImpl::InformProvidersPermissionGranted() {
157 DCHECK(IsRunning());
158 if (!OnGeolocationThread()) {
159 task_runner()->PostTask(
160 FROM_HERE,
161 base::Bind(&GeolocationProviderImpl::InformProvidersPermissionGranted,
162 base::Unretained(this)));
163 return;
164 }
165 DCHECK(OnGeolocationThread());
166 DCHECK(arbitrator_);
167 arbitrator_->OnPermissionGranted();
168 }
169
170 void GeolocationProviderImpl::NotifyClients(const Geoposition& position) {
171 DCHECK_CURRENTLY_ON(BrowserThread::UI);
172 DCHECK(position.Validate() ||
173 position.error_code != Geoposition::ERROR_CODE_NONE);
174 position_ = position;
175 high_accuracy_callbacks_.Notify(position_);
176 low_accuracy_callbacks_.Notify(position_);
177 }
178
179 void GeolocationProviderImpl::Init() {
180 DCHECK(OnGeolocationThread());
181 DCHECK(!arbitrator_);
182 arbitrator_ = CreateArbitrator();
183 }
184
185 void GeolocationProviderImpl::CleanUp() {
186 DCHECK(OnGeolocationThread());
187 arbitrator_.reset();
188 }
189
190 std::unique_ptr<LocationArbitrator>
191 GeolocationProviderImpl::CreateArbitrator() {
192 LocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
193 &GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this));
194 // Use the embedder's |g_delegate| or fall back to the default one.
195 if (!g_delegate.Get())
196 g_delegate.Get().reset(new GeolocationDelegate);
197
198 return base::WrapUnique(
199 new LocationArbitratorImpl(callback, g_delegate.Get().get()));
200 }
201
202 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698