OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/background_sync/background_sync_manager.h" | |
6 | |
7 #include "base/barrier_closure.h" | |
8 #include "base/bind.h" | |
9 #include "content/browser/background_sync/background_sync.pb.h" | |
10 #include "content/browser/service_worker/service_worker_cache_scheduler.h" | |
11 #include "content/browser/service_worker/service_worker_context_wrapper.h" | |
12 #include "content/browser/service_worker/service_worker_storage.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 | |
15 namespace { | |
16 const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData"; | |
17 } | |
18 | |
19 namespace content { | |
20 | |
21 // static | |
22 scoped_ptr<BackgroundSyncManager> BackgroundSyncManager::Create( | |
23 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) { | |
24 BackgroundSyncManager* sync_manager = | |
25 new BackgroundSyncManager(service_worker_context); | |
26 sync_manager->Init(); | |
27 return make_scoped_ptr(sync_manager); | |
28 } | |
29 | |
30 BackgroundSyncManager::~BackgroundSyncManager() { | |
31 } | |
32 | |
33 void BackgroundSyncManager::Register( | |
34 const GURL& origin, | |
35 int64 sw_registration_id, | |
36 const BackgroundSyncRegistration& sync_registration, | |
37 const StatusAndRegistrationCallback& callback) { | |
38 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
39 DCHECK(initialized_ || initializing_); | |
40 | |
41 StatusAndRegistrationCallback pending_callback = | |
42 base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback, | |
43 weak_ptr_factory_.GetWeakPtr(), callback); | |
44 | |
45 op_scheduler_->ScheduleOperation(base::Bind( | |
46 &BackgroundSyncManager::RegisterImpl, weak_ptr_factory_.GetWeakPtr(), | |
47 origin, sw_registration_id, sync_registration, pending_callback)); | |
48 } | |
49 | |
50 void BackgroundSyncManager::Unregister( | |
51 const GURL& origin, | |
52 int64 sw_registration_id, | |
53 const BackgroundSyncRegistration& sync_registration, | |
54 const StatusCallback& callback) { | |
55 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
56 DCHECK(initialized_ || initializing_); | |
57 | |
58 StatusCallback pending_callback = | |
59 base::Bind(&BackgroundSyncManager::PendingStatusCallback, | |
60 weak_ptr_factory_.GetWeakPtr(), callback); | |
61 | |
62 op_scheduler_->ScheduleOperation(base::Bind( | |
63 &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(), | |
64 origin, sw_registration_id, sync_registration, pending_callback)); | |
65 } | |
66 | |
67 void BackgroundSyncManager::GetRegistration( | |
68 const GURL& origin, | |
69 int64 sw_registration_id, | |
70 const std::string sync_registration_id, | |
71 const StatusAndRegistrationCallback& callback) { | |
72 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
73 DCHECK(initialized_ || initializing_); | |
74 | |
75 StatusAndRegistrationCallback pending_callback = | |
76 base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback, | |
77 weak_ptr_factory_.GetWeakPtr(), callback); | |
78 | |
79 op_scheduler_->ScheduleOperation( | |
80 base::Bind(&BackgroundSyncManager::GetRegistrationImpl, | |
81 weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id, | |
82 sync_registration_id, pending_callback)); | |
83 } | |
84 | |
85 BackgroundSyncManager::BackgroundSyncManager( | |
86 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) | |
87 : initialized_(false), | |
88 initializing_(false), | |
89 registration_map_(new IdToRegistrationMap()), | |
90 op_scheduler_(new ServiceWorkerCacheScheduler()), | |
91 service_worker_context_(service_worker_context), | |
92 weak_ptr_factory_(this) { | |
93 } | |
94 | |
95 void BackgroundSyncManager::Init() { | |
96 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
97 DCHECK(!initialized_ && !initializing_); | |
98 DCHECK(op_scheduler_->Empty()); | |
99 | |
100 initializing_ = true; | |
101 op_scheduler_->ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl, | |
102 weak_ptr_factory_.GetWeakPtr())); | |
103 } | |
104 | |
105 void BackgroundSyncManager::InitImpl() { | |
106 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
107 DCHECK(!initialized_); | |
108 DCHECK(initializing_); | |
109 | |
110 service_worker_context_->context()->storage()->GetUserDataForAllRegistrations( | |
111 kBackgroundSyncUserDataKey, | |
112 base::Bind(&BackgroundSyncManager::InitDidGetUserData, | |
113 weak_ptr_factory_.GetWeakPtr())); | |
114 } | |
115 | |
116 void BackgroundSyncManager::InitDidGetUserData( | |
117 const std::vector<std::pair<int64, std::string>>& user_data, | |
118 ServiceWorkerStatusCode status) { | |
119 for (const std::pair<int64, std::string>& data : user_data) { | |
120 BackgroundSyncRegistrationsProto registrations_proto; | |
121 if (registrations_proto.ParseFromString(data.second)) { | |
122 for (int i = 0, max = registrations_proto.registration_size(); i < max; | |
123 ++i) { | |
124 const BackgroundSyncRegistrationProto& registration_proto = | |
125 registrations_proto.registration(i); | |
126 (*registration_map_)[data.first].push_back( | |
127 BackgroundSyncRegistration(registration_proto.id())); | |
128 } | |
129 } | |
130 } | |
131 | |
132 initializing_ = false; | |
133 initialized_ = true; | |
134 | |
135 // TODO(jkarlin): Call the scheduling algorithm here. | |
136 | |
137 op_scheduler_->CompleteOperationAndRunNext(); | |
138 } | |
139 | |
140 void BackgroundSyncManager::RegisterImpl( | |
141 const GURL& origin, | |
142 int64 sw_registration_id, | |
143 const BackgroundSyncRegistration& sync_registration, | |
144 const StatusAndRegistrationCallback& callback) { | |
145 // TODO(jkarlin): Check for permission. | |
davidben
2015/03/13 22:05:43
(Seems an important thing to do. :-P)
jkarlin
2015/03/14 01:17:27
Yes, though we're protected by (two) command line
| |
146 | |
147 if (!AddRegistrationToMap(sw_registration_id, sync_registration)) { | |
148 callback.Run(ErrorTypeExists, BackgroundSyncRegistration("")); | |
davidben
2015/03/13 22:05:43
Between this and everyone futher up the stack, it
jkarlin
2015/03/14 01:17:27
RunSoon is a good idea, done.
| |
149 return; | |
150 } | |
151 | |
152 StoreRegistrations( | |
153 origin, sw_registration_id, | |
154 base::Bind(&BackgroundSyncManager::RegisterDidStore, | |
155 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, | |
156 sync_registration, callback)); | |
157 } | |
158 | |
159 bool BackgroundSyncManager::HasRegistration( | |
160 int64 sw_registration_id, | |
161 const BackgroundSyncRegistration& sync_registration) { | |
162 IdToRegistrationMap::iterator it = | |
163 registration_map_->find(sw_registration_id); | |
164 if (it == registration_map_->end()) | |
165 return false; | |
166 | |
167 for (const BackgroundSyncRegistration& reg : it->second) { | |
168 if (sync_registration.id == reg.id) | |
169 return true; | |
170 } | |
171 return false; | |
172 } | |
173 | |
174 void BackgroundSyncManager::StoreRegistrations( | |
175 const GURL& origin, | |
176 int64 sw_registration_id, | |
177 const ServiceWorkerStorage::StatusCallback& callback) { | |
178 // Serialize the data. | |
179 BackgroundSyncRegistrationsProto registrations_proto; | |
180 for (const BackgroundSyncRegistration& sync_registration : | |
181 (*registration_map_)[sw_registration_id]) { | |
182 BackgroundSyncRegistrationProto* registration_proto = | |
183 registrations_proto.add_registration(); | |
184 registration_proto->set_id(sync_registration.id); | |
185 } | |
davidben
2015/03/13 22:05:43
Writing N registrations takes O(N^2). Is this a pr
jkarlin
2015/03/14 01:17:27
The thought is that the lists will be small. In w
| |
186 std::string serialized; | |
187 bool success = registrations_proto.SerializeToString(&serialized); | |
188 DCHECK(success); | |
189 | |
190 // Store it. | |
191 service_worker_context_->context()->storage()->StoreUserData( | |
192 sw_registration_id, origin, kBackgroundSyncUserDataKey, serialized, | |
193 callback); | |
194 } | |
195 | |
196 void BackgroundSyncManager::RegisterDidStore( | |
197 int64 sw_registration_id, | |
198 const BackgroundSyncRegistration& sync_registration, | |
199 const StatusAndRegistrationCallback& callback, | |
200 ServiceWorkerStatusCode status) { | |
201 if (status != SERVICE_WORKER_OK) { | |
202 // Restore the previous state. | |
203 RemoveRegistrationFromMap(sw_registration_id, sync_registration); | |
204 callback.Run(ErrorTypeStorage, BackgroundSyncRegistration()); | |
205 return; | |
206 } | |
207 // TODO(jkarlin): Run the registration algorithm. | |
208 callback.Run(ErrorTypeOK, sync_registration); | |
209 } | |
210 | |
211 bool BackgroundSyncManager::RemoveRegistrationFromMap( | |
212 int64 sw_registration_id, | |
213 const BackgroundSyncRegistration& sync_registration) { | |
214 IdToRegistrationMap::iterator it = | |
215 registration_map_->find(sw_registration_id); | |
216 | |
217 if (it == registration_map_->end()) | |
218 return false; | |
219 | |
220 std::list<BackgroundSyncRegistration>* registrations = &(it->second); | |
221 for (std::list<BackgroundSyncRegistration>::iterator reg_iter = | |
222 registrations->begin(); | |
223 reg_iter != registrations->end(); ++reg_iter) { | |
224 if (reg_iter->id == sync_registration.id) { | |
225 registrations->erase(reg_iter); | |
226 return true; | |
227 } | |
228 } | |
229 | |
230 return false; | |
231 } | |
232 | |
233 bool BackgroundSyncManager::AddRegistrationToMap( | |
234 int64 sw_registration_id, | |
235 const BackgroundSyncRegistration& sync_registration) { | |
236 if (HasRegistration(sw_registration_id, sync_registration)) | |
237 return false; | |
238 | |
239 (*registration_map_)[sw_registration_id].push_back(sync_registration); | |
240 return true; | |
241 } | |
242 | |
243 void BackgroundSyncManager::UnregisterImpl( | |
244 const GURL& origin, | |
245 int64 sw_registration_id, | |
246 const BackgroundSyncRegistration& sync_registration, | |
247 const StatusCallback& callback) { | |
248 if (!RemoveRegistrationFromMap(sw_registration_id, sync_registration)) { | |
249 callback.Run(ErrorTypeNotFound); | |
250 return; | |
251 } | |
252 | |
253 StoreRegistrations( | |
254 origin, sw_registration_id, | |
255 base::Bind(&BackgroundSyncManager::UnregisterDidStore, | |
256 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, | |
257 sync_registration, callback)); | |
258 } | |
259 | |
260 void BackgroundSyncManager::UnregisterDidStore( | |
261 int64 sw_registration_id, | |
262 const BackgroundSyncRegistration& sync_registration, | |
263 const StatusCallback& callback, | |
264 ServiceWorkerStatusCode status) { | |
265 if (status != SERVICE_WORKER_OK) { | |
266 // Restore the previous state. | |
267 AddRegistrationToMap(sw_registration_id, sync_registration); | |
268 callback.Run(ErrorTypeStorage); | |
269 return; | |
270 } | |
271 | |
272 // TODO(jkarlin): Run the registration algorithm. | |
273 callback.Run(ErrorTypeOK); | |
274 } | |
275 | |
276 void BackgroundSyncManager::GetRegistrationImpl( | |
277 const GURL& origin, | |
278 int64 sw_registration_id, | |
279 const std::string sync_registration_id, | |
280 const StatusAndRegistrationCallback& callback) { | |
281 IdToRegistrationMap::iterator it = | |
282 registration_map_->find(sw_registration_id); | |
283 | |
284 if (it == registration_map_->end()) { | |
285 callback.Run(ErrorTypeNotFound, BackgroundSyncRegistration()); | |
286 return; | |
287 } | |
288 | |
289 std::list<BackgroundSyncRegistration>* registrations = &(it->second); | |
290 for (std::list<BackgroundSyncRegistration>::iterator reg_iter = | |
291 registrations->begin(); | |
292 reg_iter != registrations->end(); ++reg_iter) { | |
davidben
2015/03/13 22:05:43
for-each loop?
jkarlin
2015/03/14 01:17:27
Done.
| |
293 if (reg_iter->id == sync_registration_id) { | |
294 callback.Run(ErrorTypeOK, *reg_iter); | |
295 return; | |
296 } | |
297 } | |
298 | |
299 callback.Run(ErrorTypeNotFound, BackgroundSyncRegistration()); | |
300 } | |
301 | |
302 void BackgroundSyncManager::PendingStatusAndRegistrationCallback( | |
303 const StatusAndRegistrationCallback& callback, | |
304 ErrorType error, | |
305 const BackgroundSyncRegistration& sync_registration) { | |
306 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | |
davidben
2015/03/13 22:05:43
Worth a comment explaining what's going on here? (
jkarlin
2015/03/14 01:17:27
Added comments. The callback is from outside of th
| |
307 callback.Run(error, sync_registration); | |
308 if (manager) | |
309 op_scheduler_->CompleteOperationAndRunNext(); | |
310 } | |
311 | |
312 void BackgroundSyncManager::PendingStatusCallback( | |
313 const StatusCallback& callback, | |
314 ErrorType error) { | |
315 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | |
316 callback.Run(error); | |
317 if (manager) | |
318 op_scheduler_->CompleteOperationAndRunNext(); | |
319 } | |
320 | |
321 } // namespace content | |
OLD | NEW |