OLD | NEW |
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 "google_apis/gcm/engine/gcm_store_impl.h" | 5 #include "google_apis/gcm/engine/gcm_store_impl.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 } | 72 } |
73 | 73 |
74 std::string ParseOutgoingKey(const std::string& key) { | 74 std::string ParseOutgoingKey(const std::string& key) { |
75 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); | 75 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); |
76 } | 76 } |
77 | 77 |
78 std::string ParseUsername(const std::string& key) { | 78 std::string ParseUsername(const std::string& key) { |
79 return key.substr(arraysize(kUserSerialNumberKeyStart) - 1); | 79 return key.substr(arraysize(kUserSerialNumberKeyStart) - 1); |
80 } | 80 } |
81 | 81 |
| 82 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore |
| 83 // outlive the slice. |
| 84 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. |
82 leveldb::Slice MakeSlice(const base::StringPiece& s) { | 85 leveldb::Slice MakeSlice(const base::StringPiece& s) { |
83 return leveldb::Slice(s.begin(), s.size()); | 86 return leveldb::Slice(s.begin(), s.size()); |
84 } | 87 } |
85 | 88 |
86 } // namespace | 89 } // namespace |
87 | 90 |
88 class GCMStoreImpl::Backend | 91 class GCMStoreImpl::Backend |
89 : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { | 92 : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { |
90 public: | 93 public: |
91 Backend(const base::FilePath& path, | 94 Backend(const base::FilePath& path, |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 228 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
226 return; | 229 return; |
227 } | 230 } |
228 | 231 |
229 leveldb::WriteOptions write_options; | 232 leveldb::WriteOptions write_options; |
230 write_options.sync = true; | 233 write_options.sync = true; |
231 | 234 |
232 std::string encrypted_token; | 235 std::string encrypted_token; |
233 Encryptor::EncryptString(base::Uint64ToString(device_security_token), | 236 Encryptor::EncryptString(base::Uint64ToString(device_security_token), |
234 &encrypted_token); | 237 &encrypted_token); |
| 238 std::string android_id_str = base::Uint64ToString(device_android_id); |
235 leveldb::Status s = | 239 leveldb::Status s = |
236 db_->Put(write_options, | 240 db_->Put(write_options, |
237 MakeSlice(kDeviceAIDKey), | 241 MakeSlice(kDeviceAIDKey), |
238 MakeSlice(base::Uint64ToString(device_android_id))); | 242 MakeSlice(android_id_str)); |
239 if (s.ok()) { | 243 if (s.ok()) { |
240 s = db_->Put( | 244 s = db_->Put( |
241 write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); | 245 write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); |
242 } | 246 } |
243 if (s.ok()) { | 247 if (s.ok()) { |
244 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 248 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
245 return; | 249 return; |
246 } | 250 } |
247 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); | 251 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); |
248 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 252 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
249 } | 253 } |
250 | 254 |
251 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, | 255 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, |
252 const UpdateCallback& callback) { | 256 const UpdateCallback& callback) { |
253 DVLOG(1) << "Saving incoming message with id " << persistent_id; | 257 DVLOG(1) << "Saving incoming message with id " << persistent_id; |
254 if (!db_.get()) { | 258 if (!db_.get()) { |
255 LOG(ERROR) << "GCMStore db doesn't exist."; | 259 LOG(ERROR) << "GCMStore db doesn't exist."; |
256 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 260 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
257 return; | 261 return; |
258 } | 262 } |
259 | 263 |
260 leveldb::WriteOptions write_options; | 264 leveldb::WriteOptions write_options; |
261 write_options.sync = true; | 265 write_options.sync = true; |
262 | 266 |
| 267 std::string key = MakeIncomingKey(persistent_id); |
263 const leveldb::Status s = db_->Put(write_options, | 268 const leveldb::Status s = db_->Put(write_options, |
264 MakeSlice(MakeIncomingKey(persistent_id)), | 269 MakeSlice(key), |
265 MakeSlice(persistent_id)); | 270 MakeSlice(persistent_id)); |
266 if (s.ok()) { | 271 if (s.ok()) { |
267 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 272 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
268 return; | 273 return; |
269 } | 274 } |
270 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); | 275 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); |
271 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 276 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
272 } | 277 } |
273 | 278 |
274 void GCMStoreImpl::Backend::RemoveIncomingMessages( | 279 void GCMStoreImpl::Backend::RemoveIncomingMessages( |
275 const PersistentIdList& persistent_ids, | 280 const PersistentIdList& persistent_ids, |
276 const UpdateCallback& callback) { | 281 const UpdateCallback& callback) { |
277 if (!db_.get()) { | 282 if (!db_.get()) { |
278 LOG(ERROR) << "GCMStore db doesn't exist."; | 283 LOG(ERROR) << "GCMStore db doesn't exist."; |
279 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 284 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
280 return; | 285 return; |
281 } | 286 } |
282 leveldb::WriteOptions write_options; | 287 leveldb::WriteOptions write_options; |
283 write_options.sync = true; | 288 write_options.sync = true; |
284 | 289 |
285 leveldb::Status s; | 290 leveldb::Status s; |
286 for (PersistentIdList::const_iterator iter = persistent_ids.begin(); | 291 for (PersistentIdList::const_iterator iter = persistent_ids.begin(); |
287 iter != persistent_ids.end(); | 292 iter != persistent_ids.end(); |
288 ++iter) { | 293 ++iter) { |
289 DVLOG(1) << "Removing incoming message with id " << *iter; | 294 DVLOG(1) << "Removing incoming message with id " << *iter; |
290 s = db_->Delete(write_options, MakeSlice(MakeIncomingKey(*iter))); | 295 std::string key = MakeIncomingKey(*iter); |
| 296 s = db_->Delete(write_options, MakeSlice(key)); |
291 if (!s.ok()) | 297 if (!s.ok()) |
292 break; | 298 break; |
293 } | 299 } |
294 if (s.ok()) { | 300 if (s.ok()) { |
295 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 301 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
296 return; | 302 return; |
297 } | 303 } |
298 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); | 304 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); |
299 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 305 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
300 } | 306 } |
301 | 307 |
302 void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, | 308 void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, |
303 const MCSMessage& message, | 309 const MCSMessage& message, |
304 const UpdateCallback& callback) { | 310 const UpdateCallback& callback) { |
305 DVLOG(1) << "Saving outgoing message with id " << persistent_id; | 311 DVLOG(1) << "Saving outgoing message with id " << persistent_id; |
306 if (!db_.get()) { | 312 if (!db_.get()) { |
307 LOG(ERROR) << "GCMStore db doesn't exist."; | 313 LOG(ERROR) << "GCMStore db doesn't exist."; |
308 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 314 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
309 return; | 315 return; |
310 } | 316 } |
311 leveldb::WriteOptions write_options; | 317 leveldb::WriteOptions write_options; |
312 write_options.sync = true; | 318 write_options.sync = true; |
313 | 319 |
314 std::string data = | 320 std::string data = |
315 static_cast<char>(message.tag()) + message.SerializeAsString(); | 321 static_cast<char>(message.tag()) + message.SerializeAsString(); |
| 322 std::string key = MakeOutgoingKey(persistent_id); |
316 const leveldb::Status s = db_->Put(write_options, | 323 const leveldb::Status s = db_->Put(write_options, |
317 MakeSlice(MakeOutgoingKey(persistent_id)), | 324 MakeSlice(key), |
318 MakeSlice(data)); | 325 MakeSlice(data)); |
319 if (s.ok()) { | 326 if (s.ok()) { |
320 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 327 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
321 return; | 328 return; |
322 } | 329 } |
323 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); | 330 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); |
324 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 331 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
325 } | 332 } |
326 | 333 |
327 void GCMStoreImpl::Backend::RemoveOutgoingMessages( | 334 void GCMStoreImpl::Backend::RemoveOutgoingMessages( |
(...skipping 13 matching lines...) Expand all Loading... |
341 write_options.sync = true; | 348 write_options.sync = true; |
342 | 349 |
343 AppIdToMessageCountMap removed_message_counts; | 350 AppIdToMessageCountMap removed_message_counts; |
344 | 351 |
345 leveldb::Status s; | 352 leveldb::Status s; |
346 for (PersistentIdList::const_iterator iter = persistent_ids.begin(); | 353 for (PersistentIdList::const_iterator iter = persistent_ids.begin(); |
347 iter != persistent_ids.end(); | 354 iter != persistent_ids.end(); |
348 ++iter) { | 355 ++iter) { |
349 DVLOG(1) << "Removing outgoing message with id " << *iter; | 356 DVLOG(1) << "Removing outgoing message with id " << *iter; |
350 std::string outgoing_message; | 357 std::string outgoing_message; |
351 leveldb::Slice key_slice = MakeSlice(MakeOutgoingKey(*iter)); | 358 std::string key = MakeOutgoingKey(*iter); |
352 s = db_->Get(read_options, key_slice, &outgoing_message); | 359 s = db_->Get(read_options, |
| 360 MakeSlice(key), |
| 361 &outgoing_message); |
353 if (!s.ok()) | 362 if (!s.ok()) |
354 break; | 363 break; |
355 mcs_proto::DataMessageStanza data_message; | 364 mcs_proto::DataMessageStanza data_message; |
356 // Skip the initial tag byte and parse the rest to extract the message. | 365 // Skip the initial tag byte and parse the rest to extract the message. |
357 if (data_message.ParseFromString(outgoing_message.substr(1))) { | 366 if (data_message.ParseFromString(outgoing_message.substr(1))) { |
358 DCHECK(!data_message.from().empty()); | 367 DCHECK(!data_message.from().empty()); |
359 if (removed_message_counts.count(data_message.from()) != 0) | 368 if (removed_message_counts.count(data_message.from()) != 0) |
360 removed_message_counts[data_message.from()]++; | 369 removed_message_counts[data_message.from()]++; |
361 else | 370 else |
362 removed_message_counts[data_message.from()] = 1; | 371 removed_message_counts[data_message.from()] = 1; |
363 } | 372 } |
364 DVLOG(1) << "Removing outgoing message with id " << *iter; | 373 DVLOG(1) << "Removing outgoing message with id " << *iter; |
365 // Have to create a new slice to perform the deletion. | 374 s = db_->Delete(write_options, MakeSlice(key)); |
366 s = db_->Delete(write_options, MakeSlice(MakeOutgoingKey(*iter))); | |
367 if (!s.ok()) | 375 if (!s.ok()) |
368 break; | 376 break; |
369 } | 377 } |
370 if (s.ok()) { | 378 if (s.ok()) { |
371 foreground_task_runner_->PostTask(FROM_HERE, | 379 foreground_task_runner_->PostTask(FROM_HERE, |
372 base::Bind(callback, | 380 base::Bind(callback, |
373 true, | 381 true, |
374 removed_message_counts)); | 382 removed_message_counts)); |
375 return; | 383 return; |
376 } | 384 } |
(...skipping 10 matching lines...) Expand all Loading... |
387 const UpdateCallback& callback) { | 395 const UpdateCallback& callback) { |
388 DVLOG(1) << "Saving username to serial number mapping for user: " << username; | 396 DVLOG(1) << "Saving username to serial number mapping for user: " << username; |
389 if (!db_.get()) { | 397 if (!db_.get()) { |
390 LOG(ERROR) << "GCMStore db doesn't exist."; | 398 LOG(ERROR) << "GCMStore db doesn't exist."; |
391 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 399 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
392 return; | 400 return; |
393 } | 401 } |
394 leveldb::WriteOptions write_options; | 402 leveldb::WriteOptions write_options; |
395 write_options.sync = true; | 403 write_options.sync = true; |
396 | 404 |
| 405 std::string key = MakeUserSerialNumberKey(username); |
| 406 std::string serial_number_str = base::Int64ToString(serial_number); |
397 const leveldb::Status status = | 407 const leveldb::Status status = |
398 db_->Put(write_options, | 408 db_->Put(write_options, |
399 MakeSlice(MakeUserSerialNumberKey(username)), | 409 MakeSlice(key), |
400 MakeSlice(base::Int64ToString(serial_number))); | 410 MakeSlice(serial_number_str)); |
401 if (status.ok()) { | 411 if (status.ok()) { |
402 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 412 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
403 return; | 413 return; |
404 } | 414 } |
405 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); | 415 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); |
406 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 416 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
407 } | 417 } |
408 | 418 |
409 void GCMStoreImpl::Backend::RemoveUserSerialNumber( | 419 void GCMStoreImpl::Backend::RemoveUserSerialNumber( |
410 const std::string& username, | 420 const std::string& username, |
(...skipping 21 matching lines...) Expand all Loading... |
432 DVLOG(1) << "Updating the value of next user serial number to: " | 442 DVLOG(1) << "Updating the value of next user serial number to: " |
433 << next_serial_number; | 443 << next_serial_number; |
434 if (!db_.get()) { | 444 if (!db_.get()) { |
435 LOG(ERROR) << "GCMStore db doesn't exist."; | 445 LOG(ERROR) << "GCMStore db doesn't exist."; |
436 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 446 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
437 return; | 447 return; |
438 } | 448 } |
439 leveldb::WriteOptions write_options; | 449 leveldb::WriteOptions write_options; |
440 write_options.sync = true; | 450 write_options.sync = true; |
441 | 451 |
| 452 std::string serial_number_str = base::Int64ToString(next_serial_number); |
442 const leveldb::Status status = | 453 const leveldb::Status status = |
443 db_->Put(write_options, | 454 db_->Put(write_options, |
444 MakeSlice(kNextSerialNumberKey), | 455 MakeSlice(kNextSerialNumberKey), |
445 MakeSlice(base::Int64ToString(next_serial_number))); | 456 MakeSlice(serial_number_str)); |
446 if (status.ok()) { | 457 if (status.ok()) { |
447 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 458 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
448 return; | 459 return; |
449 } | 460 } |
450 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); | 461 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); |
451 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 462 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
452 } | 463 } |
453 | 464 |
454 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, | 465 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, |
455 uint64* security_token) { | 466 uint64* security_token) { |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 removed_message_counts.begin(); | 800 removed_message_counts.begin(); |
790 iter != removed_message_counts.end(); ++iter) { | 801 iter != removed_message_counts.end(); ++iter) { |
791 DCHECK_NE(app_message_counts_.count(iter->first), 0U); | 802 DCHECK_NE(app_message_counts_.count(iter->first), 0U); |
792 app_message_counts_[iter->first] -= iter->second; | 803 app_message_counts_[iter->first] -= iter->second; |
793 DCHECK_GE(app_message_counts_[iter->first], 0); | 804 DCHECK_GE(app_message_counts_[iter->first], 0); |
794 } | 805 } |
795 callback.Run(true); | 806 callback.Run(true); |
796 } | 807 } |
797 | 808 |
798 } // namespace gcm | 809 } // namespace gcm |
OLD | NEW |