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

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: have reference to service worker context in geofencing manager Created 6 years, 2 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 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,
Michael van Ouwerkerk 2014/10/21 11:46:40 It seems odd for a struct to own a callback, but m
Marijn Kruisselbrink 2014/10/21 23:50:06 Yeah, I'm not entirely thrilled at this part of th
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_ = GeofencingService::GetInstance();
79 }
80
81 void GeofencingManager::ShutdownOnIO() {
82 DCHECK_CURRENTLY_ON(BrowserThread::IO);
83 // Clean up all registrations with the |GeofencingService|.
84 for (const auto& registration : registrations_by_id_) {
85 service_->UnregisterRegion(registration.first);
Michael van Ouwerkerk 2014/10/21 11:46:40 Does this mean all regions are unregistered whenev
Marijn Kruisselbrink 2014/10/21 23:50:07 Yes, currently it means that.
86 }
95 } 87 }
96 88
97 void GeofencingManager::RegisterRegion( 89 void GeofencingManager::RegisterRegion(
98 BrowserContext* browser_context,
99 int64 service_worker_registration_id, 90 int64 service_worker_registration_id,
100 const GURL& service_worker_origin,
101 const std::string& region_id, 91 const std::string& region_id,
102 const blink::WebCircularGeofencingRegion& region, 92 const blink::WebCircularGeofencingRegion& region,
103 const StatusCallback& callback) { 93 const StatusCallback& callback) {
104 DCHECK_CURRENTLY_ON(BrowserThread::IO); 94 DCHECK_CURRENTLY_ON(BrowserThread::IO);
105 95
106 // TODO(mek): Validate region_id and region. 96 // TODO(mek): Validate region_id and region.
107 97
108 if (!provider_.get()) { 98 if (!service_->IsServiceAvailable()) {
109 callback.Run(GeofencingStatus:: 99 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
110 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
111 return; 100 return;
112 } 101 }
113 102
114 RegistrationKey key(browser_context, 103 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. 104 // Already registered, return an error.
120 callback.Run(GeofencingStatus::GEOFENCING_STATUS_ERROR); 105 callback.Run(GEOFENCING_STATUS_ERROR);
Michael van Ouwerkerk 2014/10/21 11:46:40 Maybe add a TODO here or file a bug for returning
Marijn Kruisselbrink 2014/10/21 23:50:07 Done.
121 return; 106 return;
122 } 107 }
123 108
124 // Add registration, but don't mark it as active yet. This prevents duplicate 109 AddRegistration(service_worker_registration_id,
125 // registrations. 110 region_id,
126 AddRegistration(key, region); 111 region,
127 112 callback,
128 // Register with provider. 113 service_->RegisterRegion(region, this));
129 provider_->RegisterRegion(
130 region,
131 base::Bind(&GeofencingManager::RegisterRegionCompleted,
132 base::Unretained(this),
133 callback,
134 key));
135 } 114 }
136 115
137 void GeofencingManager::UnregisterRegion(BrowserContext* browser_context, 116 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, 117 const std::string& region_id,
141 const StatusCallback& callback) { 118 const StatusCallback& callback) {
142 DCHECK_CURRENTLY_ON(BrowserThread::IO); 119 DCHECK_CURRENTLY_ON(BrowserThread::IO);
143 120
144 // TODO(mek): Validate region_id. 121 // TODO(mek): Validate region_id.
145 122
146 if (!provider_.get()) { 123 if (!service_->IsServiceAvailable()) {
147 callback.Run(GeofencingStatus:: 124 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
148 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
149 return; 125 return;
150 } 126 }
151 127
152 RegistrationKey key(browser_context, 128 Registration* registration =
153 service_worker_registration_id, 129 FindRegistration(service_worker_registration_id, region_id);
154 service_worker_origin,
155 region_id);
156 Registration* registration = FindRegistration(key);
157 if (!registration) { 130 if (!registration) {
158 // Not registered, return an error/ 131 // Not registered, return an error.
159 callback.Run(GeofencingStatus::GEOFENCING_STATUS_ERROR); 132 callback.Run(GEOFENCING_STATUS_ERROR);
160 return; 133 return;
161 } 134 }
162 135
163 if (!registration->is_active) { 136 if (!registration->is_active()) {
164 // Started registration, but not completed yet, error. 137 // Started registration, but not completed yet, error.
165 callback.Run(GeofencingStatus::GEOFENCING_STATUS_ERROR); 138 callback.Run(GEOFENCING_STATUS_ERROR);
166 return; 139 return;
167 } 140 }
168 141
169 if (registration->registration_id != -1) { 142 service_->UnregisterRegion(registration->geofencing_registration_id);
170 provider_->UnregisterRegion(registration->registration_id); 143 ClearRegistration(registration);
171 } 144 callback.Run(GEOFENCING_STATUS_OK);
172 ClearRegistration(key);
173 callback.Run(GeofencingStatus::GEOFENCING_STATUS_OK);
174 } 145 }
175 146
176 GeofencingStatus GeofencingManager::GetRegisteredRegions( 147 GeofencingStatus GeofencingManager::GetRegisteredRegions(
177 BrowserContext* browser_context,
178 int64 service_worker_registration_id, 148 int64 service_worker_registration_id,
179 const GURL& service_worker_origin,
180 std::map<std::string, blink::WebCircularGeofencingRegion>* result) { 149 std::map<std::string, blink::WebCircularGeofencingRegion>* result) {
181 DCHECK_CURRENTLY_ON(BrowserThread::IO); 150 DCHECK_CURRENTLY_ON(BrowserThread::IO);
182 CHECK(result); 151 CHECK(result);
183 152
184 if (!provider_.get()) { 153 if (!service_->IsServiceAvailable()) {
185 return GeofencingStatus:: 154 return GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE;
186 GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE;
187 } 155 }
188 156
189 // Populate result, filtering out inactive registrations. 157 // Populate result, filtering out inactive registrations.
190 result->clear(); 158 result->clear();
191 for (const auto& registration : registrations_) { 159 ServiceWorkerRegistrationsMap::iterator registrations =
192 if (registration.key.browser_context == browser_context && 160 registrations_.find(service_worker_registration_id);
193 registration.key.service_worker_registration_id == 161 if (registrations == registrations_.end())
194 service_worker_registration_id && 162 return GEOFENCING_STATUS_OK;
195 registration.key.service_worker_origin == service_worker_origin && 163 for (const auto& registration : registrations->second) {
196 registration.is_active) { 164 if (registration.second.is_active()) {
197 (*result)[registration.key.region_id] = registration.region; 165 (*result)[registration.first] = registration.second.region;
198 } 166 }
199 } 167 }
200 return GeofencingStatus::GEOFENCING_STATUS_OK; 168 return GEOFENCING_STATUS_OK;
201 } 169 }
202 170
203 void GeofencingManager::RegisterRegionCompleted(const StatusCallback& callback, 171 void GeofencingManager::RegistrationFinished(int64 geofencing_registration_id,
204 const RegistrationKey& key, 172 GeofencingStatus status) {
205 GeofencingStatus status,
206 int registration_id) {
207 DCHECK_CURRENTLY_ON(BrowserThread::IO); 173 DCHECK_CURRENTLY_ON(BrowserThread::IO);
174 Registration* registration = FindRegistrationById(geofencing_registration_id);
175 DCHECK(registration);
176 DCHECK(!registration->is_active());
177 registration->registration_callback.Run(status);
178 registration->registration_callback.Reset();
179
180 // If the registration wasn't succesfull, remove it from our storage.
Michael van Ouwerkerk 2014/10/21 11:46:41 Nit: successful
Marijn Kruisselbrink 2014/10/21 23:50:07 Done.
208 if (status != GEOFENCING_STATUS_OK) { 181 if (status != GEOFENCING_STATUS_OK) {
209 ClearRegistration(key); 182 ClearRegistration(registration);
210 callback.Run(status);
211 return;
212 } 183 }
Michael van Ouwerkerk 2014/10/21 11:46:40 Nit: no need for braces with one liners
Marijn Kruisselbrink 2014/10/21 23:50:06 Done.
213
214 Registration* registration = FindRegistration(key);
215 DCHECK(registration);
216 registration->registration_id = registration_id;
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 } 184 }
226 185
227 GeofencingManager::Registration* GeofencingManager::FindRegistration( 186 GeofencingManager::Registration* GeofencingManager::FindRegistration(
228 const RegistrationKey& key) { 187 int64 service_worker_registration_id,
229 std::vector<Registration>::iterator it = std::find_if( 188 const std::string& region_id) {
Michael van Ouwerkerk 2014/10/21 11:46:40 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Marijn Kruisselbrink 2014/10/21 23:50:06 Done.
230 registrations_.begin(), registrations_.end(), RegistrationMatches(key)); 189 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
231 if (it == registrations_.end()) 190 registrations_.find(service_worker_registration_id);
191 if (registrations_iterator == registrations_.end())
232 return nullptr; 192 return nullptr;
233 return &*it; 193 RegionIdRegistrationMap::iterator registration =
194 registrations_iterator->second.find(region_id);
195 if (registration == registrations_iterator->second.end())
196 return nullptr;
197 return &registration->second;
198 }
199
200 GeofencingManager::Registration* GeofencingManager::FindRegistrationById(
201 int64 geofencing_registration_id) {
202 RegistrationIdRegistrationMap::iterator registration_iterator =
203 registrations_by_id_.find(geofencing_registration_id);
204 if (registration_iterator == registrations_by_id_.end())
205 return nullptr;
206 return &registration_iterator->second->second;
234 } 207 }
235 208
236 GeofencingManager::Registration& GeofencingManager::AddRegistration( 209 GeofencingManager::Registration& GeofencingManager::AddRegistration(
237 const RegistrationKey& key, 210 int64 service_worker_registration_id,
238 const blink::WebCircularGeofencingRegion& region) { 211 const std::string& region_id,
239 DCHECK(!FindRegistration(key)); 212 const blink::WebCircularGeofencingRegion& region,
240 registrations_.push_back(Registration(key, region)); 213 const StatusCallback& callback,
241 return registrations_.back(); 214 int64 geofencing_registration_id) {
Michael van Ouwerkerk 2014/10/21 11:46:41 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Marijn Kruisselbrink 2014/10/21 23:50:07 Done.
215 DCHECK(!FindRegistration(service_worker_registration_id, region_id));
216 RegionIdRegistrationMap::iterator registration =
217 registrations_[service_worker_registration_id]
218 .insert(std::make_pair(region_id,
219 Registration(service_worker_registration_id,
220 region_id,
221 region,
222 callback,
223 geofencing_registration_id)))
224 .first;
225 registrations_by_id_[geofencing_registration_id] = registration;
226 return registration->second;
242 } 227 }
243 228
244 void GeofencingManager::ClearRegistration(const RegistrationKey& key) { 229 void GeofencingManager::ClearRegistration(Registration* registration) {
245 std::vector<Registration>::iterator it = std::find_if( 230 registrations_by_id_.erase(registration->geofencing_registration_id);
246 registrations_.begin(), registrations_.end(), RegistrationMatches(key)); 231 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
247 if (it == registrations_.end()) 232 registrations_.find(registration->service_worker_registration_id);
248 return; 233 DCHECK(registrations_iterator != registrations_.end());
249 registrations_.erase(it); 234 registrations_iterator->second.erase(registration->region_id);
235 if (registrations_iterator->second.empty())
236 registrations_.erase(registrations_iterator);
250 } 237 }
251 238
252 } // namespace content 239 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698