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 |