gcm_store_impl.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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" 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/os_crypt/os_crypt.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, 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_runner); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Blocking implementations of GCMStoreImpl methods. 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Load(const LoadCallback& callback); 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void Close(); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Destroy(const UpdateCallback& callback); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetDeviceCredentials(uint64 device_android_id, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void AddRegistration(const std::string& app_id, 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback); 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void RemoveRegistration(const std::string& app_id, 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddIncomingMessage(const std::string& persistent_id, 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveIncomingMessages(const PersistentIdList& persistent_ids, 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddOutgoingMessage(const std::string& persistent_id, 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveOutgoingMessages( 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddUserSerialNumber(const std::string& username, 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number, 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveUserSerialNumber(const std::string& username, 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void SetLastCheckinTime(const base::Time& last_checkin_time, 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback); 142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void SetGServicesSettings( 143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::map<std::string, std::string>& settings, 144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& digest, 145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const UpdateCallback& callback); 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class base::RefCountedThreadSafe<Backend>; 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Backend(); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool LoadRegistrations(RegistrationInfoMap* registrations); 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool LoadLastCheckinTime(base::Time* last_checkin_time); 156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool LoadGServicesSettings(std::map<std::string, std::string>* settings, 157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string* digest); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath path_; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::DB> db_; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::Backend( 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : path_(path), foreground_task_runner_(foreground_task_runner) {} 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::~Backend() {} 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result(new LoadResult()); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_.get()) { 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Attempting to reload open database."; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Options options; 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.create_if_missing = true; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB* db; 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status status = 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!status.ok()) { 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to open database " << path_.value() << ": " 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << status.ToString(); 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(db); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!LoadDeviceCredentials(&result->device_android_id, 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &result->device_security_token) || 200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !LoadRegistrations(&result->registrations) || 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadIncomingMessages(&result->incoming_messages) || 202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !LoadOutgoingMessages(&result->outgoing_messages) || 203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !LoadLastCheckinTime(&result->last_checkin_time) || 204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !LoadGServicesSettings(&result->gservices_settings, 205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch &result->gservices_digest)) { 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_android_id = 0; 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_security_token = 0; 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result->registrations.clear(); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.clear(); 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.clear(); 211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch result->gservices_settings.clear(); 212a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch result->gservices_digest.clear(); 213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch result->last_checkin_time = base::Time::FromInternalValue(0LL); 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only record histograms if GCM had already been set up for this device. 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result->device_android_id != 0 && result->device_security_token != 0) { 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 file_size = 0; 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (base::GetFileSize(path_, &file_size)) { 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<int>(file_size / 1024)); 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_COUNTS("GCM.RestoredRegistrations", 228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result->registrations.size()); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.size()); 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.size()); 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Succeeded in loading " << result->registrations.size() 236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << " registrations, " 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << result->incoming_messages.size() 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged incoming messages and " 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << result->outgoing_messages.size() 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged outgoing messages."; 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->success = true; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Backend::Close() { 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Closing GCM store."; 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) db_.reset(); 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Destroying GCM store."; 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(); 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Destroy failed: " << s.ToString(); 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::SetDeviceCredentials( 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_android_id, 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving device credentials with AID " << device_android_id; 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encrypted_token; 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::EncryptString(base::Uint64ToString(device_security_token), 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &encrypted_token); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string android_id_str = base::Uint64ToString(device_android_id); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Put(write_options, 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(kDeviceAIDKey), 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(android_id_str)); 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Put( 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::Backend::AddRegistration( 301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id, 302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Saving registration info for app: " << app_id; 305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!db_.get()) { 306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "GCMStore db doesn't exist."; 307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::WriteOptions write_options; 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch write_options.sync = true; 312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string key = MakeRegistrationKey(app_id); 314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string value = registration->SerializeAsString(); 315effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const leveldb::Status status = db_->Put(write_options, 316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeSlice(key), 317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeSlice(value)); 318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (status.ok()) { 319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::Backend::RemoveRegistration(const std::string& app_id, 327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!db_.get()) { 329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "GCMStore db doesn't exist."; 330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::WriteOptions write_options; 334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch write_options.sync = true; 335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::Status status = db_->Delete(write_options, MakeSlice(app_id)); 337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (status.ok()) { 338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving incoming message with id " << persistent_id; 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(persistent_id); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(persistent_id)); 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveIncomingMessages( 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing incoming message with id " << *iter; 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(*iter); 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving outgoing message with id " << persistent_id; 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string data = 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<char>(message.tag()) + message.SerializeAsString(); 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(persistent_id); 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(data)); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveOutgoingMessages( 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback) { 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap removed_message_counts; 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string outgoing_message; 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(*iter); 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &outgoing_message); 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mcs_proto::DataMessageStanza data_message; 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Skip the initial tag byte and parse the rest to extract the message. 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (data_message.ParseFromString(outgoing_message.substr(1))) { 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message.category().empty()); 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (removed_message_counts.count(data_message.category()) != 0) 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()]++; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()] = 1; 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts)); 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 482c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GCMStoreImpl::Backend::SetLastCheckinTime( 483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Time& last_checkin_time, 484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback) { 485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::WriteOptions write_options; 486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch write_options.sync = true; 487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 last_checkin_time_internal = last_checkin_time.ToInternalValue(); 489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const leveldb::Status s = 490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch db_->Put(write_options, 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(kLastCheckinTimeKey), 492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(base::Int64ToString(last_checkin_time_internal))); 493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!s.ok()) 495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString(); 496a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 497a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 498a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 499a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid GCMStoreImpl::Backend::SetGServicesSettings( 500a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::map<std::string, std::string>& settings, 501a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& settings_digest, 502a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const UpdateCallback& callback) { 503a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::WriteBatch write_batch; 504a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 505a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Remove all existing settings. 506a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::ReadOptions read_options; 507a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch read_options.verify_checksums = true; 508a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 509a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (iter->Seek(MakeSlice(kGServiceSettingKeyStart)); 510a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd; 511a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Next()) { 512a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_batch.Delete(iter->key()); 513a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 514a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 515a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Add the new settings. 516a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (std::map<std::string, std::string>::const_iterator iter = 517a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch settings.begin(); 518a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter != settings.end(); ++iter) { 519a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_batch.Put(MakeSlice(MakeGServiceSettingKey(iter->first)), 520a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch MakeSlice(iter->second)); 521a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 522a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 523a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Update the settings digest. 524a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_batch.Put(MakeSlice(kGServiceSettingsDigestKey), 525a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch MakeSlice(settings_digest)); 526a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 527a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Write it all in a batch. 528a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::WriteOptions write_options; 529a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch write_options.sync = true; 530c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 531a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::Status s = db_->Write(write_options, &write_batch); 532a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!s.ok()) 533a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch LOG(ERROR) << "LevelDB GService Settings update failed: " << s.ToString(); 534c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 535c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 536c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64* security_token) { 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string result; 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(result, android_id)) { 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore device id."; 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.clear(); 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, MakeSlice(kDeviceTokenKey), &result); 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string decrypted_token; 554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::DecryptString(result, &decrypted_token); 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(decrypted_token, security_token)) { 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore security token."; 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.IsNotFound()) { 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "No credentials found."; 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading credentials from store."; 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 571effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool GCMStoreImpl::Backend::LoadRegistrations( 572effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RegistrationInfoMap* registrations) { 573effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::ReadOptions read_options; 574effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch read_options.verify_checksums = true; 575effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 576effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 577effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (iter->Seek(MakeSlice(kRegistrationKeyStart)); 578effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch iter->Valid() && iter->key().ToString() < kRegistrationKeyEnd; 579effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch iter->Next()) { 580effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::Slice s = iter->value(); 581effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (s.size() <= 1) { 582effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Error reading registration with key " << s.ToString(); 583effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 584effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 585effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string app_id = ParseRegistrationKey(iter->key().ToString()); 586effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch linked_ptr<RegistrationInfo> registration(new RegistrationInfo); 587effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!registration->ParseFromString(iter->value().ToString())) { 588effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Failed to parse registration with app id " << app_id; 589effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 590effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 591effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Found registration with app id " << app_id; 592effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (*registrations)[app_id] = registration; 593effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 594effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 595effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 596effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 597effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadIncomingMessages( 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>* incoming_messages) { 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kIncomingMsgKeyStart)); 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd; 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.empty()) { 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << iter->key().ToString(); 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found incoming message with id " << s.ToString(); 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) incoming_messages->push_back(s.ToString()); 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadOutgoingMessages( 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OutgoingMessageMap* outgoing_messages) { 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.size() <= 1) { 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8 tag = iter->value().data()[0]; 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string id = ParseOutgoingKey(iter->key().ToString()); 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<google::protobuf::MessageLite> message( 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildProtobufFromTag(tag)); 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!message.get() || 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !message->ParseFromString(iter->value().ToString().substr(1))) { 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to parse outgoing message with id " << id 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " and tag " << tag; 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found outgoing message with id " << id << " of type " 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << base::IntToString(tag); 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*outgoing_messages)[id] = make_linked_ptr(message.release()); 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 652c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool GCMStoreImpl::Backend::LoadLastCheckinTime( 653c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Time* last_checkin_time) { 654c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::ReadOptions read_options; 655c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch read_options.verify_checksums = true; 656c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 657c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::string result; 658c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::Status s = db_->Get(read_options, 659c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(kLastCheckinTimeKey), 660c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &result); 661c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 time_internal = 0LL; 662c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (s.ok() && !base::StringToInt64(result, &time_internal)) 663c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "Failed to restore last checkin time. Using default = 0."; 664c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 665c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // In case we cannot read last checkin time, we default it to 0, as we don't 666c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // want that situation to cause the whole load to fail. 667c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *last_checkin_time = base::Time::FromInternalValue(time_internal); 668c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 669c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return true; 670c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 671c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 672a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool GCMStoreImpl::Backend::LoadGServicesSettings( 673a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::map<std::string, std::string>* settings, 674a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string* digest) { 675a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch leveldb::ReadOptions read_options; 676a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch read_options.verify_checksums = true; 677a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 678a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Load all of the GServices settings. 679a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 680a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (iter->Seek(MakeSlice(kGServiceSettingKeyStart)); 681a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd; 682a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter->Next()) { 683a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string value = iter->value().ToString(); 684a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (value.empty()) { 685a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch LOG(ERROR) << "Error reading GService Settings " << value; 686a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return false; 687a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 688a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string id = ParseGServiceSettingKey(iter->key().ToString()); 689a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch (*settings)[id] = value; 690a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DVLOG(1) << "Found G Service setting with key: " << id 691a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch << ", and value: " << value; 692a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 693a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 694a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Load the settings digest. It's ok if it is empty. 695a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch db_->Get(read_options, MakeSlice(kGServiceSettingsDigestKey), digest); 696a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 697a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return true; 698a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 699a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::GCMStoreImpl( 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : backend_(new Backend(path, base::MessageLoopProxy::current())), 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_(blocking_task_runner), 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_(this) { 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::~GCMStoreImpl() {} 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Load(const LoadCallback& callback) { 7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Load, 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::LoadContinuation, 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Close() { 721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) blocking_task_runner_->PostTask( 722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 723a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Close, backend_)); 724a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 725a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Destroy(const UpdateCallback& callback) { 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Destroy, backend_, callback)); 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::SetDeviceCredentials(uint64 device_android_id, 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::SetDeviceCredentials, 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_android_id, 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_security_token, 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 744effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::AddRegistration( 745effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id, 746effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 747effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 748effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blocking_task_runner_->PostTask( 749effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 750effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&GCMStoreImpl::Backend::AddRegistration, 751effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch backend_, 752effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id, 753effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registration, 754effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback)); 755effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 756effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 757effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::RemoveRegistration(const std::string& app_id, 758effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 759effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blocking_task_runner_->PostTask( 760effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 761effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&GCMStoreImpl::Backend::RemoveRegistration, 762effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch backend_, 763effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id, 764effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback)); 765effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 766effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id, 7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddIncomingMessage, 7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessage(const std::string& persistent_id, 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessages( 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 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) persistent_ids, 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::AddOutgoingMessage(const std::string& persistent_id, 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(app_id) == 0) 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id] = 0; 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[app_id] < kMessagesPerAppLimit) { 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]++; 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::AddOutgoingMessageContinuation, 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback, 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_id))); 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::OverwriteOutgoingMessage(const std::string& persistent_id, 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // There should already be pending messages for this app. 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_.count(app_id)); 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(zea): consider verifying the specific message already exists. 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessage(const std::string& persistent_id, 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessages( 8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 8585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, 8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 869c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time, 870c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback) { 871c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch blocking_task_runner_->PostTask( 872c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 873c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime, 874c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch backend_, 875c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch last_checkin_time, 876c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback)); 877c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 878c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 879a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid GCMStoreImpl::SetGServicesSettings( 880a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::map<std::string, std::string>& settings, 881a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& digest, 882a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const UpdateCallback& callback) { 883a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch blocking_task_runner_->PostTask( 884a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch FROM_HERE, 885a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::Bind(&GCMStoreImpl::Backend::SetGServicesSettings, 886a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch backend_, 887a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch settings, 888a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch digest, 889a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch callback)); 890a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 891a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, 8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result) { 8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!result->success) { 8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int num_throttled_apps = 0; 8995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (OutgoingMessageMap::const_iterator 9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = result->outgoing_messages.begin(); 9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != result->outgoing_messages.end(); ++iter) { 9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const mcs_proto::DataMessageStanza* data_message = 9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get()); 9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message->category().empty()); 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(data_message->category()) == 0) 9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()] = 1; 9075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()]++; 9095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[data_message->category()] == kMessagesPerAppLimit) 9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_throttled_apps++; 9115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); 9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddOutgoingMessageContinuation( 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success) { 9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_[app_id] > 0); 9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]--; 9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(success); 9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessagesContinuation( 9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success, 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppIdToMessageCountMap& removed_message_counts) { 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false); 9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppIdToMessageCountMap::const_iterator iter = 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts.begin(); 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != removed_message_counts.end(); ++iter) { 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(app_message_counts_.count(iter->first), 0U); 9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[iter->first] -= iter->second; 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GE(app_message_counts_[iter->first], 0); 9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(true); 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace gcm 946