| 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 |