Index: content/browser/geofencing/geofencing_service.cc |
diff --git a/content/browser/geofencing/geofencing_service.cc b/content/browser/geofencing/geofencing_service.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..11df9529e4d34ce6646d507d48605ccdb34935ab |
--- /dev/null |
+++ b/content/browser/geofencing/geofencing_service.cc |
@@ -0,0 +1,199 @@ |
+// Copyright 2014 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/geofencing/geofencing_service.h" |
+ |
+#include "base/memory/singleton.h" |
+#include "base/message_loop/message_loop.h" |
+#include "content/browser/geofencing/geofencing_provider.h" |
+#include "content/browser/geofencing/geofencing_registration_delegate.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+void RunSoon(const base::Closure& callback) { |
+ if (!callback.is_null()) |
+ base::MessageLoop::current()->PostTask(FROM_HERE, callback); |
+} |
+ |
+} // namespace |
+ |
+struct GeofencingServiceImpl::Registration { |
+ Registration(); |
+ Registration(const blink::WebCircularGeofencingRegion& region, |
+ int64 geofencing_registration_id, |
+ GeofencingRegistrationDelegate* delegate); |
+ |
+ blink::WebCircularGeofencingRegion region; |
+ int64 geofencing_registration_id; |
+ GeofencingRegistrationDelegate* delegate; |
+ |
+ enum RegistrationState { |
+ // In progress of being registered with provider. |
+ STATE_REGISTERING, |
+ // Currently registered with provider. |
+ STATE_REGISTERED, |
+ // In progress of being registered with provider, but should be unregistered |
+ // and deleted. |
+ STATE_SHOULD_UNREGISTER_AND_DELETE, |
+ // Not currently registered with provider, but still an active registration. |
+ STATE_UNREGISTERED |
+ }; |
+ RegistrationState state; |
+}; |
+ |
+GeofencingServiceImpl::Registration::Registration() |
+ : geofencing_registration_id(-1), |
+ delegate(nullptr), |
+ state(STATE_UNREGISTERED) { |
+} |
+ |
+GeofencingServiceImpl::Registration::Registration( |
+ const blink::WebCircularGeofencingRegion& region, |
+ int64 geofencing_registration_id, |
+ GeofencingRegistrationDelegate* delegate) |
+ : region(region), |
+ geofencing_registration_id(geofencing_registration_id), |
+ delegate(delegate), |
+ state(STATE_REGISTERING) { |
+} |
+ |
+GeofencingServiceImpl::GeofencingServiceImpl() : next_registration_id_(0) { |
+} |
+ |
+GeofencingServiceImpl::~GeofencingServiceImpl() { |
+} |
+ |
+GeofencingServiceImpl* GeofencingServiceImpl::GetInstance() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ return Singleton<GeofencingServiceImpl>::get(); |
+} |
+ |
+bool GeofencingServiceImpl::IsServiceAvailable() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ return EnsureProvider(); |
+} |
+ |
+int64 GeofencingServiceImpl::RegisterRegion( |
+ const blink::WebCircularGeofencingRegion& region, |
+ GeofencingRegistrationDelegate* delegate) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ int64 geofencing_registration_id = GetNextId(); |
+ registrations_[geofencing_registration_id] = |
+ Registration(region, geofencing_registration_id, delegate); |
+ |
+ if (!EnsureProvider()) { |
+ RunSoon( |
+ base::Bind(&GeofencingServiceImpl::NotifyRegistrationFinished, |
+ base::Unretained(this), |
+ geofencing_registration_id, |
+ GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE)); |
+ return geofencing_registration_id; |
+ } |
+ |
+ provider_->RegisterRegion( |
+ geofencing_registration_id, |
+ region, |
+ base::Bind(&GeofencingServiceImpl::NotifyRegistrationFinished, |
+ base::Unretained(this), |
+ geofencing_registration_id)); |
+ return geofencing_registration_id; |
+} |
+ |
+void GeofencingServiceImpl::UnregisterRegion(int64 geofencing_registration_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ RegistrationsMap::iterator registration_iterator = |
+ registrations_.find(geofencing_registration_id); |
+ DCHECK(registration_iterator != registrations_.end()); |
+ |
+ if (!EnsureProvider()) |
+ return; |
+ |
+ switch (registration_iterator->second.state) { |
+ case Registration::STATE_REGISTERED: |
+ provider_->UnregisterRegion(geofencing_registration_id); |
+ // fallthru |
+ case Registration::STATE_UNREGISTERED: |
+ registrations_.erase(registration_iterator); |
+ break; |
+ case Registration::STATE_REGISTERING: |
+ // Update state, NotifyRegistrationFinished will take care of actually |
+ // unregistering. |
+ registration_iterator->second.state = |
+ Registration::STATE_SHOULD_UNREGISTER_AND_DELETE; |
+ break; |
+ case Registration::STATE_SHOULD_UNREGISTER_AND_DELETE: |
+ // Should not happen. |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+void GeofencingServiceImpl::SetProviderForTesting( |
+ scoped_ptr<GeofencingProvider> provider) { |
+ DCHECK(!provider_.get()); |
+ provider_ = provider.Pass(); |
+} |
+ |
+int GeofencingServiceImpl::RegistrationCountForTesting() { |
+ return registrations_.size(); |
+} |
+ |
+bool GeofencingServiceImpl::EnsureProvider() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ if (!provider_) { |
+ // TODO(mek): Create platform specific provider. |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+int64 GeofencingServiceImpl::GetNextId() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ return next_registration_id_++; |
+} |
+ |
+void GeofencingServiceImpl::NotifyRegistrationFinished( |
+ int64 geofencing_registration_id, |
+ GeofencingStatus status) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ RegistrationsMap::iterator registration_iterator = |
+ registrations_.find(geofencing_registration_id); |
+ DCHECK(registration_iterator != registrations_.end()); |
+ DCHECK(registration_iterator->second.state == |
+ Registration::STATE_REGISTERING || |
+ registration_iterator->second.state == |
+ Registration::STATE_SHOULD_UNREGISTER_AND_DELETE); |
+ |
+ if (registration_iterator->second.state == |
+ Registration::STATE_SHOULD_UNREGISTER_AND_DELETE) { |
+ // Don't call delegate, but unregister with provider if registration was |
+ // succesfull. |
+ if (status == GEOFENCING_STATUS_OK) { |
+ provider_->UnregisterRegion(geofencing_registration_id); |
+ } |
+ registrations_.erase(registration_iterator); |
+ return; |
+ } |
+ |
+ // Normal case, mark as registered and call delegate. |
+ registration_iterator->second.state = Registration::STATE_REGISTERED; |
+ registration_iterator->second.delegate->RegistrationFinished( |
+ geofencing_registration_id, status); |
+ |
+ if (status != GEOFENCING_STATUS_OK) { |
+ // Registration failed, remove from our book-keeping. |
+ registrations_.erase(registration_iterator); |
+ } |
+} |
+ |
+} // namespace content |