gcm_store_impl.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/tracked_objects.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/os_crypt/os_crypt.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_message.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_util.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/protocol/mcs.pb.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gcm { 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Limit to the number of outstanding messages per app. 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMessagesPerAppLimit = 20; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ---- LevelDB keys. ---- 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key for this device's android id. 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDeviceAIDKey[] = "device_aid_key"; 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key for this device's android security token. 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDeviceTokenKey[] = "device_token_key"; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered incoming message key. 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing messages. 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kIncomingMsgKeyStart[] = "incoming1-"; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all incoming message keys. 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kIncomingMsgKeyEnd[] = "incoming2-"; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key for next serial number assigned to the user. 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kNextSerialNumberKey[] = "next_serial_number_key"; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered outgoing message key. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing outgoing messages. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kOutgoingMsgKeyStart[] = "outgoing1-"; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all outgoing message keys. 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kOutgoingMsgKeyEnd[] = "outgoing2-"; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered username. 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing username to serial number mappings. 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kUserSerialNumberKeyStart[] = "user1-"; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all usernames. 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kUserSerialNumberKeyEnd[] = "user2-"; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Value indicating that serial number was not assigned. 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int64 kSerialNumberMissing = -1LL; 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeIncomingKey(const std::string& persistent_id) { 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kIncomingMsgKeyStart + persistent_id; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeOutgoingKey(const std::string& persistent_id) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kOutgoingMsgKeyStart + persistent_id; 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeUserSerialNumberKey(const std::string& username) { 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kUserSerialNumberKeyStart + username; 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string ParseOutgoingKey(const std::string& key) { 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string ParseUsername(const std::string& key) { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return key.substr(arraysize(kUserSerialNumberKeyStart) - 1); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// outlive the slice. 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For example: MakeSlice(MakeOutgoingKey(x)) is invalid. 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)leveldb::Slice MakeSlice(const base::StringPiece& s) { 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return leveldb::Slice(s.begin(), s.size()); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GCMStoreImpl::Backend 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Backend(const base::FilePath& path, 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_runner); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Blocking implementations of GCMStoreImpl methods. 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Load(const LoadCallback& callback); 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void Close(); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Destroy(const UpdateCallback& callback); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetDeviceCredentials(uint64 device_android_id, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddIncomingMessage(const std::string& persistent_id, 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveIncomingMessages(const PersistentIdList& persistent_ids, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddOutgoingMessage(const std::string& persistent_id, 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveOutgoingMessages( 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddUserSerialNumber(const std::string& username, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveUserSerialNumber(const std::string& username, 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class base::RefCountedThreadSafe<Backend>; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Backend(); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadNextSerialNumber(int64* next_serial_number); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadUserSerialNumberMap( 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::map<std::string, int64>* user_serial_number_map); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath path_; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::DB> db_; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::Backend( 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : path_(path), foreground_task_runner_(foreground_task_runner) {} 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::~Backend() {} 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result(new LoadResult()); 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_.get()) { 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Attempting to reload open database."; 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Options options; 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.create_if_missing = true; 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB* db; 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status status = 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!status.ok()) { 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to open database " << path_.value() << ": " 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << status.ToString(); 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(db); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!LoadDeviceCredentials(&result->device_android_id, 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &result->device_security_token) || 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadIncomingMessages(&result->incoming_messages) || 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadOutgoingMessages(&result->outgoing_messages) || 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadNextSerialNumber( 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &result->serial_number_mappings.next_serial_number) || 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadUserSerialNumberMap( 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &result->serial_number_mappings.user_serial_numbers)) { 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_android_id = 0; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_security_token = 0; 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.clear(); 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.clear(); 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only record histograms if GCM had already been set up for this device. 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result->device_android_id != 0 && result->device_security_token != 0) { 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 file_size = 0; 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (base::GetFileSize(path_, &file_size)) { 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<int>(file_size / 1024)); 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.size()); 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.size()); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS( 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "GCM.NumUsers", 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->serial_number_mappings.user_serial_numbers.size()); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Succeeded in loading " << result->incoming_messages.size() 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged incoming messages and " 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << result->outgoing_messages.size() 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged outgoing messages."; 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->success = true; 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Backend::Close() { 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Closing GCM store."; 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) db_.reset(); 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Destroying GCM store."; 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(); 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Destroy failed: " << s.ToString(); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::SetDeviceCredentials( 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_android_id, 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving device credentials with AID " << device_android_id; 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encrypted_token; 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::EncryptString(base::Uint64ToString(device_security_token), 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &encrypted_token); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string android_id_str = base::Uint64ToString(device_android_id); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Put(write_options, 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(kDeviceAIDKey), 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(android_id_str)); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Put( 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving incoming message with id " << persistent_id; 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(persistent_id); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(persistent_id)); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveIncomingMessages( 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing incoming message with id " << *iter; 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(*iter); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving outgoing message with id " << persistent_id; 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string data = 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<char>(message.tag()) + message.SerializeAsString(); 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(persistent_id); 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(data)); 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveOutgoingMessages( 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback) { 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap removed_message_counts; 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string outgoing_message; 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(*iter); 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &outgoing_message); 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mcs_proto::DataMessageStanza data_message; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Skip the initial tag byte and parse the rest to extract the message. 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (data_message.ParseFromString(outgoing_message.substr(1))) { 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message.category().empty()); 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (removed_message_counts.count(data_message.category()) != 0) 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()]++; 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()] = 1; 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts)); 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddUserSerialNumber( 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& username, 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number, 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving username to serial number mapping for user: " << username; 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeUserSerialNumberKey(username); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string serial_number_str = base::Int64ToString(serial_number); 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status status = 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Put(write_options, 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(serial_number_str)); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.ok()) { 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveUserSerialNumber( 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& username, 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status status = db_->Delete(write_options, MakeSlice(username)); 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.ok()) { 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::SetNextSerialNumber( 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 next_serial_number, 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Updating the value of next user serial number to: " 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << next_serial_number; 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string serial_number_str = base::Int64ToString(next_serial_number); 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status status = 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Put(write_options, 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(kNextSerialNumberKey), 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(serial_number_str)); 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.ok()) { 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64* security_token) { 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string result; 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(result, android_id)) { 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore device id."; 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.clear(); 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, MakeSlice(kDeviceTokenKey), &result); 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string decrypted_token; 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::DecryptString(result, &decrypted_token); 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(decrypted_token, security_token)) { 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore security token."; 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.IsNotFound()) { 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "No credentials found."; 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading credentials from store."; 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadIncomingMessages( 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>* incoming_messages) { 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kIncomingMsgKeyStart)); 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd; 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.empty()) { 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << iter->key().ToString(); 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found incoming message with id " << s.ToString(); 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) incoming_messages->push_back(s.ToString()); 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadOutgoingMessages( 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OutgoingMessageMap* outgoing_messages) { 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.size() <= 1) { 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8 tag = iter->value().data()[0]; 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string id = ParseOutgoingKey(iter->key().ToString()); 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<google::protobuf::MessageLite> message( 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildProtobufFromTag(tag)); 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!message.get() || 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !message->ParseFromString(iter->value().ToString().substr(1))) { 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to parse outgoing message with id " << id 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " and tag " << tag; 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found outgoing message with id " << id << " of type " 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << base::IntToString(tag); 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*outgoing_messages)[id] = make_linked_ptr(message.release()); 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) { 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string result; 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status status = 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Get(read_options, MakeSlice(kNextSerialNumberKey), &result); 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.ok()) { 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToInt64(result, next_serial_number)) { 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore the next serial number."; 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsNotFound()) { 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "No next serial number found."; 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error when reading the next serial number."; 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadUserSerialNumberMap( 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::map<std::string, int64>* user_serial_number_map) { 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kUserSerialNumberKeyStart)); 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kUserSerialNumberKeyEnd; 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string username = ParseUsername(iter->key().ToString()); 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (username.empty()) { 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading username. It should not be empty."; 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string serial_number_string = iter->value().ToString(); 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number = kSerialNumberMissing; 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToInt64(serial_number_string, &serial_number)) { 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading user serial number for user: " << username; 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*user_serial_number_map)[username] = serial_number; 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::GCMStoreImpl( 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool use_mock_keychain, 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : backend_(new Backend(path, base::MessageLoopProxy::current())), 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_(blocking_task_runner), 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_(this) { 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// On OSX, prevent the Keychain permissions popup during unit tests. 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_MACOSX) 627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::UseMockKeychain(use_mock_keychain); 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::~GCMStoreImpl() {} 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Load(const LoadCallback& callback) { 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Load, 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::LoadContinuation, 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 643a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Close() { 644a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) blocking_task_runner_->PostTask( 645a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Close, backend_)); 647a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 648a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Destroy(const UpdateCallback& callback) { 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Destroy, backend_, callback)); 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::SetDeviceCredentials(uint64 device_android_id, 6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::SetDeviceCredentials, 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_android_id, 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_security_token, 6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id, 6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddIncomingMessage, 6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessage(const std::string& persistent_id, 6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessages( 6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::AddOutgoingMessage(const std::string& persistent_id, 6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(app_id) == 0) 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id] = 0; 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[app_id] < kMessagesPerAppLimit) { 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]++; 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::AddOutgoingMessageContinuation, 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback, 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_id))); 7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::OverwriteOutgoingMessage(const std::string& persistent_id, 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // There should already be pending messages for this app. 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_.count(app_id)); 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(zea): consider verifying the specific message already exists. 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessage(const std::string& persistent_id, 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::RemoveOutgoingMessages, 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessages( 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::SetNextSerialNumber(int64 next_serial_number, 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::SetNextSerialNumber, 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_serial_number, 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddUserSerialNumber(const std::string& username, 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number, 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddUserSerialNumber, 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) username, 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) serial_number, 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveUserSerialNumber(const std::string& username, 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber, 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) username, 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result) { 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!result->success) { 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int num_throttled_apps = 0; 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (OutgoingMessageMap::const_iterator 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = result->outgoing_messages.begin(); 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != result->outgoing_messages.end(); ++iter) { 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const mcs_proto::DataMessageStanza* data_message = 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get()); 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message->category().empty()); 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(data_message->category()) == 0) 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()] = 1; 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()]++; 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[data_message->category()] == kMessagesPerAppLimit) 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_throttled_apps++; 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddOutgoingMessageContinuation( 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success) { 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_[app_id] > 0); 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]--; 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(success); 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessagesContinuation( 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success, 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppIdToMessageCountMap& removed_message_counts) { 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false); 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppIdToMessageCountMap::const_iterator iter = 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts.begin(); 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != removed_message_counts.end(); ++iter) { 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(app_message_counts_.count(iter->first), 0U); 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[iter->first] -= iter->second; 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GE(app_message_counts_[iter->first], 0); 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(true); 8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace gcm 855