| 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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 void RemoveUserSerialNumber(const std::string& username, | 117 void RemoveUserSerialNumber(const std::string& username, |
| 118 const UpdateCallback& callback); | 118 const UpdateCallback& callback); |
| 119 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); | 119 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); |
| 120 | 120 |
| 121 private: | 121 private: |
| 122 friend class base::RefCountedThreadSafe<Backend>; | 122 friend class base::RefCountedThreadSafe<Backend>; |
| 123 ~Backend(); | 123 ~Backend(); |
| 124 | 124 |
| 125 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); | 125 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); |
| 126 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); | 126 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); |
| 127 bool LoadOutgoingMessages( | 127 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); |
| 128 std::map<std::string, google::protobuf::MessageLite*>* outgoing_messages); | |
| 129 bool LoadNextSerialNumber(int64* next_serial_number); | 128 bool LoadNextSerialNumber(int64* next_serial_number); |
| 130 bool LoadUserSerialNumberMap( | 129 bool LoadUserSerialNumberMap( |
| 131 std::map<std::string, int64>* user_serial_number_map); | 130 std::map<std::string, int64>* user_serial_number_map); |
| 132 | 131 |
| 133 const base::FilePath path_; | 132 const base::FilePath path_; |
| 134 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; | 133 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; |
| 135 | 134 |
| 136 scoped_ptr<leveldb::DB> db_; | 135 scoped_ptr<leveldb::DB> db_; |
| 137 }; | 136 }; |
| 138 | 137 |
| 139 GCMStoreImpl::Backend::Backend( | 138 GCMStoreImpl::Backend::Backend( |
| 140 const base::FilePath& path, | 139 const base::FilePath& path, |
| 141 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) | 140 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) |
| 142 : path_(path), foreground_task_runner_(foreground_task_runner) {} | 141 : path_(path), foreground_task_runner_(foreground_task_runner) {} |
| 143 | 142 |
| 144 GCMStoreImpl::Backend::~Backend() {} | 143 GCMStoreImpl::Backend::~Backend() {} |
| 145 | 144 |
| 146 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { | 145 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { |
| 147 LoadResult result; | 146 scoped_ptr<LoadResult> result(new LoadResult()); |
| 148 if (db_.get()) { | 147 if (db_.get()) { |
| 149 LOG(ERROR) << "Attempting to reload open database."; | 148 LOG(ERROR) << "Attempting to reload open database."; |
| 150 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); | 149 foreground_task_runner_->PostTask(FROM_HERE, |
| 150 base::Bind(callback, |
| 151 base::Passed(&result))); |
| 151 return; | 152 return; |
| 152 } | 153 } |
| 153 | 154 |
| 154 leveldb::Options options; | 155 leveldb::Options options; |
| 155 options.create_if_missing = true; | 156 options.create_if_missing = true; |
| 156 leveldb::DB* db; | 157 leveldb::DB* db; |
| 157 leveldb::Status status = | 158 leveldb::Status status = |
| 158 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); | 159 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); |
| 159 UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); | 160 UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); |
| 160 if (!status.ok()) { | 161 if (!status.ok()) { |
| 161 LOG(ERROR) << "Failed to open database " << path_.value() << ": " | 162 LOG(ERROR) << "Failed to open database " << path_.value() << ": " |
| 162 << status.ToString(); | 163 << status.ToString(); |
| 163 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); | 164 foreground_task_runner_->PostTask(FROM_HERE, |
| 165 base::Bind(callback, |
| 166 base::Passed(&result))); |
| 164 return; | 167 return; |
| 165 } | 168 } |
| 166 db_.reset(db); | 169 db_.reset(db); |
| 167 | 170 |
| 168 if (!LoadDeviceCredentials(&result.device_android_id, | 171 if (!LoadDeviceCredentials(&result->device_android_id, |
| 169 &result.device_security_token) || | 172 &result->device_security_token) || |
| 170 !LoadIncomingMessages(&result.incoming_messages) || | 173 !LoadIncomingMessages(&result->incoming_messages) || |
| 171 !LoadOutgoingMessages(&result.outgoing_messages) || | 174 !LoadOutgoingMessages(&result->outgoing_messages) || |
| 172 !LoadNextSerialNumber( | 175 !LoadNextSerialNumber( |
| 173 &result.serial_number_mappings.next_serial_number) || | 176 &result->serial_number_mappings.next_serial_number) || |
| 174 !LoadUserSerialNumberMap( | 177 !LoadUserSerialNumberMap( |
| 175 &result.serial_number_mappings.user_serial_numbers)) { | 178 &result->serial_number_mappings.user_serial_numbers)) { |
| 176 result.device_android_id = 0; | 179 result->device_android_id = 0; |
| 177 result.device_security_token = 0; | 180 result->device_security_token = 0; |
| 178 result.incoming_messages.clear(); | 181 result->incoming_messages.clear(); |
| 179 STLDeleteContainerPairSecondPointers(result.outgoing_messages.begin(), | 182 result->outgoing_messages.clear(); |
| 180 result.outgoing_messages.end()); | 183 foreground_task_runner_->PostTask(FROM_HERE, |
| 181 result.outgoing_messages.clear(); | 184 base::Bind(callback, |
| 182 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); | 185 base::Passed(&result))); |
| 183 return; | 186 return; |
| 184 } | 187 } |
| 185 | 188 |
| 186 // Only record histograms if GCM had already been set up for this device. | 189 // Only record histograms if GCM had already been set up for this device. |
| 187 if (result.device_android_id != 0 && result.device_security_token != 0) { | 190 if (result->device_android_id != 0 && result->device_security_token != 0) { |
| 188 int64 file_size = 0; | 191 int64 file_size = 0; |
| 189 if (base::GetFileSize(path_, &file_size)) { | 192 if (base::GetFileSize(path_, &file_size)) { |
| 190 UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", | 193 UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", |
| 191 static_cast<int>(file_size / 1024)); | 194 static_cast<int>(file_size / 1024)); |
| 192 } | 195 } |
| 193 UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", | 196 UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", |
| 194 result.outgoing_messages.size()); | 197 result->outgoing_messages.size()); |
| 195 UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", | 198 UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", |
| 196 result.incoming_messages.size()); | 199 result->incoming_messages.size()); |
| 197 UMA_HISTOGRAM_COUNTS( | 200 UMA_HISTOGRAM_COUNTS( |
| 198 "GCM.NumUsers", | 201 "GCM.NumUsers", |
| 199 result.serial_number_mappings.user_serial_numbers.size()); | 202 result->serial_number_mappings.user_serial_numbers.size()); |
| 200 } | 203 } |
| 201 | 204 |
| 202 DVLOG(1) << "Succeeded in loading " << result.incoming_messages.size() | 205 DVLOG(1) << "Succeeded in loading " << result->incoming_messages.size() |
| 203 << " unacknowledged incoming messages and " | 206 << " unacknowledged incoming messages and " |
| 204 << result.outgoing_messages.size() | 207 << result->outgoing_messages.size() |
| 205 << " unacknowledged outgoing messages."; | 208 << " unacknowledged outgoing messages."; |
| 206 result.success = true; | 209 result->success = true; |
| 207 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); | 210 foreground_task_runner_->PostTask(FROM_HERE, |
| 211 base::Bind(callback, |
| 212 base::Passed(&result))); |
| 208 return; | 213 return; |
| 209 } | 214 } |
| 210 | 215 |
| 211 void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { | 216 void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { |
| 212 DVLOG(1) << "Destroying GCM store."; | 217 DVLOG(1) << "Destroying GCM store."; |
| 213 db_.reset(); | 218 db_.reset(); |
| 214 const leveldb::Status s = | 219 const leveldb::Status s = |
| 215 leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); | 220 leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); |
| 216 if (s.ok()) { | 221 if (s.ok()) { |
| 217 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | 222 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 return false; | 520 return false; |
| 516 } | 521 } |
| 517 DVLOG(1) << "Found incoming message with id " << s.ToString(); | 522 DVLOG(1) << "Found incoming message with id " << s.ToString(); |
| 518 incoming_messages->push_back(s.ToString()); | 523 incoming_messages->push_back(s.ToString()); |
| 519 } | 524 } |
| 520 | 525 |
| 521 return true; | 526 return true; |
| 522 } | 527 } |
| 523 | 528 |
| 524 bool GCMStoreImpl::Backend::LoadOutgoingMessages( | 529 bool GCMStoreImpl::Backend::LoadOutgoingMessages( |
| 525 std::map<std::string, google::protobuf::MessageLite*>* outgoing_messages) { | 530 OutgoingMessageMap* outgoing_messages) { |
| 526 leveldb::ReadOptions read_options; | 531 leveldb::ReadOptions read_options; |
| 527 read_options.verify_checksums = true; | 532 read_options.verify_checksums = true; |
| 528 | 533 |
| 529 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); | 534 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); |
| 530 for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); | 535 for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); |
| 531 iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; | 536 iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; |
| 532 iter->Next()) { | 537 iter->Next()) { |
| 533 leveldb::Slice s = iter->value(); | 538 leveldb::Slice s = iter->value(); |
| 534 if (s.size() <= 1) { | 539 if (s.size() <= 1) { |
| 535 LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); | 540 LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); |
| 536 return false; | 541 return false; |
| 537 } | 542 } |
| 538 uint8 tag = iter->value().data()[0]; | 543 uint8 tag = iter->value().data()[0]; |
| 539 std::string id = ParseOutgoingKey(iter->key().ToString()); | 544 std::string id = ParseOutgoingKey(iter->key().ToString()); |
| 540 scoped_ptr<google::protobuf::MessageLite> message( | 545 scoped_ptr<google::protobuf::MessageLite> message( |
| 541 BuildProtobufFromTag(tag)); | 546 BuildProtobufFromTag(tag)); |
| 542 if (!message.get() || | 547 if (!message.get() || |
| 543 !message->ParseFromString(iter->value().ToString().substr(1))) { | 548 !message->ParseFromString(iter->value().ToString().substr(1))) { |
| 544 LOG(ERROR) << "Failed to parse outgoing message with id " << id | 549 LOG(ERROR) << "Failed to parse outgoing message with id " << id |
| 545 << " and tag " << tag; | 550 << " and tag " << tag; |
| 546 return false; | 551 return false; |
| 547 } | 552 } |
| 548 DVLOG(1) << "Found outgoing message with id " << id << " of type " | 553 DVLOG(1) << "Found outgoing message with id " << id << " of type " |
| 549 << base::IntToString(tag); | 554 << base::IntToString(tag); |
| 550 (*outgoing_messages)[id] = message.release(); | 555 (*outgoing_messages)[id] = make_linked_ptr(message.release()); |
| 551 } | 556 } |
| 552 | 557 |
| 553 return true; | 558 return true; |
| 554 } | 559 } |
| 555 | 560 |
| 556 bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) { | 561 bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) { |
| 557 leveldb::ReadOptions read_options; | 562 leveldb::ReadOptions read_options; |
| 558 read_options.verify_checksums = true; | 563 read_options.verify_checksums = true; |
| 559 | 564 |
| 560 std::string result; | 565 std::string result; |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 const UpdateCallback& callback) { | 761 const UpdateCallback& callback) { |
| 757 blocking_task_runner_->PostTask( | 762 blocking_task_runner_->PostTask( |
| 758 FROM_HERE, | 763 FROM_HERE, |
| 759 base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber, | 764 base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber, |
| 760 backend_, | 765 backend_, |
| 761 username, | 766 username, |
| 762 callback)); | 767 callback)); |
| 763 } | 768 } |
| 764 | 769 |
| 765 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, | 770 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, |
| 766 const LoadResult& result) { | 771 scoped_ptr<LoadResult> result) { |
| 767 if (!result.success) { | 772 if (!result->success) { |
| 768 callback.Run(result); | 773 callback.Run(result.Pass()); |
| 769 return; | 774 return; |
| 770 } | 775 } |
| 771 int num_throttled_apps = 0; | 776 int num_throttled_apps = 0; |
| 772 for (std::map<std::string, google::protobuf::MessageLite*>::const_iterator | 777 for (OutgoingMessageMap::const_iterator |
| 773 iter = result.outgoing_messages.begin(); | 778 iter = result->outgoing_messages.begin(); |
| 774 iter != result.outgoing_messages.end(); ++iter) { | 779 iter != result->outgoing_messages.end(); ++iter) { |
| 775 const mcs_proto::DataMessageStanza* data_message = | 780 const mcs_proto::DataMessageStanza* data_message = |
| 776 reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second); | 781 reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get()); |
| 777 DCHECK(!data_message->from().empty()); | 782 DCHECK(!data_message->from().empty()); |
| 778 if (app_message_counts_.count(data_message->from()) == 0) | 783 if (app_message_counts_.count(data_message->from()) == 0) |
| 779 app_message_counts_[data_message->from()] = 1; | 784 app_message_counts_[data_message->from()] = 1; |
| 780 else | 785 else |
| 781 app_message_counts_[data_message->from()]++; | 786 app_message_counts_[data_message->from()]++; |
| 782 if (app_message_counts_[data_message->from()] == kMessagesPerAppLimit) | 787 if (app_message_counts_[data_message->from()] == kMessagesPerAppLimit) |
| 783 num_throttled_apps++; | 788 num_throttled_apps++; |
| 784 } | 789 } |
| 785 UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); | 790 UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); |
| 786 callback.Run(result); | 791 callback.Run(result.Pass()); |
| 787 } | 792 } |
| 788 | 793 |
| 789 void GCMStoreImpl::AddOutgoingMessageContinuation( | 794 void GCMStoreImpl::AddOutgoingMessageContinuation( |
| 790 const UpdateCallback& callback, | 795 const UpdateCallback& callback, |
| 791 const std::string& app_id, | 796 const std::string& app_id, |
| 792 bool success) { | 797 bool success) { |
| 793 if (!success) { | 798 if (!success) { |
| 794 DCHECK(app_message_counts_[app_id] > 0); | 799 DCHECK(app_message_counts_[app_id] > 0); |
| 795 app_message_counts_[app_id]--; | 800 app_message_counts_[app_id]--; |
| 796 } | 801 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 809 removed_message_counts.begin(); | 814 removed_message_counts.begin(); |
| 810 iter != removed_message_counts.end(); ++iter) { | 815 iter != removed_message_counts.end(); ++iter) { |
| 811 DCHECK_NE(app_message_counts_.count(iter->first), 0U); | 816 DCHECK_NE(app_message_counts_.count(iter->first), 0U); |
| 812 app_message_counts_[iter->first] -= iter->second; | 817 app_message_counts_[iter->first] -= iter->second; |
| 813 DCHECK_GE(app_message_counts_[iter->first], 0); | 818 DCHECK_GE(app_message_counts_[iter->first], 0); |
| 814 } | 819 } |
| 815 callback.Run(true); | 820 callback.Run(true); |
| 816 } | 821 } |
| 817 | 822 |
| 818 } // namespace gcm | 823 } // namespace gcm |
| OLD | NEW |