#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/time/time.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/event_router.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/common/extensions/api/location.h"
-#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/geolocation_provider.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
#include "content/public/common/geoposition.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/common/extension.h"
#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/permissions/permissions_data.h"
using content::BrowserThread;
{}
// UpdatePolicy Implementation
- virtual bool ShouldSendUpdate(const content::Geoposition& position) const
- OVERRIDE {
+ bool ShouldSendUpdate(const content::Geoposition& position) const override {
return !last_updated_position_.Validate() ||
Distance(position.latitude,
position.longitude,
distance_update_threshold_meters_;
}
- virtual void OnPositionReported(const content::Geoposition& position)
- OVERRIDE {
+ void OnPositionReported(const content::Geoposition& position) override {
last_updated_position_ = position;
}
private:
- virtual ~DistanceBasedUpdatePolicy() {}
+ ~DistanceBasedUpdatePolicy() override {}
// Calculates the distance between two latitude and longitude points.
static double Distance(const double latitude1,
{}
// UpdatePolicy Implementation
- virtual bool ShouldSendUpdate(const content::Geoposition&) const OVERRIDE {
+ bool ShouldSendUpdate(const content::Geoposition&) const override {
return (base::Time::Now() - last_update_time_).InMilliseconds() >
time_between_updates_ms_;
}
- virtual void OnPositionReported(const content::Geoposition&) OVERRIDE {
+ void OnPositionReported(const content::Geoposition&) override {
last_update_time_ = base::Time::Now();
}
private:
- virtual ~TimeBasedUpdatePolicy() {}
+ ~TimeBasedUpdatePolicy() override {}
base::Time last_update_time_;
const double time_between_updates_ms_;
} // namespace updatepolicy
// Request created by chrome.location.watchLocation() call.
-// Lives in the IO thread, except for the constructor.
-class LocationRequest
- : public base::RefCountedThreadSafe<LocationRequest,
- BrowserThread::DeleteOnIOThread> {
+class LocationRequest : public base::RefCounted<LocationRequest> {
public:
LocationRequest(
- const base::WeakPtr<LocationManager>& location_manager,
+ LocationManager* location_manager,
const std::string& extension_id,
const std::string& request_name,
const double* distance_update_threshold_meters,
const double* time_between_updates_ms);
- // Finishes the necessary setup for this object.
- // Call this method immediately after taking a strong reference
- // to this object.
- //
- // Ideally, we would do this at construction time, but currently
- // our refcount starts at zero. BrowserThread::PostTask will take a ref
- // and potentially release it before we are done, destroying us in the
- // constructor.
- void Initialize();
-
const std::string& request_name() const { return request_name_; }
- // Grants permission for using geolocation.
- static void GrantPermission();
-
private:
- friend class base::DeleteHelper<LocationRequest>;
- friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
-
- virtual ~LocationRequest();
-
- void AddObserverOnIOThread();
+ friend class base::RefCounted<LocationRequest>;
+ ~LocationRequest();
void OnLocationUpdate(const content::Geoposition& position);
const std::string extension_id_;
// Owning location manager.
- const base::WeakPtr<LocationManager> location_manager_;
+ LocationManager* location_manager_;
// Holds Update Policies.
typedef std::vector<scoped_refptr<updatepolicy::UpdatePolicy> >
UpdatePolicyVector;
UpdatePolicyVector update_policies_;
- content::GeolocationProvider::LocationUpdateCallback callback_;
+ scoped_ptr<content::GeolocationProvider::Subscription>
+ geolocation_subscription_;
DISALLOW_COPY_AND_ASSIGN(LocationRequest);
};
LocationRequest::LocationRequest(
- const base::WeakPtr<LocationManager>& location_manager,
+ LocationManager* location_manager,
const std::string& extension_id,
const std::string& request_name,
const double* distance_update_threshold_meters,
extension_id_(extension_id),
location_manager_(location_manager) {
// TODO(vadimt): use request_info.
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
if (time_between_updates_ms) {
update_policies_.push_back(
new updatepolicy::TimeBasedUpdatePolicy(
new updatepolicy::DistanceBasedUpdatePolicy(
*distance_update_threshold_meters));
}
-}
-
-void LocationRequest::Initialize() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- callback_ = base::Bind(&LocationRequest::OnLocationUpdate,
- base::Unretained(this));
-
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&LocationRequest::AddObserverOnIOThread,
- this));
-}
-
-void LocationRequest::GrantPermission() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
-}
-
-LocationRequest::~LocationRequest() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- content::GeolocationProvider::GetInstance()->RemoveLocationUpdateCallback(
- callback_);
-}
-
-void LocationRequest::AddObserverOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// TODO(vadimt): This can get a location cached by GeolocationProvider,
// contrary to the API definition which says that creating a location watch
// will get new location.
- content::GeolocationProvider::GetInstance()->AddLocationUpdateCallback(
- callback_, true);
+ geolocation_subscription_ = content::GeolocationProvider::GetInstance()->
+ AddLocationUpdateCallback(
+ base::Bind(&LocationRequest::OnLocationUpdate,
+ base::Unretained(this)),
+ true);
+}
+
+LocationRequest::~LocationRequest() {
}
void LocationRequest::OnLocationUpdate(const content::Geoposition& position) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (ShouldSendUpdate(position)) {
OnPositionReported(position);
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&LocationManager::SendLocationUpdate,
- location_manager_,
- extension_id_,
- request_name_,
- position));
+ location_manager_->SendLocationUpdate(
+ extension_id_, request_name_, position);
}
}
bool LocationRequest::ShouldSendUpdate(const content::Geoposition& position) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
for (UpdatePolicyVector::iterator it = update_policies_.begin();
it != update_policies_.end();
++it) {
}
void LocationRequest::OnPositionReported(const content::Geoposition& position) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
for (UpdatePolicyVector::iterator it = update_policies_.begin();
it != update_policies_.end();
++it) {
}
}
-LocationManager::LocationManager(Profile* profile)
- : profile_(profile) {
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(profile_));
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(profile_));
+LocationManager::LocationManager(content::BrowserContext* context)
+ : browser_context_(context), extension_registry_observer_(this) {
+ extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
}
void LocationManager::AddLocationRequest(
const std::string& request_name,
const double* distance_update_threshold_meters,
const double* time_between_updates_ms) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// TODO(vadimt): Consider resuming requests after restarting the browser.
// Override any old request with the same name.
RemoveLocationRequest(extension_id, request_name);
LocationRequestPointer location_request =
- new LocationRequest(AsWeakPtr(),
+ new LocationRequest(this,
extension_id,
request_name,
distance_update_threshold_meters,
time_between_updates_ms);
- location_request->Initialize();
location_requests_.insert(
LocationRequestMap::value_type(extension_id, location_request));
}
void LocationManager::RemoveLocationRequest(const std::string& extension_id,
const std::string& name) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::pair<LocationRequestMap::iterator, LocationRequestMap::iterator>
extension_range = location_requests_.equal_range(extension_id);
const std::string& extension_id,
const std::string& request_name,
const content::Geoposition& position) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_ptr<base::ListValue> args(new base::ListValue());
std::string event_name;
scoped_ptr<Event> event(new Event(event_name, args.Pass()));
- ExtensionSystem::Get(profile_)->event_router()->
- DispatchEventToExtension(extension_id, event.Pass());
+ EventRouter::Get(browser_context_)
+ ->DispatchEventToExtension(extension_id, event.Pass());
}
-void LocationManager::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- switch (type) {
- case chrome::NOTIFICATION_EXTENSION_LOADED: {
- // Grants permission to use geolocation once an extension with "location"
- // permission is loaded.
- const Extension* extension =
- content::Details<const Extension>(details).ptr();
-
- if (extension->HasAPIPermission(APIPermission::kLocation)) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&LocationRequest::GrantPermission));
- }
- break;
- }
- case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
- // Delete all requests from the unloaded extension.
- const Extension* extension =
- content::Details<const UnloadedExtensionInfo>(details)->extension;
- location_requests_.erase(extension->id());
- break;
- }
- default:
- NOTREACHED();
- break;
+void LocationManager::OnExtensionLoaded(
+ content::BrowserContext* browser_context,
+ const Extension* extension) {
+ // Grants permission to use geolocation once an extension with "location"
+ // permission is loaded.
+ if (extension->permissions_data()->HasAPIPermission(
+ APIPermission::kLocation)) {
+ content::GeolocationProvider::GetInstance()
+ ->UserDidOptIntoLocationServices();
}
}
-static base::LazyInstance<ProfileKeyedAPIFactory<LocationManager> >
-g_factory = LAZY_INSTANCE_INITIALIZER;
+void LocationManager::OnExtensionUnloaded(
+ content::BrowserContext* browser_context,
+ const Extension* extension,
+ UnloadedExtensionInfo::Reason reason) {
+ // Delete all requests from the unloaded extension.
+ location_requests_.erase(extension->id());
+}
+
+static base::LazyInstance<BrowserContextKeyedAPIFactory<LocationManager> >
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
-ProfileKeyedAPIFactory<LocationManager>* LocationManager::GetFactoryInstance() {
- return &g_factory.Get();
+BrowserContextKeyedAPIFactory<LocationManager>*
+LocationManager::GetFactoryInstance() {
+ return g_factory.Pointer();
}
- // static
-LocationManager* LocationManager::Get(Profile* profile) {
- return ProfileKeyedAPIFactory<LocationManager>::GetForProfile(profile);
+// static
+LocationManager* LocationManager::Get(content::BrowserContext* context) {
+ return BrowserContextKeyedAPIFactory<LocationManager>::Get(context);
}
} // namespace extensions