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

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: *Argh*, missed another forward declaration of a struct as a class. 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..da592e205a92fa36a84e3c5dc3c78383d98e6786 100644
--- a/content/browser/geolocation/geolocation_provider.cc
+++ b/content/browser/geolocation/geolocation_provider.cc
@@ -6,49 +6,66 @@
#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;
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());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
observers_[observer] = update_options;
- OnObserversChanged();
+ OnClientsChanged();
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;
+ 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::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 +75,46 @@ 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());
+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 callback to guard against synchronous unregister.
+ // Advance iterator before calling the observer to guard against synchronous
+ // unregister.
GeolocationObserver* observer = it->first;
++it;
observer->OnLocationUpdate(position_);
}
+ if (!callbacks_.empty()) {
+ // Copy the callback list to guard against synchronous callback requests
+ // reallocating the vector and invalidating the iterator.
+ CallbackList callbacks = callbacks_;
+ callbacks_.clear();
+ for (CallbackList::iterator it = callbacks.begin();
+ it != callbacks.end();
+ ++it)
+ it->Run(position);
+ OnClientsChanged();
+ }
}
void GeolocationProvider::StartProviders(
@@ -97,9 +131,10 @@ void GeolocationProvider::StopProviders() {
}
void GeolocationProvider::OnPermissionGranted() {
- DCHECK(OnClientThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ bool was_permission_granted = is_permission_granted_;
is_permission_granted_ = true;
- if (IsRunning())
+ if (IsRunning() && !was_permission_granted)
InformProvidersPermissionGranted();
}
@@ -135,29 +170,25 @@ void GeolocationProvider::OnLocationUpdate(
// Will be true only in testing.
if (ignore_location_updates_)
return;
- client_loop_->PostTask(
- FROM_HERE,
- base::Bind(&GeolocationProvider::NotifyObservers,
- base::Unretained(this), position));
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GeolocationProvider::NotifyClients,
+ base::Unretained(this), position));
}
void GeolocationProvider::OverrideLocationForTesting(
const content::Geoposition& position) {
- DCHECK(OnClientThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
position_ = position;
ignore_location_updates_ = true;
- NotifyObservers(position);
+ NotifyClients(position);
}
bool GeolocationProvider::HasPermissionBeenGranted() const {
- DCHECK(OnClientThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
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