gcm_store_impl.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/engine/gcm_store_impl.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/callback.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/file_util.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file_path.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/sequenced_task_runner.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/stl_util.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_piece.h" 19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/time/time.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/tracked_objects.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "google_apis/gcm/base/encryptor.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_message.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_util.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/protocol/mcs.pb.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gcm { 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Limit to the number of outstanding messages per app. 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMessagesPerAppLimit = 20; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ---- LevelDB keys. ---- 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key for this device's android id. 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDeviceAIDKey[] = "device_aid_key"; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key for this device's android security token. 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDeviceTokenKey[] = "device_token_key"; 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Lowest lexicographically ordered app ids. 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Used for prefixing app id. 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kRegistrationKeyStart[] = "reg1-"; 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Key guaranteed to be higher than all app ids. 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Used for limiting iteration. 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kRegistrationKeyEnd[] = "reg2-"; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered incoming message key. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing messages. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kIncomingMsgKeyStart[] = "incoming1-"; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all incoming message keys. 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kIncomingMsgKeyEnd[] = "incoming2-"; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered outgoing message key. 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing outgoing messages. 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kOutgoingMsgKeyStart[] = "outgoing1-"; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all outgoing message keys. 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kOutgoingMsgKeyEnd[] = "outgoing2-"; 58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Lowest lexicographically ordered G-service settings key. 59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Used for prefixing G-services settings. 60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst char kGServiceSettingKeyStart[] = "gservice1-"; 61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Key guaranteed to be higher than all G-services settings keys. 62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Used for limiting iteration. 63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst char kGServiceSettingKeyEnd[] = "gservice2-"; 64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Key for digest of the last G-services settings update. 65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst char kGServiceSettingsDigestKey[] = "gservices_digest"; 66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Key used to timestamp last checkin (marked with G services settings update). 67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kLastCheckinTimeKey[] = "last_checkin_time"; 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string MakeRegistrationKey(const std::string& app_id) { 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return kRegistrationKeyStart + app_id; 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string ParseRegistrationKey(const std::string& key) { 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return key.substr(arraysize(kRegistrationKeyStart) - 1); 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeIncomingKey(const std::string& persistent_id) { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kIncomingMsgKeyStart + persistent_id; 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeOutgoingKey(const std::string& persistent_id) { 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kOutgoingMsgKeyStart + persistent_id; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string ParseOutgoingKey(const std::string& key) { 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::string MakeGServiceSettingKey(const std::string& setting_name) { 90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return kGServiceSettingKeyStart + setting_name; 91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::string ParseGServiceSettingKey(const std::string& key) { 94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return key.substr(arraysize(kGServiceSettingKeyStart) - 1); 95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// outlive the slice. 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For example: MakeSlice(MakeOutgoingKey(x)) is invalid. 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)leveldb::Slice MakeSlice(const base::StringPiece& s) { 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return leveldb::Slice(s.begin(), s.size()); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GCMStoreImpl::Backend 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Backend(const base::FilePath& path, 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_runner, 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Encryptor> encryptor); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Blocking implementations of GCMStoreImpl methods. 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Load(const LoadCallback& callback); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void Close(); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Destroy(const UpdateCallback& callback); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetDeviceCredentials(uint64 device_android_id, 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void AddRegistration(const std::string& app_id, 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback); 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void RemoveRegistration(const std::string& app_id, 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddIncomingMessage(const std::string& persistent_id, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveIncomingMessages(const PersistentIdList& persistent_ids, 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddOutgoingMessage(const std::string& persistent_id, 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveOutgoingMessages( 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback); 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddUserSerialNumber(const std::string& username, 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number, 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveUserSerialNumber(const std::string& username, 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void SetLastCheckinTime(const base::Time& last_checkin_time, 142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback); 143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void SetGServicesSettings( 144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::map<std::string, std::string>& settings, 145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& digest, 146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const UpdateCallback& callback); 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class base::RefCountedThreadSafe<Backend>; 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Backend(); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool LoadRegistrations(RegistrationInfoMap* registrations); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool LoadLastCheckinTime(base::Time* last_checkin_time); 157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool LoadGServicesSettings(std::map<std::string, std::string>* settings, 158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string* digest); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath path_; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Encryptor> encryptor_; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::DB> db_; 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::Backend( 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner, 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Encryptor> encryptor) 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : path_(path), 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) foreground_task_runner_(foreground_task_runner), 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) encryptor_(encryptor.Pass()) { 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::~Backend() {} 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result(new LoadResult()); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_.get()) { 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Attempting to reload open database."; 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Options options; 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.create_if_missing = true; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB* db; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status status = 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!status.ok()) { 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to open database " << path_.value() << ": " 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << status.ToString(); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(db); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!LoadDeviceCredentials(&result->device_android_id, 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &result->device_security_token) || 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !LoadRegistrations(&result->registrations) || 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadIncomingMessages(&result->incoming_messages) || 208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !LoadOutgoingMessages(&result->outgoing_messages) || 209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !LoadLastCheckinTime(&result->last_checkin_time) || 210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !LoadGServicesSettings(&result->gservices_settings, 211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch &result->gservices_digest)) { 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_android_id = 0; 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_security_token = 0; 214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result->registrations.clear(); 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.clear(); 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.clear(); 217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch result->gservices_settings.clear(); 218a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch result->gservices_digest.clear(); 219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch result->last_checkin_time = base::Time::FromInternalValue(0LL); 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only record histograms if GCM had already been set up for this device. 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result->device_android_id != 0 && result->device_security_token != 0) { 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 file_size = 0; 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (base::GetFileSize(path_, &file_size)) { 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<int>(file_size / 1024)); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_COUNTS("GCM.RestoredRegistrations", 234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result->registrations.size()); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.size()); 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.size()); 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Succeeded in loading " << result->registrations.size() 242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << " registrations, " 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << result->incoming_messages.size() 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged incoming messages and " 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << result->outgoing_messages.size() 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged outgoing messages."; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->success = true; 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Backend::Close() { 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Closing GCM store."; 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) db_.reset(); 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Destroying GCM store."; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(); 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Destroy failed: " << s.ToString(); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::SetDeviceCredentials( 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_android_id, 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving device credentials with AID " << device_android_id; 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encrypted_token; 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) encryptor_->EncryptString(base::Uint64ToString(device_security_token), 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &encrypted_token); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string android_id_str = base::Uint64ToString(device_android_id); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Put(write_options, 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(kDeviceAIDKey), 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(android_id_str)); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Put( 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::Backend::AddRegistration( 307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id, 308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Saving registration info for app: " << app_id; 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!db_.get()) { 312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "GCMStore db doesn't exist."; 313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 315effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::WriteOptions write_options; 317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch write_options.sync = true; 318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string key = MakeRegistrationKey(app_id); 320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string value = registration->SerializeAsString(); 321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const leveldb::Status status = db_->Put(write_options, 322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeSlice(key), 323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeSlice(value)); 324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (status.ok()) { 325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::Backend::RemoveRegistration(const std::string& app_id, 333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!db_.get()) { 335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "GCMStore db doesn't exist."; 336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::WriteOptions write_options; 340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch write_options.sync = true; 341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::Status status = db_->Delete(write_options, MakeSlice(app_id)); 343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (status.ok()) { 344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); 348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving incoming message with id " << persistent_id; 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(persistent_id); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(persistent_id)); 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveIncomingMessages( 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing incoming message with id " << *iter; 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(*iter); 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving outgoing message with id " << persistent_id; 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string data = 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<char>(message.tag()) + message.SerializeAsString(); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(persistent_id); 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(data)); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveOutgoingMessages( 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback) { 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap removed_message_counts; 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string outgoing_message; 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(*iter); 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &outgoing_message); 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mcs_proto::DataMessageStanza data_message; 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Skip the initial tag byte and parse the rest to extract the message. 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (data_message.ParseFromString(outgoing_message.substr(1))) { 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message.category().empty()); 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (removed_message_counts.count(data_message.category()) != 0) 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()]++; 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()] = 1; 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts)); 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GCMStoreImpl::Backend::SetLastCheckinTime( 489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Time& last_checkin_time, 490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback) { 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::WriteOptions write_options; 492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch write_options.sync = true; 493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 last_checkin_time_internal = last_checkin_time.ToInternalValue(); 495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const leveldb::Status s = 496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch db_->Put(write_options, 497c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(kLastCheckinTimeKey), 498c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(base::Int64ToString(last_checkin_time_internal))); 499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 500c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!s.ok()) 501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString(); 502a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 503a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 504a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 505a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid GCMStoreImpl::Backend::SetGServicesSettings( 506a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::map<std::string, std::string>& settings, 507a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& settings_digest, 508a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const UpdateCallback& callback) { 509a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::WriteBatch write_batch; 510a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 511a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Remove all existing settings. 512a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::ReadOptions read_options; 513a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch read_options.verify_checksums = true; 514a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 515a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (iter->Seek(MakeSlice(kGServiceSettingKeyStart)); 516a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd; 517a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Next()) { 518a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_batch.Delete(iter->key()); 519a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 520a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 521a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Add the new settings. 522a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (std::map<std::string, std::string>::const_iterator iter = 523a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch settings.begin(); 524a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter != settings.end(); ++iter) { 525a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_batch.Put(MakeSlice(MakeGServiceSettingKey(iter->first)), 526a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch MakeSlice(iter->second)); 527a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 528a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 529a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Update the settings digest. 530a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_batch.Put(MakeSlice(kGServiceSettingsDigestKey), 531a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch MakeSlice(settings_digest)); 532a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 533a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Write it all in a batch. 534a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::WriteOptions write_options; 535a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_options.sync = true; 536c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 537a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::Status s = db_->Write(write_options, &write_batch); 538a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!s.ok()) 539a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch LOG(ERROR) << "LevelDB GService Settings update failed: " << s.ToString(); 540c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 541c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 542c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64* security_token) { 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string result; 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(result, android_id)) { 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore device id."; 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.clear(); 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, MakeSlice(kDeviceTokenKey), &result); 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string decrypted_token; 560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) encryptor_->DecryptString(result, &decrypted_token); 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(decrypted_token, security_token)) { 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore security token."; 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.IsNotFound()) { 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "No credentials found."; 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading credentials from store."; 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 577effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool GCMStoreImpl::Backend::LoadRegistrations( 578effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RegistrationInfoMap* registrations) { 579effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::ReadOptions read_options; 580effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch read_options.verify_checksums = true; 581effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 582effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 583effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (iter->Seek(MakeSlice(kRegistrationKeyStart)); 584effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch iter->Valid() && iter->key().ToString() < kRegistrationKeyEnd; 585effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch iter->Next()) { 586effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::Slice s = iter->value(); 587effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (s.size() <= 1) { 588effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Error reading registration with key " << s.ToString(); 589effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 590effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 591effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string app_id = ParseRegistrationKey(iter->key().ToString()); 592effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch linked_ptr<RegistrationInfo> registration(new RegistrationInfo); 593effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!registration->ParseFromString(iter->value().ToString())) { 594effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Failed to parse registration with app id " << app_id; 595effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 596effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 597effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Found registration with app id " << app_id; 598effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (*registrations)[app_id] = registration; 599effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 600effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 601effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 602effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 603effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadIncomingMessages( 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>* incoming_messages) { 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kIncomingMsgKeyStart)); 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd; 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.empty()) { 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << iter->key().ToString(); 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found incoming message with id " << s.ToString(); 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) incoming_messages->push_back(s.ToString()); 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadOutgoingMessages( 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OutgoingMessageMap* outgoing_messages) { 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.size() <= 1) { 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8 tag = iter->value().data()[0]; 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string id = ParseOutgoingKey(iter->key().ToString()); 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<google::protobuf::MessageLite> message( 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildProtobufFromTag(tag)); 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!message.get() || 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !message->ParseFromString(iter->value().ToString().substr(1))) { 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to parse outgoing message with id " << id 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " and tag " << tag; 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found outgoing message with id " << id << " of type " 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << base::IntToString(tag); 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*outgoing_messages)[id] = make_linked_ptr(message.release()); 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 658c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool GCMStoreImpl::Backend::LoadLastCheckinTime( 659c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Time* last_checkin_time) { 660c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::ReadOptions read_options; 661c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch read_options.verify_checksums = true; 662c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 663c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::string result; 664c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::Status s = db_->Get(read_options, 665c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(kLastCheckinTimeKey), 666c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &result); 667c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 time_internal = 0LL; 668c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (s.ok() && !base::StringToInt64(result, &time_internal)) 669c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "Failed to restore last checkin time. Using default = 0."; 670c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 671c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // In case we cannot read last checkin time, we default it to 0, as we don't 672c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // want that situation to cause the whole load to fail. 673c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *last_checkin_time = base::Time::FromInternalValue(time_internal); 674c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 675c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return true; 676c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 677c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 678a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool GCMStoreImpl::Backend::LoadGServicesSettings( 679a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::map<std::string, std::string>* settings, 680a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string* digest) { 681a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::ReadOptions read_options; 682a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch read_options.verify_checksums = true; 683a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 684a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Load all of the GServices settings. 685a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 686a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (iter->Seek(MakeSlice(kGServiceSettingKeyStart)); 687a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd; 688a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Next()) { 689a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string value = iter->value().ToString(); 690a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (value.empty()) { 691a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch LOG(ERROR) << "Error reading GService Settings " << value; 692a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return false; 693a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 694a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string id = ParseGServiceSettingKey(iter->key().ToString()); 695a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch (*settings)[id] = value; 696a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DVLOG(1) << "Found G Service setting with key: " << id 697a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch << ", and value: " << value; 698a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 699a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 700a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Load the settings digest. It's ok if it is empty. 701a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch db_->Get(read_options, MakeSlice(kGServiceSettingsDigestKey), digest); 702a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 703a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return true; 704a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 705a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::GCMStoreImpl( 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, 709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Encryptor> encryptor) 710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : backend_(new Backend(path, 711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoopProxy::current(), 712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) encryptor.Pass())), 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_(blocking_task_runner), 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_(this) { 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::~GCMStoreImpl() {} 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Load(const LoadCallback& callback) { 7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Load, 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::LoadContinuation, 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 729a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Close() { 730f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.InvalidateWeakPtrs(); 731f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) app_message_counts_.clear(); 732a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) blocking_task_runner_->PostTask( 733a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 734a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Close, backend_)); 735a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 736a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Destroy(const UpdateCallback& callback) { 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Destroy, backend_, callback)); 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::SetDeviceCredentials(uint64 device_android_id, 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::SetDeviceCredentials, 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_android_id, 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_security_token, 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::AddRegistration( 756effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id, 757effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 758effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 759effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blocking_task_runner_->PostTask( 760effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 761effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&GCMStoreImpl::Backend::AddRegistration, 762effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch backend_, 763effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id, 764effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registration, 765effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback)); 766effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 767effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 768effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::RemoveRegistration(const std::string& app_id, 769effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 770effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blocking_task_runner_->PostTask( 771effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 772effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&GCMStoreImpl::Backend::RemoveRegistration, 773effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch backend_, 774effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id, 775effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback)); 776effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 777effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id, 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddIncomingMessage, 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessage(const std::string& persistent_id, 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessages( 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::AddOutgoingMessage(const std::string& persistent_id, 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(app_id) == 0) 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id] = 0; 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[app_id] < kMessagesPerAppLimit) { 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]++; 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::AddOutgoingMessageContinuation, 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback, 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_id))); 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::OverwriteOutgoingMessage(const std::string& persistent_id, 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // There should already be pending messages for this app. 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_.count(app_id)); 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(zea): consider verifying the specific message already exists. 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessage(const std::string& persistent_id, 8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, 8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessages( 8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 8695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, 8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 8765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 880c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time, 881c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback) { 882c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch blocking_task_runner_->PostTask( 883c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 884c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime, 885c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch backend_, 886c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch last_checkin_time, 887c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback)); 888c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 889c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 890a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid GCMStoreImpl::SetGServicesSettings( 891a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::map<std::string, std::string>& settings, 892a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& digest, 893a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const UpdateCallback& callback) { 894a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch blocking_task_runner_->PostTask( 895a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch FROM_HERE, 896a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::Bind(&GCMStoreImpl::Backend::SetGServicesSettings, 897a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch backend_, 898a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch settings, 899a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch digest, 900a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch callback)); 901a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 902a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, 9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result) { 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!result->success) { 9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 9075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int num_throttled_apps = 0; 9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (OutgoingMessageMap::const_iterator 9115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = result->outgoing_messages.begin(); 9125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != result->outgoing_messages.end(); ++iter) { 9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const mcs_proto::DataMessageStanza* data_message = 9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get()); 9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message->category().empty()); 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(data_message->category()) == 0) 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()] = 1; 9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()]++; 9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[data_message->category()] == kMessagesPerAppLimit) 9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_throttled_apps++; 9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); 9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddOutgoingMessageContinuation( 9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success) { 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_[app_id] > 0); 9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]--; 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(success); 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessagesContinuation( 9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success, 9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppIdToMessageCountMap& removed_message_counts) { 9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false); 9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppIdToMessageCountMap::const_iterator iter = 9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts.begin(); 9485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != removed_message_counts.end(); ++iter) { 9495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(app_message_counts_.count(iter->first), 0U); 9505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[iter->first] -= iter->second; 9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GE(app_message_counts_[iter->first], 0); 9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(true); 9545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace gcm 957