gcm_store_impl.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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"; 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Lowest lexicographically ordered app ids. 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Used for prefixing app id. 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kRegistrationKeyStart[] = "reg1-"; 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Key guaranteed to be higher than all app ids. 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Used for limiting iteration. 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kRegistrationKeyEnd[] = "reg2-"; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered incoming message key. 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing messages. 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kIncomingMsgKeyStart[] = "incoming1-"; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all incoming message keys. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kIncomingMsgKeyEnd[] = "incoming2-"; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Lowest lexicographically ordered outgoing message key. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for prefixing outgoing messages. 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kOutgoingMsgKeyStart[] = "outgoing1-"; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Key guaranteed to be higher than all outgoing message keys. 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used for limiting iteration. 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kOutgoingMsgKeyEnd[] = "outgoing2-"; 56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Key used to timestamp last checkin (marked with G services settings update). 57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kLastCheckinTimeKey[] = "last_checkin_time"; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string MakeRegistrationKey(const std::string& app_id) { 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return kRegistrationKeyStart + app_id; 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string ParseRegistrationKey(const std::string& key) { 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return key.substr(arraysize(kRegistrationKeyStart) - 1); 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeIncomingKey(const std::string& persistent_id) { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kIncomingMsgKeyStart + persistent_id; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeOutgoingKey(const std::string& persistent_id) { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return kOutgoingMsgKeyStart + persistent_id; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string ParseOutgoingKey(const std::string& key) { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return key.substr(arraysize(kOutgoingMsgKeyStart) - 1); 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// outlive the slice. 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For example: MakeSlice(MakeOutgoingKey(x)) is invalid. 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)leveldb::Slice MakeSlice(const base::StringPiece& s) { 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return leveldb::Slice(s.begin(), s.size()); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GCMStoreImpl::Backend 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Backend(const base::FilePath& path, 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_runner); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Blocking implementations of GCMStoreImpl methods. 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Load(const LoadCallback& callback); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void Close(); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Destroy(const UpdateCallback& callback); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetDeviceCredentials(uint64 device_android_id, 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void AddRegistration(const std::string& app_id, 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback); 104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void RemoveRegistration(const std::string& app_id, 105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddIncomingMessage(const std::string& persistent_id, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveIncomingMessages(const PersistentIdList& persistent_ids, 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddOutgoingMessage(const std::string& persistent_id, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveOutgoingMessages( 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddUserSerialNumber(const std::string& username, 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 serial_number, 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveUserSerialNumber(const std::string& username, 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback); 122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void SetLastCheckinTime(const base::Time& last_checkin_time, 123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class base::RefCountedThreadSafe<Backend>; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Backend(); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool LoadRegistrations(RegistrationInfoMap* registrations); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages); 133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool LoadLastCheckinTime(base::Time* last_checkin_time); 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath path_; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::DB> db_; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::Backend( 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : path_(path), foreground_task_runner_(foreground_task_runner) {} 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::Backend::~Backend() {} 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result(new LoadResult()); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_.get()) { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Attempting to reload open database."; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Options options; 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.create_if_missing = true; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB* db; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status status = 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!status.ok()) { 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to open database " << path_.value() << ": " 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << status.ToString(); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(db); 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!LoadDeviceCredentials(&result->device_android_id, 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &result->device_security_token) || 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !LoadRegistrations(&result->registrations) || 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !LoadIncomingMessages(&result->incoming_messages) || 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !LoadOutgoingMessages(&result->outgoing_messages) || 179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !LoadLastCheckinTime(&result->last_checkin_time)) { 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_android_id = 0; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->device_security_token = 0; 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result->registrations.clear(); 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.clear(); 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.clear(); 185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch result->last_checkin_time = base::Time::FromInternalValue(0LL); 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&result))); 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only record histograms if GCM had already been set up for this device. 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result->device_android_id != 0 && result->device_security_token != 0) { 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 file_size = 0; 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (base::GetFileSize(path_, &file_size)) { 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<int>(file_size / 1024)); 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_COUNTS("GCM.RestoredRegistrations", 200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch result->registrations.size()); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->outgoing_messages.size()); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->incoming_messages.size()); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Succeeded in loading " << result->registrations.size() 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << " registrations, " 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << result->incoming_messages.size() 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged incoming messages and " 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << result->outgoing_messages.size() 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " unacknowledged outgoing messages."; 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->success = true; 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) 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Backend::Close() { 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Closing GCM store."; 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) db_.reset(); 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Destroying GCM store."; 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_.reset(); 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Destroy failed: " << s.ToString(); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::SetDeviceCredentials( 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_android_id, 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving device credentials with AID " << device_android_id; 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string encrypted_token; 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::EncryptString(base::Uint64ToString(device_security_token), 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &encrypted_token); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string android_id_str = base::Uint64ToString(device_android_id); 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->Put(write_options, 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(kDeviceAIDKey), 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(android_id_str)); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Put( 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token)); 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::Backend::AddRegistration( 273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id, 274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Saving registration info for app: " << app_id; 277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!db_.get()) { 278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "GCMStore db doesn't exist."; 279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::WriteOptions write_options; 283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch write_options.sync = true; 284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string key = MakeRegistrationKey(app_id); 286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string value = registration->SerializeAsString(); 287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const leveldb::Status status = db_->Put(write_options, 288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeSlice(key), 289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeSlice(value)); 290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (status.ok()) { 291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "LevelDB put failed: " << status.ToString(); 295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 296effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 297effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 298effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::Backend::RemoveRegistration(const std::string& app_id, 299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!db_.get()) { 301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "GCMStore db doesn't exist."; 302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::WriteOptions write_options; 306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch write_options.sync = true; 307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::Status status = db_->Delete(write_options, MakeSlice(app_id)); 309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (status.ok()) { 310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "LevelDB remove failed: " << status.ToString(); 314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 315effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id, 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving incoming message with id " << persistent_id; 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(persistent_id); 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(persistent_id)); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveIncomingMessages( 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing incoming message with id " << *iter; 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeIncomingKey(*iter); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id, 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Saving outgoing message with id " << persistent_id; 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string data = 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<char>(message.tag()) + message.SerializeAsString(); 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(persistent_id); 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Status s = db_->Put(write_options, 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(data)); 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Backend::RemoveOutgoingMessages( 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool, const AppIdToMessageCountMap&)> 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback) { 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_.get()) { 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GCMStore db doesn't exist."; 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::WriteOptions write_options; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_options.sync = true; 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap removed_message_counts; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (PersistentIdList::const_iterator iter = persistent_ids.begin(); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != persistent_ids.end(); 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string outgoing_message; 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string key = MakeOutgoingKey(*iter); 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeSlice(key), 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &outgoing_message); 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mcs_proto::DataMessageStanza data_message; 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Skip the initial tag byte and parse the rest to extract the message. 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (data_message.ParseFromString(outgoing_message.substr(1))) { 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message.category().empty()); 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (removed_message_counts.count(data_message.category()) != 0) 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()]++; 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts[data_message.category()] = 1; 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Removing outgoing message with id " << *iter; 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Delete(write_options, MakeSlice(key)); 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!s.ok()) 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts)); 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) foreground_task_runner_->PostTask(FROM_HERE, 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIdToMessageCountMap())); 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GCMStoreImpl::Backend::SetLastCheckinTime( 455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Time& last_checkin_time, 456c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback) { 457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::WriteOptions write_options; 458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch write_options.sync = true; 459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 last_checkin_time_internal = last_checkin_time.ToInternalValue(); 461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const leveldb::Status s = 462c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch db_->Put(write_options, 463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(kLastCheckinTimeKey), 464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(base::Int64ToString(last_checkin_time_internal))); 465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!s.ok()) 467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "LevelDB set last checkin time failed: " << s.ToString(); 468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, s.ok())); 470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 471c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id, 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64* security_token) { 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string result; 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result); 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(result, android_id)) { 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore device id."; 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.clear(); 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) s = db_->Get(read_options, MakeSlice(kDeviceTokenKey), &result); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.ok()) { 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string decrypted_token; 489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::DecryptString(result, &decrypted_token); 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::StringToUint64(decrypted_token, security_token)) { 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to restore security token."; 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.IsNotFound()) { 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "No credentials found."; 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading credentials from store."; 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 506effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool GCMStoreImpl::Backend::LoadRegistrations( 507effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RegistrationInfoMap* registrations) { 508effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::ReadOptions read_options; 509effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch read_options.verify_checksums = true; 510effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 511effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 512effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (iter->Seek(MakeSlice(kRegistrationKeyStart)); 513effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch iter->Valid() && iter->key().ToString() < kRegistrationKeyEnd; 514effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch iter->Next()) { 515effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch leveldb::Slice s = iter->value(); 516effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (s.size() <= 1) { 517effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Error reading registration with key " << s.ToString(); 518effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 519effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 520effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string app_id = ParseRegistrationKey(iter->key().ToString()); 521effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch linked_ptr<RegistrationInfo> registration(new RegistrationInfo); 522effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!registration->ParseFromString(iter->value().ToString())) { 523effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG(ERROR) << "Failed to parse registration with app id " << app_id; 524effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 525effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 526effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(1) << "Found registration with app id " << app_id; 527effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (*registrations)[app_id] = registration; 528effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 529effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 530effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 531effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 532effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadIncomingMessages( 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>* incoming_messages) { 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kIncomingMsgKeyStart)); 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd; 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.empty()) { 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << iter->key().ToString(); 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found incoming message with id " << s.ToString(); 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) incoming_messages->push_back(s.ToString()); 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::Backend::LoadOutgoingMessages( 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OutgoingMessageMap* outgoing_messages) { 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::ReadOptions read_options; 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_options.verify_checksums = true; 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->Next()) { 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Slice s = iter->value(); 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (s.size() <= 1) { 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8 tag = iter->value().data()[0]; 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string id = ParseOutgoingKey(iter->key().ToString()); 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<google::protobuf::MessageLite> message( 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildProtobufFromTag(tag)); 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!message.get() || 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !message->ParseFromString(iter->value().ToString().substr(1))) { 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to parse outgoing message with id " << id 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " and tag " << tag; 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Found outgoing message with id " << id << " of type " 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << base::IntToString(tag); 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*outgoing_messages)[id] = make_linked_ptr(message.release()); 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 587c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool GCMStoreImpl::Backend::LoadLastCheckinTime( 588c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Time* last_checkin_time) { 589c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::ReadOptions read_options; 590c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch read_options.verify_checksums = true; 591c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 592c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::string result; 593c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch leveldb::Status s = db_->Get(read_options, 594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch MakeSlice(kLastCheckinTimeKey), 595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &result); 596c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 time_internal = 0LL; 597c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (s.ok() && !base::StringToInt64(result, &time_internal)) 598c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "Failed to restore last checkin time. Using default = 0."; 599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 600c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // In case we cannot read last checkin time, we default it to 0, as we don't 601c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // want that situation to cause the whole load to fail. 602c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *last_checkin_time = base::Time::FromInternalValue(time_internal); 603c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 604c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return true; 605c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 606c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::GCMStoreImpl( 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool use_mock_keychain, 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : backend_(new Backend(path, base::MessageLoopProxy::current())), 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_(blocking_task_runner), 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_(this) { 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// On OSX, prevent the Keychain permissions popup during unit tests. 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_MACOSX) 616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OSCrypt::UseMockKeychain(use_mock_keychain); 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GCMStoreImpl::~GCMStoreImpl() {} 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Load(const LoadCallback& callback) { 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Load, 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::LoadContinuation, 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMStoreImpl::Close() { 633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) blocking_task_runner_->PostTask( 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Close, backend_)); 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::Destroy(const UpdateCallback& callback) { 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::Destroy, backend_, callback)); 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::SetDeviceCredentials(uint64 device_android_id, 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 device_security_token, 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::SetDeviceCredentials, 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_android_id, 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_security_token, 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::AddRegistration( 657effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id, 658effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const linked_ptr<RegistrationInfo>& registration, 659effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 660effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blocking_task_runner_->PostTask( 661effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 662effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&GCMStoreImpl::Backend::AddRegistration, 663effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch backend_, 664effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id, 665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registration, 666effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback)); 667effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 668effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 669effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid GCMStoreImpl::RemoveRegistration(const std::string& app_id, 670effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const UpdateCallback& callback) { 671effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blocking_task_runner_->PostTask( 672effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 673effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&GCMStoreImpl::Backend::RemoveRegistration, 674effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch backend_, 675effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id, 676effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback)); 677effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 678effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id, 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddIncomingMessage, 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessage(const std::string& persistent_id, 6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveIncomingMessages( 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveIncomingMessages, 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GCMStoreImpl::AddOutgoingMessage(const std::string& persistent_id, 7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(app_id) == 0) 7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id] = 0; 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[app_id] < kMessagesPerAppLimit) { 7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]++; 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::AddOutgoingMessageContinuation, 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback, 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_id))); 7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::OverwriteOutgoingMessage(const std::string& persistent_id, 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const MCSMessage& message, 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(message.tag(), kDataMessageStanzaTag); 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>( 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &message.GetProtobuf())->category(); 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!app_id.empty()); 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // There should already be pending messages for this app. 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_.count(app_id)); 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(zea): consider verifying the specific message already exists. 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::AddOutgoingMessage, 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_id, 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message, 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessage(const std::string& persistent_id, 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback) { 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_->PostTask( 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::Backend::RemoveOutgoingMessages, 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PersistentIdList(1, persistent_id), 7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessages( 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PersistentIdList& persistent_ids, 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::RemoveOutgoingMessages, 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backend_, 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) persistent_ids, 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation, 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback))); 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 781c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GCMStoreImpl::SetLastCheckinTime(const base::Time& last_checkin_time, 782c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const UpdateCallback& callback) { 783c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch blocking_task_runner_->PostTask( 784c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 785c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&GCMStoreImpl::Backend::SetLastCheckinTime, 786c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch backend_, 787c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch last_checkin_time, 788c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback)); 789c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 790c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LoadResult> result) { 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!result->success) { 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int num_throttled_apps = 0; 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (OutgoingMessageMap::const_iterator 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter = result->outgoing_messages.begin(); 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != result->outgoing_messages.end(); ++iter) { 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const mcs_proto::DataMessageStanza* data_message = 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get()); 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!data_message->category().empty()); 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_.count(data_message->category()) == 0) 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()] = 1; 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[data_message->category()]++; 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_message_counts_[data_message->category()] == kMessagesPerAppLimit) 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_throttled_apps++; 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(result.Pass()); 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::AddOutgoingMessageContinuation( 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success) { 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(app_message_counts_[app_id] > 0); 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[app_id]--; 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(success); 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GCMStoreImpl::RemoveOutgoingMessagesContinuation( 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const UpdateCallback& callback, 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success, 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppIdToMessageCountMap& removed_message_counts) { 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!success) { 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(false); 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppIdToMessageCountMap::const_iterator iter = 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) removed_message_counts.begin(); 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != removed_message_counts.end(); ++iter) { 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(app_message_counts_.count(iter->first), 0U); 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_message_counts_[iter->first] -= iter->second; 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GE(app_message_counts_[iter->first], 0); 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback.Run(true); 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace gcm 845