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

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

Issue 10344004: Add content API for requesting the current geolocation (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Removed method for mocking geolocation in unit tests for now, as requested by jam@. Created 8 years, 8 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.cc
diff --git a/content/browser/geolocation/geolocation_provider.cc b/content/browser/geolocation/geolocation_provider.cc
index d61c7c7d064244162350a2d4e0b73b35095e05b0..e572af10fd847e919e2e89c69a9438cd18c6f014 100644
--- a/content/browser/geolocation/geolocation_provider.cc
+++ b/content/browser/geolocation/geolocation_provider.cc
@@ -6,49 +6,103 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
#include "base/memory/singleton.h"
-#include "base/threading/thread_restrictions.h"
+#include "base/message_loop.h"
#include "content/browser/geolocation/location_arbitrator.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+void GeolocationProvider::AddObserver(GeolocationObserver* observer,
+ const GeolocationObserverOptions& update_options) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ observers_[observer] = update_options;
+ OnClientsChanged();
+ if (position_.Validate() ||
+ position_.error_code != content::Geoposition::ERROR_CODE_NONE)
+ observer->OnLocationUpdate(position_);
+}
+
+bool GeolocationProvider::RemoveObserver(GeolocationObserver* observer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ size_t removed = observers_.erase(observer);
+ if (removed)
+ OnClientsChanged();
+ return removed > 0;
+}
+
+void GeolocationProvider::RequestCallback(
+ const content::GeolocationUpdateCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ callbacks_.push_back(callback);
+ OnClientsChanged();
+ OnPermissionGranted();
+}
+
+void GeolocationProvider::OnPermissionGranted() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ bool was_permission_granted = is_permission_granted_;
+ is_permission_granted_ = true;
jam 2012/05/03 06:17:49 this looks like a process wide security variable.
bartfab (slow) 2012/05/03 08:41:15 No. Website permissions are handled elsewhere. The
+ if (IsRunning() && !was_permission_granted)
+ InformProvidersPermissionGranted();
+}
+
+bool GeolocationProvider::HasPermissionBeenGranted() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return is_permission_granted_;
+}
+
+void GeolocationProvider::OnLocationUpdate(
+ const content::Geoposition& position) {
+ DCHECK(OnGeolocationThread());
+ // Will be true only in testing.
+ if (ignore_location_updates_)
+ return;
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GeolocationProvider::NotifyClients,
+ base::Unretained(this), position));
+}
+
+void GeolocationProvider::OverrideLocationForTesting(
+ const content::Geoposition& position) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ position_ = position;
+ ignore_location_updates_ = true;
+ NotifyClients(position);
+}
GeolocationProvider* GeolocationProvider::GetInstance() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return Singleton<GeolocationProvider>::get();
}
GeolocationProvider::GeolocationProvider()
: base::Thread("Geolocation"),
- client_loop_(base::MessageLoopProxy::current()),
is_permission_granted_(false),
ignore_location_updates_(false),
arbitrator_(NULL) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
GeolocationProvider::~GeolocationProvider() {
- DCHECK(observers_.empty()); // observers must unregister.
+ // All observers should have unregistered before this singleton is destructed.
+ DCHECK(observers_.empty());
Stop();
DCHECK(!arbitrator_);
}
-void GeolocationProvider::AddObserver(GeolocationObserver* observer,
- const GeolocationObserverOptions& update_options) {
- DCHECK(OnClientThread());
- observers_[observer] = update_options;
- OnObserversChanged();
- if (position_.Validate() ||
- position_.error_code != content::Geoposition::ERROR_CODE_NONE)
- observer->OnLocationUpdate(position_);
-}
-
-bool GeolocationProvider::RemoveObserver(GeolocationObserver* observer) {
- DCHECK(OnClientThread());
- size_t remove = observers_.erase(observer);
- OnObserversChanged();
- return remove > 0;
+bool GeolocationProvider::OnGeolocationThread() const {
+ return MessageLoop::current() == message_loop();
}
-void GeolocationProvider::OnObserversChanged() {
- DCHECK(OnClientThread());
+void GeolocationProvider::OnClientsChanged() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
base::Closure task;
- if (observers_.empty()) {
+ if (observers_.empty() && callbacks_.empty()) {
DCHECK(IsRunning());
task = base::Bind(&GeolocationProvider::StopProviders,
base::Unretained(this));
@@ -58,29 +112,26 @@ void GeolocationProvider::OnObserversChanged() {
if (HasPermissionBeenGranted())
InformProvidersPermissionGranted();
}
-
- // The high accuracy requirement may have changed.
+ // Determine a set of options that satisfies all clients.
+ GeolocationObserverOptions options =
+ GeolocationObserverOptions::Collapse(observers_);
+ // For callbacks, high accuracy position information is always requested.
+ if (!callbacks_.empty())
+ options.Collapse(GeolocationObserverOptions(true));
+
+ // Send the current options to the providers as they may have changed.
task = base::Bind(&GeolocationProvider::StartProviders,
base::Unretained(this),
- GeolocationObserverOptions::Collapse(observers_));
+ options);
}
message_loop()->PostTask(FROM_HERE, task);
}
-void GeolocationProvider::NotifyObservers(
- const content::Geoposition& position) {
- DCHECK(OnClientThread());
- DCHECK(position.Validate() ||
- position.error_code != content::Geoposition::ERROR_CODE_NONE);
- position_ = position;
- ObserverMap::const_iterator it = observers_.begin();
- while (it != observers_.end()) {
- // Advance iterator before callback to guard against synchronous unregister.
- GeolocationObserver* observer = it->first;
- ++it;
- observer->OnLocationUpdate(position_);
- }
+void GeolocationProvider::StopProviders() {
+ DCHECK(OnGeolocationThread());
+ DCHECK(arbitrator_);
+ arbitrator_->StopProviders();
}
void GeolocationProvider::StartProviders(
@@ -90,19 +141,6 @@ void GeolocationProvider::StartProviders(
arbitrator_->StartProviders(options);
}
-void GeolocationProvider::StopProviders() {
- DCHECK(OnGeolocationThread());
- DCHECK(arbitrator_);
- arbitrator_->StopProviders();
-}
-
-void GeolocationProvider::OnPermissionGranted() {
- DCHECK(OnClientThread());
- is_permission_granted_ = true;
- if (IsRunning())
- InformProvidersPermissionGranted();
-}
-
void GeolocationProvider::InformProvidersPermissionGranted() {
DCHECK(IsRunning());
if (!OnGeolocationThread()) {
@@ -117,6 +155,29 @@ void GeolocationProvider::InformProvidersPermissionGranted() {
arbitrator_->OnPermissionGranted();
}
+void GeolocationProvider::NotifyClients(const content::Geoposition& position) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(position.Validate() ||
+ position.error_code != content::Geoposition::ERROR_CODE_NONE);
+ position_ = position;
+ ObserverMap::const_iterator it = observers_.begin();
+ while (it != observers_.end()) {
+ // Advance iterator before calling the observer to guard against synchronous
+ // unregister.
+ GeolocationObserver* observer = it->first;
+ ++it;
+ observer->OnLocationUpdate(position_);
+ }
+ if (!callbacks_.empty()) {
+ for (CallbackList::iterator it = callbacks_.begin();
+ it != callbacks_.end();
+ ++it)
+ it->Run(position);
+ callbacks_.clear();
+ OnClientsChanged();
+ }
+}
+
void GeolocationProvider::Init() {
DCHECK(OnGeolocationThread());
DCHECK(!arbitrator_);
@@ -128,36 +189,3 @@ void GeolocationProvider::CleanUp() {
delete arbitrator_;
arbitrator_ = NULL;
}
-
-void GeolocationProvider::OnLocationUpdate(
- const content::Geoposition& position) {
- DCHECK(OnGeolocationThread());
- // Will be true only in testing.
- if (ignore_location_updates_)
- return;
- client_loop_->PostTask(
- FROM_HERE,
- base::Bind(&GeolocationProvider::NotifyObservers,
- base::Unretained(this), position));
-}
-
-void GeolocationProvider::OverrideLocationForTesting(
- const content::Geoposition& position) {
- DCHECK(OnClientThread());
- position_ = position;
- ignore_location_updates_ = true;
- NotifyObservers(position);
-}
-
-bool GeolocationProvider::HasPermissionBeenGranted() const {
- DCHECK(OnClientThread());
- return is_permission_granted_;
-}
-
-bool GeolocationProvider::OnClientThread() const {
- return client_loop_->BelongsToCurrentThread();
-}
-
-bool GeolocationProvider::OnGeolocationThread() const {
- return MessageLoop::current() == message_loop();
-}
« no previous file with comments | « content/browser/geolocation/geolocation_provider.h ('k') | content/browser/geolocation/geolocation_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698