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/geofencing/geofencing_manager.cc

Issue 645763003: Refactor GeofencingManager to have one instance per StoragePartition. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments Created 6 years, 1 month 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/geofencing/geofencing_manager.h" 5 #include "content/browser/geofencing/geofencing_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/memory/singleton.h" 10 #include "content/browser/geofencing/geofencing_service.h"
11 #include "content/browser/geofencing/geofencing_provider.h" 11 #include "content/browser/service_worker/service_worker_context_wrapper.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h" 13 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
14 #include "url/gurl.h"
15 14
16 namespace content { 15 namespace content {
17 16
18 struct GeofencingManager::RegistrationKey { 17 struct GeofencingManager::Registration {
19 RegistrationKey(BrowserContext* browser_context, 18 Registration(int64 service_worker_registration_id,
20 int64 service_worker_registration_id, 19 const std::string& region_id,
21 const GURL& service_worker_origin, 20 const blink::WebCircularGeofencingRegion& region,
22 const std::string& region_id); 21 const StatusCallback& callback,
23 22 int64 geofencing_registration_id);
24 BrowserContext* browser_context;
25 23
26 int64 service_worker_registration_id; 24 int64 service_worker_registration_id;
27 GURL service_worker_origin; 25 std::string region_id;
26 blink::WebCircularGeofencingRegion region;
28 27
29 std::string region_id; 28 // Registration ID as returned by the |GeofencingService|.
29 int64 geofencing_registration_id;
30
31 // Callback to call when registration is completed. This field is reset when
32 // registration is complete.
33 StatusCallback registration_callback;
34
35 // Returns true if registration has been completed, and thus should be
36 // included in calls to GetRegisteredRegions.
37 bool is_active() const { return registration_callback.is_null(); }
30 }; 38 };
31 39
32 GeofencingManager::RegistrationKey::RegistrationKey( 40 GeofencingManager::Registration::Registration(
33 BrowserContext* browser_context,
34 int64 service_worker_registration_id, 41 int64 service_worker_registration_id,
35 const GURL& service_worker_origin, 42 const std::string& region_id,
36 const std::string& region_id) 43 const blink::WebCircularGeofencingRegion& region,
37 : browser_context(browser_context), 44 const GeofencingManager::StatusCallback& callback,
38 service_worker_registration_id(service_worker_registration_id), 45 int64 geofencing_registration_id)
39 service_worker_origin(service_worker_origin), 46 : service_worker_registration_id(service_worker_registration_id),
40 region_id(region_id) { 47 region_id(region_id),
48 region(region),
49 geofencing_registration_id(geofencing_registration_id),
50 registration_callback(callback) {
41 } 51 }
42 52
43 struct GeofencingManager::Registration { 53 GeofencingManager::GeofencingManager(
44 Registration(); 54 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
45 Registration(const RegistrationKey& key, 55 : service_(nullptr), service_worker_context_(service_worker_context) {
46 const blink::WebCircularGeofencingRegion& region); 56 DCHECK_CURRENTLY_ON(BrowserThread::UI);
47
48 RegistrationKey key;
49 blink::WebCircularGeofencingRegion region;
50
51 // Registration id as returned by the GeofencingProvider, set to -1 if not
52 // currently registered with the provider.
53 int registration_id;
54
55 // Flag to indicate if this registration has completed, and thus should be
56 // included in calls to GetRegisteredRegions.
57 bool is_active;
58 };
59
60 GeofencingManager::Registration::Registration() : key(nullptr, -1, GURL(), "") {
61 }
62
63 GeofencingManager::Registration::Registration(
64 const RegistrationKey& key,
65 const blink::WebCircularGeofencingRegion& region)
66 : key(key), region(region), registration_id(-1), is_active(false) {
67 }
68
69 class GeofencingManager::RegistrationMatches {
70 public:
71 RegistrationMatches(const RegistrationKey& key) : key_(key) {}
72
73 bool operator()(const Registration& registration) {
74 return registration.key.browser_context == key_.browser_context &&
75 registration.key.service_worker_registration_id ==
76 key_.service_worker_registration_id &&
77 registration.key.service_worker_origin ==
78 key_.service_worker_origin &&
79 registration.key.region_id == key_.region_id;
80 }
81
82 private:
83 const RegistrationKey& key_;
84 };
85
86 GeofencingManager::GeofencingManager() {
87 } 57 }
88 58
89 GeofencingManager::~GeofencingManager() { 59 GeofencingManager::~GeofencingManager() {
90 } 60 }
91 61
92 GeofencingManager* GeofencingManager::GetInstance() { 62 void GeofencingManager::Init() {
63 DCHECK_CURRENTLY_ON(BrowserThread::UI);
64 BrowserThread::PostTask(BrowserThread::IO,
65 FROM_HERE,
66 base::Bind(&GeofencingManager::InitOnIO, this));
67 }
68
69 void GeofencingManager::Shutdown() {
70 DCHECK_CURRENTLY_ON(BrowserThread::UI);
71 BrowserThread::PostTask(BrowserThread::IO,
72 FROM_HERE,
73 base::Bind(&GeofencingManager::ShutdownOnIO, this));
74 }
75
76 void GeofencingManager::InitOnIO() {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO); 77 DCHECK_CURRENTLY_ON(BrowserThread::IO);
94 return Singleton<GeofencingManager>::get(); 78 service_ = GeofencingServiceImpl::GetInstance();
79 }
80
81 void GeofencingManager::ShutdownOnIO() {
82 DCHECK_CURRENTLY_ON(BrowserThread::IO);
83 // Clean up all registrations with the |GeofencingService|.
84 // TODO(mek): This will need to change to support geofence registrations that
85 // outlive the browser, although removing the references to this
86 // |GeofencingManager| from the |GeofencingService| will still be needed.
87 for (const auto& registration : registrations_by_id_) {
88 service_->UnregisterRegion(registration.first);
89 }
95 } 90 }
96 91
97 void GeofencingManager::RegisterRegion( 92 void GeofencingManager::RegisterRegion(
98 BrowserContext* browser_context,
99 int64 service_worker_registration_id, 93 int64 service_worker_registration_id,
100 const GURL& service_worker_origin,
101 const std::string& region_id, 94 const std::string& region_id,
102 const blink::WebCircularGeofencingRegion& region, 95 const blink::WebCircularGeofencingRegion& region,
103 const StatusCallback& callback) { 96 const StatusCallback& callback) {
104 DCHECK_CURRENTLY_ON(BrowserThread::IO); 97 DCHECK_CURRENTLY_ON(BrowserThread::IO);
105 98
106 // TODO(mek): Validate region_id and region. 99 // TODO(mek): Validate region_id and region.
107 100
108 if (!provider_.get()) { 101 if (!service_->IsServiceAvailable()) {
109 callback.Run(GeofencingStatus:: 102 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
110 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
111 return; 103 return;
112 } 104 }
113 105
114 RegistrationKey key(browser_context, 106 if (FindRegistration(service_worker_registration_id, region_id)) {
115 service_worker_registration_id,
116 service_worker_origin,
117 region_id);
118 if (FindRegistration(key)) {
119 // Already registered, return an error. 107 // Already registered, return an error.
120 callback.Run(GeofencingStatus::GEOFENCING_STATUS_ERROR); 108 // TODO(mek): Use a more specific error code.
109 callback.Run(GEOFENCING_STATUS_ERROR);
121 return; 110 return;
122 } 111 }
123 112
124 // Add registration, but don't mark it as active yet. This prevents duplicate 113 AddRegistration(service_worker_registration_id,
125 // registrations. 114 region_id,
126 AddRegistration(key, region); 115 region,
127 116 callback,
128 // Register with provider. 117 service_->RegisterRegion(region, this));
129 provider_->RegisterRegion(
130 region,
131 base::Bind(&GeofencingManager::RegisterRegionCompleted,
132 base::Unretained(this),
133 callback,
134 key));
135 } 118 }
136 119
137 void GeofencingManager::UnregisterRegion(BrowserContext* browser_context, 120 void GeofencingManager::UnregisterRegion(int64 service_worker_registration_id,
138 int64 service_worker_registration_id,
139 const GURL& service_worker_origin,
140 const std::string& region_id, 121 const std::string& region_id,
141 const StatusCallback& callback) { 122 const StatusCallback& callback) {
142 DCHECK_CURRENTLY_ON(BrowserThread::IO); 123 DCHECK_CURRENTLY_ON(BrowserThread::IO);
143 124
144 // TODO(mek): Validate region_id. 125 // TODO(mek): Validate region_id.
145 126
146 if (!provider_.get()) { 127 if (!service_->IsServiceAvailable()) {
147 callback.Run(GeofencingStatus:: 128 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
148 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
149 return; 129 return;
150 } 130 }
151 131
152 RegistrationKey key(browser_context, 132 Registration* registration =
153 service_worker_registration_id, 133 FindRegistration(service_worker_registration_id, region_id);
154 service_worker_origin,
155 region_id);
156 Registration* registration = FindRegistration(key);
157 if (!registration) { 134 if (!registration) {
158 // Not registered, return an error/ 135 // Not registered, return an error.
159 callback.Run(GeofencingStatus::GEOFENCING_STATUS_ERROR); 136 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED);
160 return; 137 return;
161 } 138 }
162 139
163 if (!registration->is_active) { 140 if (!registration->is_active()) {
164 // Started registration, but not completed yet, error. 141 // Started registration, but not completed yet, error.
165 callback.Run(GeofencingStatus::GEOFENCING_STATUS_ERROR); 142 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED);
166 return; 143 return;
167 } 144 }
168 145
169 if (registration->registration_id != -1) { 146 service_->UnregisterRegion(registration->geofencing_registration_id);
170 provider_->UnregisterRegion(registration->registration_id); 147 ClearRegistration(registration);
171 } 148 callback.Run(GEOFENCING_STATUS_OK);
172 ClearRegistration(key);
173 callback.Run(GeofencingStatus::GEOFENCING_STATUS_OK);
174 } 149 }
175 150
176 GeofencingStatus GeofencingManager::GetRegisteredRegions( 151 GeofencingStatus GeofencingManager::GetRegisteredRegions(
177 BrowserContext* browser_context,
178 int64 service_worker_registration_id, 152 int64 service_worker_registration_id,
179 const GURL& service_worker_origin,
180 std::map<std::string, blink::WebCircularGeofencingRegion>* result) { 153 std::map<std::string, blink::WebCircularGeofencingRegion>* result) {
181 DCHECK_CURRENTLY_ON(BrowserThread::IO); 154 DCHECK_CURRENTLY_ON(BrowserThread::IO);
182 CHECK(result); 155 CHECK(result);
183 156
184 if (!provider_.get()) { 157 if (!service_->IsServiceAvailable()) {
185 return GeofencingStatus:: 158 return GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE;
186 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE;
187 } 159 }
188 160
189 // Populate result, filtering out inactive registrations. 161 // Populate result, filtering out inactive registrations.
190 result->clear(); 162 result->clear();
191 for (const auto& registration : registrations_) { 163 ServiceWorkerRegistrationsMap::iterator registrations =
192 if (registration.key.browser_context == browser_context && 164 registrations_.find(service_worker_registration_id);
193 registration.key.service_worker_registration_id == 165 if (registrations == registrations_.end())
194 service_worker_registration_id && 166 return GEOFENCING_STATUS_OK;
195 registration.key.service_worker_origin == service_worker_origin && 167 for (const auto& registration : registrations->second) {
196 registration.is_active) { 168 if (registration.second.is_active())
197 (*result)[registration.key.region_id] = registration.region; 169 (*result)[registration.first] = registration.second.region;
198 }
199 } 170 }
200 return GeofencingStatus::GEOFENCING_STATUS_OK; 171 return GEOFENCING_STATUS_OK;
201 } 172 }
202 173
203 void GeofencingManager::RegisterRegionCompleted(const StatusCallback& callback, 174 void GeofencingManager::RegistrationFinished(int64 geofencing_registration_id,
204 const RegistrationKey& key, 175 GeofencingStatus status) {
205 GeofencingStatus status,
206 int registration_id) {
207 DCHECK_CURRENTLY_ON(BrowserThread::IO); 176 DCHECK_CURRENTLY_ON(BrowserThread::IO);
208 if (status != GEOFENCING_STATUS_OK) { 177 Registration* registration = FindRegistrationById(geofencing_registration_id);
209 ClearRegistration(key); 178 DCHECK(registration);
210 callback.Run(status); 179 DCHECK(!registration->is_active());
211 return; 180 registration->registration_callback.Run(status);
212 } 181 registration->registration_callback.Reset();
213 182
214 Registration* registration = FindRegistration(key); 183 // If the registration wasn't succesful, remove it from our storage.
215 DCHECK(registration); 184 if (status != GEOFENCING_STATUS_OK)
216 registration->registration_id = registration_id; 185 ClearRegistration(registration);
217 registration->is_active = true;
218 callback.Run(GeofencingStatus::GEOFENCING_STATUS_OK);
219 }
220
221 void GeofencingManager::SetProviderForTests(
222 scoped_ptr<GeofencingProvider> provider) {
223 DCHECK(!provider_.get());
224 provider_ = provider.Pass();
225 } 186 }
226 187
227 GeofencingManager::Registration* GeofencingManager::FindRegistration( 188 GeofencingManager::Registration* GeofencingManager::FindRegistration(
228 const RegistrationKey& key) { 189 int64 service_worker_registration_id,
229 std::vector<Registration>::iterator it = std::find_if( 190 const std::string& region_id) {
230 registrations_.begin(), registrations_.end(), RegistrationMatches(key)); 191 DCHECK_CURRENTLY_ON(BrowserThread::IO);
231 if (it == registrations_.end()) 192 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
193 registrations_.find(service_worker_registration_id);
194 if (registrations_iterator == registrations_.end())
232 return nullptr; 195 return nullptr;
233 return &*it; 196 RegionIdRegistrationMap::iterator registration =
197 registrations_iterator->second.find(region_id);
198 if (registration == registrations_iterator->second.end())
199 return nullptr;
200 return &registration->second;
201 }
202
203 GeofencingManager::Registration* GeofencingManager::FindRegistrationById(
204 int64 geofencing_registration_id) {
205 DCHECK_CURRENTLY_ON(BrowserThread::IO);
206 RegistrationIdRegistrationMap::iterator registration_iterator =
207 registrations_by_id_.find(geofencing_registration_id);
208 if (registration_iterator == registrations_by_id_.end())
209 return nullptr;
210 return &registration_iterator->second->second;
234 } 211 }
235 212
236 GeofencingManager::Registration& GeofencingManager::AddRegistration( 213 GeofencingManager::Registration& GeofencingManager::AddRegistration(
237 const RegistrationKey& key, 214 int64 service_worker_registration_id,
238 const blink::WebCircularGeofencingRegion& region) { 215 const std::string& region_id,
239 DCHECK(!FindRegistration(key)); 216 const blink::WebCircularGeofencingRegion& region,
240 registrations_.push_back(Registration(key, region)); 217 const StatusCallback& callback,
241 return registrations_.back(); 218 int64 geofencing_registration_id) {
219 DCHECK_CURRENTLY_ON(BrowserThread::IO);
220 DCHECK(!FindRegistration(service_worker_registration_id, region_id));
221 RegionIdRegistrationMap::iterator registration =
222 registrations_[service_worker_registration_id]
223 .insert(std::make_pair(region_id,
224 Registration(service_worker_registration_id,
225 region_id,
226 region,
227 callback,
228 geofencing_registration_id)))
229 .first;
230 registrations_by_id_[geofencing_registration_id] = registration;
231 return registration->second;
242 } 232 }
243 233
244 void GeofencingManager::ClearRegistration(const RegistrationKey& key) { 234 void GeofencingManager::ClearRegistration(Registration* registration) {
245 std::vector<Registration>::iterator it = std::find_if( 235 DCHECK_CURRENTLY_ON(BrowserThread::IO);
246 registrations_.begin(), registrations_.end(), RegistrationMatches(key)); 236 registrations_by_id_.erase(registration->geofencing_registration_id);
247 if (it == registrations_.end()) 237 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
248 return; 238 registrations_.find(registration->service_worker_registration_id);
249 registrations_.erase(it); 239 DCHECK(registrations_iterator != registrations_.end());
240 registrations_iterator->second.erase(registration->region_id);
241 if (registrations_iterator->second.empty())
242 registrations_.erase(registrations_iterator);
250 } 243 }
251 244
252 } // namespace content 245 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/geofencing/geofencing_manager.h ('k') | content/browser/geofencing/geofencing_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698