| 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 17 matching lines...) Expand all Loading... |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 // Limit to the number of outstanding messages per app. | 30 // Limit to the number of outstanding messages per app. |
| 31 const int kMessagesPerAppLimit = 20; | 31 const int kMessagesPerAppLimit = 20; |
| 32 | 32 |
| 33 // ---- LevelDB keys. ---- | 33 // ---- LevelDB keys. ---- |
| 34 // Key for this device's android id. | 34 // Key for this device's android id. |
| 35 const char kDeviceAIDKey[] = "device_aid_key"; | 35 const char kDeviceAIDKey[] = "device_aid_key"; |
| 36 // Key for this device's android security token. | 36 // Key for this device's android security token. |
| 37 const char kDeviceTokenKey[] = "device_token_key"; | 37 const char kDeviceTokenKey[] = "device_token_key"; |
| 38 // Lowest lexicographically ordered app ids. |
| 39 // Used for prefixing app id. |
| 40 const char kRegistrationKeyStart[] = "reg1-"; |
| 41 // Key guaranteed to be higher than all app ids. |
| 42 // Used for limiting iteration. |
| 43 const char kRegistrationKeyEnd[] = "reg2-"; |
| 38 // Lowest lexicographically ordered incoming message key. | 44 // Lowest lexicographically ordered incoming message key. |
| 39 // Used for prefixing messages. | 45 // Used for prefixing messages. |
| 40 const char kIncomingMsgKeyStart[] = "incoming1-"; | 46 const char kIncomingMsgKeyStart[] = "incoming1-"; |
| 41 // Key guaranteed to be higher than all incoming message keys. | 47 // Key guaranteed to be higher than all incoming message keys. |
| 42 // Used for limiting iteration. | 48 // Used for limiting iteration. |
| 43 const char kIncomingMsgKeyEnd[] = "incoming2-"; | 49 const char kIncomingMsgKeyEnd[] = "incoming2-"; |
| 44 // Key for next serial number assigned to the user. | |
| 45 const char kNextSerialNumberKey[] = "next_serial_number_key"; | |
| 46 // Lowest lexicographically ordered outgoing message key. | 50 // Lowest lexicographically ordered outgoing message key. |
| 47 // Used for prefixing outgoing messages. | 51 // Used for prefixing outgoing messages. |
| 48 const char kOutgoingMsgKeyStart[] = "outgoing1-"; | 52 const char kOutgoingMsgKeyStart[] = "outgoing1-"; |
| 49 // Key guaranteed to be higher than all outgoing message keys. | 53 // Key guaranteed to be higher than all outgoing message keys. |
| 50 // Used for limiting iteration. | 54 // Used for limiting iteration. |
| 51 const char kOutgoingMsgKeyEnd[] = "outgoing2-"; | 55 const char kOutgoingMsgKeyEnd[] = "outgoing2-"; |
| 52 // Lowest lexicographically ordered username. | |
| 53 // Used for prefixing username to serial number mappings. | |
| 54 const char kUserSerialNumberKeyStart[] = "user1-"; | |
| 55 // Key guaranteed to be higher than all usernames. | |
| 56 // Used for limiting iteration. | |
| 57 const char kUserSerialNumberKeyEnd[] = "user2-"; | |
| 58 | 56 |
| 59 // Value indicating that serial number was not assigned. | 57 std::string MakeRegistrationKey(const std::string& app_id) { |
| 60 const int64 kSerialNumberMissing = -1LL; | 58 return kRegistrationKeyStart + app_id; |
| 59 } |
| 60 |
| 61 std::string ParseRegistrationKey(const std::string& key) { |
| 62 return key.substr(arraysize(kRegistrationKeyStart) - 1); |
| 63 } |
| 61 | 64 |
| 62 std::string MakeIncomingKey(const std::string& persistent_id) { | 65 std::string MakeIncomingKey(const std::string& persistent_id) { |
| 63 return kIncomingMsgKeyStart + persistent_id; | 66 return kIncomingMsgKeyStart + persistent_id; |
| 64 } | 67 } |
| 65 | 68 |
| 66 std::string MakeOutgoingKey(const std::string& persistent_id) { | 69 std::string MakeOutgoingKey(const std::string& persistent_id) { |
| 67 return kOutgoingMsgKeyStart + persistent_id; | 70 return kOutgoingMsgKeyStart + persistent_id; |
| 68 } | 71 } |
| 69 | 72 |
| 70 std::string MakeUserSerialNumberKey(const std::string& username) { | |
| 71 return kUserSerialNumberKeyStart + username; | |
| 72 } | |
| 73 | |
| 74 std::string ParseOutgoingKey(const std::string& key) { | 73 std::string ParseOutgoingKey(const std::string& key) { |
| 75 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); | 74 return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); |
| 76 } | 75 } |
| 77 | 76 |
| 78 std::string ParseUsername(const std::string& key) { | |
| 79 return key.substr(arraysize(kUserSerialNumberKeyStart) - 1); | |
| 80 } | |
| 81 | |
| 82 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore | 77 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore |
| 83 // outlive the slice. | 78 // outlive the slice. |
| 84 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. | 79 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid. |
| 85 leveldb::Slice MakeSlice(const base::StringPiece& s) { | 80 leveldb::Slice MakeSlice(const base::StringPiece& s) { |
| 86 return leveldb::Slice(s.begin(), s.size()); | 81 return leveldb::Slice(s.begin(), s.size()); |
| 87 } | 82 } |
| 88 | 83 |
| 89 } // namespace | 84 } // namespace |
| 90 | 85 |
| 91 class GCMStoreImpl::Backend | 86 class GCMStoreImpl::Backend |
| 92 : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { | 87 : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { |
| 93 public: | 88 public: |
| 94 Backend(const base::FilePath& path, | 89 Backend(const base::FilePath& path, |
| 95 scoped_refptr<base::SequencedTaskRunner> foreground_runner); | 90 scoped_refptr<base::SequencedTaskRunner> foreground_runner); |
| 96 | 91 |
| 97 // Blocking implementations of GCMStoreImpl methods. | 92 // Blocking implementations of GCMStoreImpl methods. |
| 98 void Load(const LoadCallback& callback); | 93 void Load(const LoadCallback& callback); |
| 99 void Close(); | 94 void Close(); |
| 100 void Destroy(const UpdateCallback& callback); | 95 void Destroy(const UpdateCallback& callback); |
| 101 void SetDeviceCredentials(uint64 device_android_id, | 96 void SetDeviceCredentials(uint64 device_android_id, |
| 102 uint64 device_security_token, | 97 uint64 device_security_token, |
| 103 const UpdateCallback& callback); | 98 const UpdateCallback& callback); |
| 99 void AddRegistration(const std::string& app_id, |
| 100 const linked_ptr<RegistrationInfo>& registration, |
| 101 const UpdateCallback& callback); |
| 102 void RemoveRegistration(const std::string& app_id, |
| 103 const UpdateCallback& callback); |
| 104 void AddIncomingMessage(const std::string& persistent_id, | 104 void AddIncomingMessage(const std::string& persistent_id, |
| 105 const UpdateCallback& callback); | 105 const UpdateCallback& callback); |
| 106 void RemoveIncomingMessages(const PersistentIdList& persistent_ids, | 106 void RemoveIncomingMessages(const PersistentIdList& persistent_ids, |
| 107 const UpdateCallback& callback); | 107 const UpdateCallback& callback); |
| 108 void AddOutgoingMessage(const std::string& persistent_id, | 108 void AddOutgoingMessage(const std::string& persistent_id, |
| 109 const MCSMessage& message, | 109 const MCSMessage& message, |
| 110 const UpdateCallback& callback); | 110 const UpdateCallback& callback); |
| 111 void RemoveOutgoingMessages( | 111 void RemoveOutgoingMessages( |
| 112 const PersistentIdList& persistent_ids, | 112 const PersistentIdList& persistent_ids, |
| 113 const base::Callback<void(bool, const AppIdToMessageCountMap&)> | 113 const base::Callback<void(bool, const AppIdToMessageCountMap&)> |
| 114 callback); | 114 callback); |
| 115 void AddUserSerialNumber(const std::string& username, | 115 void AddUserSerialNumber(const std::string& username, |
| 116 int64 serial_number, | 116 int64 serial_number, |
| 117 const UpdateCallback& callback); | 117 const UpdateCallback& callback); |
| 118 void RemoveUserSerialNumber(const std::string& username, | 118 void RemoveUserSerialNumber(const std::string& username, |
| 119 const UpdateCallback& callback); | 119 const UpdateCallback& callback); |
| 120 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); | 120 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); |
| 121 | 121 |
| 122 private: | 122 private: |
| 123 friend class base::RefCountedThreadSafe<Backend>; | 123 friend class base::RefCountedThreadSafe<Backend>; |
| 124 ~Backend(); | 124 ~Backend(); |
| 125 | 125 |
| 126 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); | 126 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); |
| 127 bool LoadRegistrations(RegistrationInfoMap* registrations); |
| 127 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); | 128 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); |
| 128 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); | 129 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); |
| 129 bool LoadNextSerialNumber(int64* next_serial_number); | |
| 130 bool LoadUserSerialNumberMap( | |
| 131 std::map<std::string, int64>* user_serial_number_map); | |
| 132 | 130 |
| 133 const base::FilePath path_; | 131 const base::FilePath path_; |
| 134 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; | 132 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; |
| 135 | 133 |
| 136 scoped_ptr<leveldb::DB> db_; | 134 scoped_ptr<leveldb::DB> db_; |
| 137 }; | 135 }; |
| 138 | 136 |
| 139 GCMStoreImpl::Backend::Backend( | 137 GCMStoreImpl::Backend::Backend( |
| 140 const base::FilePath& path, | 138 const base::FilePath& path, |
| 141 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) | 139 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 164 << status.ToString(); | 162 << status.ToString(); |
| 165 foreground_task_runner_->PostTask(FROM_HERE, | 163 foreground_task_runner_->PostTask(FROM_HERE, |
| 166 base::Bind(callback, | 164 base::Bind(callback, |
| 167 base::Passed(&result))); | 165 base::Passed(&result))); |
| 168 return; | 166 return; |
| 169 } | 167 } |
| 170 db_.reset(db); | 168 db_.reset(db); |
| 171 | 169 |
| 172 if (!LoadDeviceCredentials(&result->device_android_id, | 170 if (!LoadDeviceCredentials(&result->device_android_id, |
| 173 &result->device_security_token) || | 171 &result->device_security_token) || |
| 172 !LoadRegistrations(&result->registrations) || |
| 174 !LoadIncomingMessages(&result->incoming_messages) || | 173 !LoadIncomingMessages(&result->incoming_messages) || |
| 175 !LoadOutgoingMessages(&result->outgoing_messages) || | 174 !LoadOutgoingMessages(&result->outgoing_messages)) { |
| 176 !LoadNextSerialNumber( | |
| 177 &result->serial_number_mappings.next_serial_number) || | |
| 178 !LoadUserSerialNumberMap( | |
| 179 &result->serial_number_mappings.user_serial_numbers)) { | |
| 180 result->device_android_id = 0; | 175 result->device_android_id = 0; |
| 181 result->device_security_token = 0; | 176 result->device_security_token = 0; |
| 177 result->registrations.clear(); |
| 182 result->incoming_messages.clear(); | 178 result->incoming_messages.clear(); |
| 183 result->outgoing_messages.clear(); | 179 result->outgoing_messages.clear(); |
| 184 foreground_task_runner_->PostTask(FROM_HERE, | 180 foreground_task_runner_->PostTask(FROM_HERE, |
| 185 base::Bind(callback, | 181 base::Bind(callback, |
| 186 base::Passed(&result))); | 182 base::Passed(&result))); |
| 187 return; | 183 return; |
| 188 } | 184 } |
| 189 | 185 |
| 190 // Only record histograms if GCM had already been set up for this device. | 186 // Only record histograms if GCM had already been set up for this device. |
| 191 if (result->device_android_id != 0 && result->device_security_token != 0) { | 187 if (result->device_android_id != 0 && result->device_security_token != 0) { |
| 192 int64 file_size = 0; | 188 int64 file_size = 0; |
| 193 if (base::GetFileSize(path_, &file_size)) { | 189 if (base::GetFileSize(path_, &file_size)) { |
| 194 UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", | 190 UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", |
| 195 static_cast<int>(file_size / 1024)); | 191 static_cast<int>(file_size / 1024)); |
| 196 } | 192 } |
| 193 UMA_HISTOGRAM_COUNTS("GCM.RestoredRegistrations", |
| 194 result->registrations.size()); |
| 197 UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", | 195 UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", |
| 198 result->outgoing_messages.size()); | 196 result->outgoing_messages.size()); |
| 199 UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", | 197 UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", |
| 200 result->incoming_messages.size()); | 198 result->incoming_messages.size()); |
| 201 UMA_HISTOGRAM_COUNTS( | |
| 202 "GCM.NumUsers", | |
| 203 result->serial_number_mappings.user_serial_numbers.size()); | |
| 204 } | 199 } |
| 205 | 200 |
| 206 DVLOG(1) << "Succeeded in loading " << result->incoming_messages.size() | 201 DVLOG(1) << "Succeeded in loading " << result->registrations.size() |
| 202 << " registrations, " |
| 203 << result->incoming_messages.size() |
| 207 << " unacknowledged incoming messages and " | 204 << " unacknowledged incoming messages and " |
| 208 << result->outgoing_messages.size() | 205 << result->outgoing_messages.size() |
| 209 << " unacknowledged outgoing messages."; | 206 << " unacknowledged outgoing messages."; |
| 210 result->success = true; | 207 result->success = true; |
| 211 foreground_task_runner_->PostTask(FROM_HERE, | 208 foreground_task_runner_->PostTask(FROM_HERE, |
| 212 base::Bind(callback, | 209 base::Bind(callback, |
| 213 base::Passed(&result))); | 210 base::Passed(&result))); |
| 214 return; | 211 return; |
| 215 } | 212 } |
| 216 | 213 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); | 256 write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); |
| 260 } | 257 } |
| 261 if (s.ok()) { | 258 if (s.ok()) { |
| 262 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 259 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
| 263 return; | 260 return; |
| 264 } | 261 } |
| 265 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); | 262 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); |
| 266 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 263 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 267 } | 264 } |
| 268 | 265 |
| 266 void GCMStoreImpl::Backend::AddRegistration( |
| 267 const std::string& app_id, |
| 268 const linked_ptr<RegistrationInfo>& registration, |
| 269 const UpdateCallback& callback) { |
| 270 DVLOG(1) << "Saving registration info for app: " << app_id; |
| 271 if (!db_.get()) { |
| 272 LOG(ERROR) << "GCMStore db doesn't exist."; |
| 273 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 274 return; |
| 275 } |
| 276 leveldb::WriteOptions write_options; |
| 277 write_options.sync = true; |
| 278 |
| 279 std::string key = MakeRegistrationKey(app_id); |
| 280 std::string value = registration->SerializeAsString(); |
| 281 const leveldb::Status status = db_->Put(write_options, |
| 282 MakeSlice(key), |
| 283 MakeSlice(value)); |
| 284 if (status.ok()) { |
| 285 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
| 286 return; |
| 287 } |
| 288 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); |
| 289 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 290 } |
| 291 |
| 292 void GCMStoreImpl::Backend::RemoveRegistration(const std::string& app_id, |
| 293 const UpdateCallback& callback) { |
| 294 if (!db_.get()) { |
| 295 LOG(ERROR) << "GCMStore db doesn't exist."; |
| 296 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 297 return; |
| 298 } |
| 299 leveldb::WriteOptions write_options; |
| 300 write_options.sync = true; |
| 301 |
| 302 leveldb::Status status = db_->Delete(write_options, MakeSlice(app_id)); |
| 303 if (status.ok()) { |
| 304 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
| 305 return; |
| 306 } |
| 307 LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); |
| 308 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 309 } |
| 310 |
| 269 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, | 311 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, |
| 270 const UpdateCallback& callback) { | 312 const UpdateCallback& callback) { |
| 271 DVLOG(1) << "Saving incoming message with id " << persistent_id; | 313 DVLOG(1) << "Saving incoming message with id " << persistent_id; |
| 272 if (!db_.get()) { | 314 if (!db_.get()) { |
| 273 LOG(ERROR) << "GCMStore db doesn't exist."; | 315 LOG(ERROR) << "GCMStore db doesn't exist."; |
| 274 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 316 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 275 return; | 317 return; |
| 276 } | 318 } |
| 277 | 319 |
| 278 leveldb::WriteOptions write_options; | 320 leveldb::WriteOptions write_options; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 removed_message_counts)); | 438 removed_message_counts)); |
| 397 return; | 439 return; |
| 398 } | 440 } |
| 399 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); | 441 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); |
| 400 foreground_task_runner_->PostTask(FROM_HERE, | 442 foreground_task_runner_->PostTask(FROM_HERE, |
| 401 base::Bind(callback, | 443 base::Bind(callback, |
| 402 false, | 444 false, |
| 403 AppIdToMessageCountMap())); | 445 AppIdToMessageCountMap())); |
| 404 } | 446 } |
| 405 | 447 |
| 406 void GCMStoreImpl::Backend::AddUserSerialNumber( | |
| 407 const std::string& username, | |
| 408 int64 serial_number, | |
| 409 const UpdateCallback& callback) { | |
| 410 DVLOG(1) << "Saving username to serial number mapping for user: " << username; | |
| 411 if (!db_.get()) { | |
| 412 LOG(ERROR) << "GCMStore db doesn't exist."; | |
| 413 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 414 return; | |
| 415 } | |
| 416 leveldb::WriteOptions write_options; | |
| 417 write_options.sync = true; | |
| 418 | |
| 419 std::string key = MakeUserSerialNumberKey(username); | |
| 420 std::string serial_number_str = base::Int64ToString(serial_number); | |
| 421 const leveldb::Status status = | |
| 422 db_->Put(write_options, | |
| 423 MakeSlice(key), | |
| 424 MakeSlice(serial_number_str)); | |
| 425 if (status.ok()) { | |
| 426 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | |
| 427 return; | |
| 428 } | |
| 429 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); | |
| 430 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 431 } | |
| 432 | |
| 433 void GCMStoreImpl::Backend::RemoveUserSerialNumber( | |
| 434 const std::string& username, | |
| 435 const UpdateCallback& callback) { | |
| 436 if (!db_.get()) { | |
| 437 LOG(ERROR) << "GCMStore db doesn't exist."; | |
| 438 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 439 return; | |
| 440 } | |
| 441 leveldb::WriteOptions write_options; | |
| 442 write_options.sync = true; | |
| 443 | |
| 444 leveldb::Status status = db_->Delete(write_options, MakeSlice(username)); | |
| 445 if (status.ok()) { | |
| 446 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | |
| 447 return; | |
| 448 } | |
| 449 LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); | |
| 450 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 451 } | |
| 452 | |
| 453 void GCMStoreImpl::Backend::SetNextSerialNumber( | |
| 454 int64 next_serial_number, | |
| 455 const UpdateCallback& callback) { | |
| 456 DVLOG(1) << "Updating the value of next user serial number to: " | |
| 457 << next_serial_number; | |
| 458 if (!db_.get()) { | |
| 459 LOG(ERROR) << "GCMStore db doesn't exist."; | |
| 460 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 461 return; | |
| 462 } | |
| 463 leveldb::WriteOptions write_options; | |
| 464 write_options.sync = true; | |
| 465 | |
| 466 std::string serial_number_str = base::Int64ToString(next_serial_number); | |
| 467 const leveldb::Status status = | |
| 468 db_->Put(write_options, | |
| 469 MakeSlice(kNextSerialNumberKey), | |
| 470 MakeSlice(serial_number_str)); | |
| 471 if (status.ok()) { | |
| 472 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | |
| 473 return; | |
| 474 } | |
| 475 LOG(ERROR) << "LevelDB put failed: " << status.ToString(); | |
| 476 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 477 } | |
| 478 | |
| 479 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, | 448 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, |
| 480 uint64* security_token) { | 449 uint64* security_token) { |
| 481 leveldb::ReadOptions read_options; | 450 leveldb::ReadOptions read_options; |
| 482 read_options.verify_checksums = true; | 451 read_options.verify_checksums = true; |
| 483 | 452 |
| 484 std::string result; | 453 std::string result; |
| 485 leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); | 454 leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); |
| 486 if (s.ok()) { | 455 if (s.ok()) { |
| 487 if (!base::StringToUint64(result, android_id)) { | 456 if (!base::StringToUint64(result, android_id)) { |
| 488 LOG(ERROR) << "Failed to restore device id."; | 457 LOG(ERROR) << "Failed to restore device id."; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 503 | 472 |
| 504 if (s.IsNotFound()) { | 473 if (s.IsNotFound()) { |
| 505 DVLOG(1) << "No credentials found."; | 474 DVLOG(1) << "No credentials found."; |
| 506 return true; | 475 return true; |
| 507 } | 476 } |
| 508 | 477 |
| 509 LOG(ERROR) << "Error reading credentials from store."; | 478 LOG(ERROR) << "Error reading credentials from store."; |
| 510 return false; | 479 return false; |
| 511 } | 480 } |
| 512 | 481 |
| 482 bool GCMStoreImpl::Backend::LoadRegistrations( |
| 483 RegistrationInfoMap* registrations) { |
| 484 leveldb::ReadOptions read_options; |
| 485 read_options.verify_checksums = true; |
| 486 |
| 487 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); |
| 488 for (iter->Seek(MakeSlice(kRegistrationKeyStart)); |
| 489 iter->Valid() && iter->key().ToString() < kRegistrationKeyEnd; |
| 490 iter->Next()) { |
| 491 leveldb::Slice s = iter->value(); |
| 492 if (s.size() <= 1) { |
| 493 LOG(ERROR) << "Error reading registration with key " << s.ToString(); |
| 494 return false; |
| 495 } |
| 496 std::string app_id = ParseRegistrationKey(iter->key().ToString()); |
| 497 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); |
| 498 if (!registration->ParseFromString(iter->value().ToString())) { |
| 499 LOG(ERROR) << "Failed to parse registration with app id " << app_id; |
| 500 return false; |
| 501 } |
| 502 DVLOG(1) << "Found registration with app id " << app_id; |
| 503 (*registrations)[app_id] = registration; |
| 504 } |
| 505 |
| 506 return true; |
| 507 } |
| 508 |
| 513 bool GCMStoreImpl::Backend::LoadIncomingMessages( | 509 bool GCMStoreImpl::Backend::LoadIncomingMessages( |
| 514 std::vector<std::string>* incoming_messages) { | 510 std::vector<std::string>* incoming_messages) { |
| 515 leveldb::ReadOptions read_options; | 511 leveldb::ReadOptions read_options; |
| 516 read_options.verify_checksums = true; | 512 read_options.verify_checksums = true; |
| 517 | 513 |
| 518 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); | 514 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); |
| 519 for (iter->Seek(MakeSlice(kIncomingMsgKeyStart)); | 515 for (iter->Seek(MakeSlice(kIncomingMsgKeyStart)); |
| 520 iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd; | 516 iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd; |
| 521 iter->Next()) { | 517 iter->Next()) { |
| 522 leveldb::Slice s = iter->value(); | 518 leveldb::Slice s = iter->value(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 return false; | 553 return false; |
| 558 } | 554 } |
| 559 DVLOG(1) << "Found outgoing message with id " << id << " of type " | 555 DVLOG(1) << "Found outgoing message with id " << id << " of type " |
| 560 << base::IntToString(tag); | 556 << base::IntToString(tag); |
| 561 (*outgoing_messages)[id] = make_linked_ptr(message.release()); | 557 (*outgoing_messages)[id] = make_linked_ptr(message.release()); |
| 562 } | 558 } |
| 563 | 559 |
| 564 return true; | 560 return true; |
| 565 } | 561 } |
| 566 | 562 |
| 567 bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) { | |
| 568 leveldb::ReadOptions read_options; | |
| 569 read_options.verify_checksums = true; | |
| 570 | |
| 571 std::string result; | |
| 572 leveldb::Status status = | |
| 573 db_->Get(read_options, MakeSlice(kNextSerialNumberKey), &result); | |
| 574 if (status.ok()) { | |
| 575 if (!base::StringToInt64(result, next_serial_number)) { | |
| 576 LOG(ERROR) << "Failed to restore the next serial number."; | |
| 577 return false; | |
| 578 } | |
| 579 return true; | |
| 580 } | |
| 581 | |
| 582 if (status.IsNotFound()) { | |
| 583 DVLOG(1) << "No next serial number found."; | |
| 584 return true; | |
| 585 } | |
| 586 | |
| 587 LOG(ERROR) << "Error when reading the next serial number."; | |
| 588 return false; | |
| 589 } | |
| 590 | |
| 591 bool GCMStoreImpl::Backend::LoadUserSerialNumberMap( | |
| 592 std::map<std::string, int64>* user_serial_number_map) { | |
| 593 leveldb::ReadOptions read_options; | |
| 594 read_options.verify_checksums = true; | |
| 595 | |
| 596 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); | |
| 597 for (iter->Seek(MakeSlice(kUserSerialNumberKeyStart)); | |
| 598 iter->Valid() && iter->key().ToString() < kUserSerialNumberKeyEnd; | |
| 599 iter->Next()) { | |
| 600 std::string username = ParseUsername(iter->key().ToString()); | |
| 601 if (username.empty()) { | |
| 602 LOG(ERROR) << "Error reading username. It should not be empty."; | |
| 603 return false; | |
| 604 } | |
| 605 std::string serial_number_string = iter->value().ToString(); | |
| 606 int64 serial_number = kSerialNumberMissing; | |
| 607 if (!base::StringToInt64(serial_number_string, &serial_number)) { | |
| 608 LOG(ERROR) << "Error reading user serial number for user: " << username; | |
| 609 return false; | |
| 610 } | |
| 611 | |
| 612 (*user_serial_number_map)[username] = serial_number; | |
| 613 } | |
| 614 | |
| 615 return true; | |
| 616 } | |
| 617 | |
| 618 GCMStoreImpl::GCMStoreImpl( | 563 GCMStoreImpl::GCMStoreImpl( |
| 619 bool use_mock_keychain, | 564 bool use_mock_keychain, |
| 620 const base::FilePath& path, | 565 const base::FilePath& path, |
| 621 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | 566 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
| 622 : backend_(new Backend(path, base::MessageLoopProxy::current())), | 567 : backend_(new Backend(path, base::MessageLoopProxy::current())), |
| 623 blocking_task_runner_(blocking_task_runner), | 568 blocking_task_runner_(blocking_task_runner), |
| 624 weak_ptr_factory_(this) { | 569 weak_ptr_factory_(this) { |
| 625 // On OSX, prevent the Keychain permissions popup during unit tests. | 570 // On OSX, prevent the Keychain permissions popup during unit tests. |
| 626 #if defined(OS_MACOSX) | 571 #if defined(OS_MACOSX) |
| 627 OSCrypt::UseMockKeychain(use_mock_keychain); | 572 OSCrypt::UseMockKeychain(use_mock_keychain); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 657 const UpdateCallback& callback) { | 602 const UpdateCallback& callback) { |
| 658 blocking_task_runner_->PostTask( | 603 blocking_task_runner_->PostTask( |
| 659 FROM_HERE, | 604 FROM_HERE, |
| 660 base::Bind(&GCMStoreImpl::Backend::SetDeviceCredentials, | 605 base::Bind(&GCMStoreImpl::Backend::SetDeviceCredentials, |
| 661 backend_, | 606 backend_, |
| 662 device_android_id, | 607 device_android_id, |
| 663 device_security_token, | 608 device_security_token, |
| 664 callback)); | 609 callback)); |
| 665 } | 610 } |
| 666 | 611 |
| 612 void GCMStoreImpl::AddRegistration( |
| 613 const std::string& app_id, |
| 614 const linked_ptr<RegistrationInfo>& registration, |
| 615 const UpdateCallback& callback) { |
| 616 blocking_task_runner_->PostTask( |
| 617 FROM_HERE, |
| 618 base::Bind(&GCMStoreImpl::Backend::AddRegistration, |
| 619 backend_, |
| 620 app_id, |
| 621 registration, |
| 622 callback)); |
| 623 } |
| 624 |
| 625 void GCMStoreImpl::RemoveRegistration(const std::string& app_id, |
| 626 const UpdateCallback& callback) { |
| 627 blocking_task_runner_->PostTask( |
| 628 FROM_HERE, |
| 629 base::Bind(&GCMStoreImpl::Backend::RemoveRegistration, |
| 630 backend_, |
| 631 app_id, |
| 632 callback)); |
| 633 } |
| 634 |
| 667 void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id, | 635 void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id, |
| 668 const UpdateCallback& callback) { | 636 const UpdateCallback& callback) { |
| 669 blocking_task_runner_->PostTask( | 637 blocking_task_runner_->PostTask( |
| 670 FROM_HERE, | 638 FROM_HERE, |
| 671 base::Bind(&GCMStoreImpl::Backend::AddIncomingMessage, | 639 base::Bind(&GCMStoreImpl::Backend::AddIncomingMessage, |
| 672 backend_, | 640 backend_, |
| 673 persistent_id, | 641 persistent_id, |
| 674 callback)); | 642 callback)); |
| 675 } | 643 } |
| 676 | 644 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 blocking_task_runner_->PostTask( | 727 blocking_task_runner_->PostTask( |
| 760 FROM_HERE, | 728 FROM_HERE, |
| 761 base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, | 729 base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, |
| 762 backend_, | 730 backend_, |
| 763 persistent_ids, | 731 persistent_ids, |
| 764 base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, | 732 base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, |
| 765 weak_ptr_factory_.GetWeakPtr(), | 733 weak_ptr_factory_.GetWeakPtr(), |
| 766 callback))); | 734 callback))); |
| 767 } | 735 } |
| 768 | 736 |
| 769 void GCMStoreImpl::SetNextSerialNumber(int64 next_serial_number, | |
| 770 const UpdateCallback& callback) { | |
| 771 blocking_task_runner_->PostTask( | |
| 772 FROM_HERE, | |
| 773 base::Bind(&GCMStoreImpl::Backend::SetNextSerialNumber, | |
| 774 backend_, | |
| 775 next_serial_number, | |
| 776 callback)); | |
| 777 } | |
| 778 | |
| 779 void GCMStoreImpl::AddUserSerialNumber(const std::string& username, | |
| 780 int64 serial_number, | |
| 781 const UpdateCallback& callback) { | |
| 782 blocking_task_runner_->PostTask( | |
| 783 FROM_HERE, | |
| 784 base::Bind(&GCMStoreImpl::Backend::AddUserSerialNumber, | |
| 785 backend_, | |
| 786 username, | |
| 787 serial_number, | |
| 788 callback)); | |
| 789 } | |
| 790 | |
| 791 void GCMStoreImpl::RemoveUserSerialNumber(const std::string& username, | |
| 792 const UpdateCallback& callback) { | |
| 793 blocking_task_runner_->PostTask( | |
| 794 FROM_HERE, | |
| 795 base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber, | |
| 796 backend_, | |
| 797 username, | |
| 798 callback)); | |
| 799 } | |
| 800 | |
| 801 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, | 737 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, |
| 802 scoped_ptr<LoadResult> result) { | 738 scoped_ptr<LoadResult> result) { |
| 803 if (!result->success) { | 739 if (!result->success) { |
| 804 callback.Run(result.Pass()); | 740 callback.Run(result.Pass()); |
| 805 return; | 741 return; |
| 806 } | 742 } |
| 807 int num_throttled_apps = 0; | 743 int num_throttled_apps = 0; |
| 808 for (OutgoingMessageMap::const_iterator | 744 for (OutgoingMessageMap::const_iterator |
| 809 iter = result->outgoing_messages.begin(); | 745 iter = result->outgoing_messages.begin(); |
| 810 iter != result->outgoing_messages.end(); ++iter) { | 746 iter != result->outgoing_messages.end(); ++iter) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 removed_message_counts.begin(); | 781 removed_message_counts.begin(); |
| 846 iter != removed_message_counts.end(); ++iter) { | 782 iter != removed_message_counts.end(); ++iter) { |
| 847 DCHECK_NE(app_message_counts_.count(iter->first), 0U); | 783 DCHECK_NE(app_message_counts_.count(iter->first), 0U); |
| 848 app_message_counts_[iter->first] -= iter->second; | 784 app_message_counts_[iter->first] -= iter->second; |
| 849 DCHECK_GE(app_message_counts_[iter->first], 0); | 785 DCHECK_GE(app_message_counts_[iter->first], 0); |
| 850 } | 786 } |
| 851 callback.Run(true); | 787 callback.Run(true); |
| 852 } | 788 } |
| 853 | 789 |
| 854 } // namespace gcm | 790 } // namespace gcm |
| OLD | NEW |