1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/services/gcm/gcm_client_mock.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/sys_byteorder.h" 11 #include "base/time/time.h" 12 #include "content/public/browser/browser_thread.h" 13 14 namespace gcm { 15 16 namespace { 17 18 // Converts the 8-byte prefix of a string into a uint64 value. 19 uint64 HashToUInt64(const std::string& hash) { 20 uint64 value; 21 DCHECK_GE(hash.size(), sizeof(value)); 22 memcpy(&value, hash.data(), sizeof(value)); 23 return base::HostToNet64(value); 24 } 25 26 } // namespace 27 28 GCMClientMock::GCMClientMock() : checkin_failure_enabled_(false) { 29 } 30 31 GCMClientMock::~GCMClientMock() { 32 } 33 34 void GCMClientMock::CheckIn(const std::string& username, Delegate* delegate) { 35 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 36 37 DCHECK(delegates_.find(username) == delegates_.end()); 38 delegates_[username] = delegate; 39 40 // Simulate the android_id and secret by some sort of hashing. 41 CheckInInfo checkin_info; 42 if (!checkin_failure_enabled_) 43 checkin_info = GetCheckInInfoFromUsername(username); 44 45 base::MessageLoop::current()->PostTask( 46 FROM_HERE, 47 base::Bind(&GCMClientMock::CheckInFinished, 48 base::Unretained(this), 49 username, 50 checkin_info)); 51 } 52 53 void GCMClientMock::Register(const std::string& username, 54 const std::string& app_id, 55 const std::string& cert, 56 const std::vector<std::string>& sender_ids) { 57 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 58 59 std::string registration_id = GetRegistrationIdFromSenderIds(sender_ids); 60 61 base::MessageLoop::current()->PostTask( 62 FROM_HERE, 63 base::Bind(&GCMClientMock::RegisterFinished, 64 base::Unretained(this), 65 username, 66 app_id, 67 registration_id)); 68 } 69 70 void GCMClientMock::Unregister(const std::string& username, 71 const std::string& app_id) { 72 } 73 74 void GCMClientMock::Send(const std::string& username, 75 const std::string& app_id, 76 const std::string& receiver_id, 77 const OutgoingMessage& message) { 78 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 79 80 base::MessageLoop::current()->PostTask( 81 FROM_HERE, 82 base::Bind(&GCMClientMock::SendFinished, 83 base::Unretained(this), 84 username, 85 app_id, 86 message.id)); 87 } 88 89 bool GCMClientMock::IsLoading() const { 90 return false; 91 } 92 93 void GCMClientMock::ReceiveMessage(const std::string& username, 94 const std::string& app_id, 95 const IncomingMessage& message) { 96 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 97 98 content::BrowserThread::PostTask( 99 content::BrowserThread::IO, 100 FROM_HERE, 101 base::Bind(&GCMClientMock::MessageReceived, 102 base::Unretained(this), 103 username, 104 app_id, 105 message)); 106 } 107 108 void GCMClientMock::DeleteMessages(const std::string& username, 109 const std::string& app_id) { 110 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 111 112 content::BrowserThread::PostTask( 113 content::BrowserThread::IO, 114 FROM_HERE, 115 base::Bind(&GCMClientMock::MessagesDeleted, 116 base::Unretained(this), 117 username, 118 app_id)); 119 } 120 121 GCMClient::CheckInInfo GCMClientMock::GetCheckInInfoFromUsername( 122 const std::string& username) const { 123 CheckInInfo checkin_info; 124 checkin_info.android_id = HashToUInt64(username); 125 checkin_info.secret = checkin_info.android_id / 10; 126 return checkin_info; 127 } 128 129 std::string GCMClientMock::GetRegistrationIdFromSenderIds( 130 const std::vector<std::string>& sender_ids) const { 131 // Simulate the registration_id by concaternating all sender IDs. 132 // Set registration_id to empty to denote an error if sender_ids contains a 133 // hint. 134 std::string registration_id; 135 if (sender_ids.size() != 1 || 136 sender_ids[0].find("error") == std::string::npos) { 137 for (size_t i = 0; i < sender_ids.size(); ++i) { 138 if (i > 0) 139 registration_id += ","; 140 registration_id += sender_ids[i]; 141 } 142 } 143 return registration_id; 144 } 145 146 GCMClient::Delegate* GCMClientMock::GetDelegate( 147 const std::string& username) const { 148 std::map<std::string, Delegate*>::const_iterator iter = 149 delegates_.find(username); 150 DCHECK(iter != delegates_.end()); 151 return iter->second; 152 } 153 154 void GCMClientMock::CheckInFinished(std::string username, 155 CheckInInfo checkin_info) { 156 GetDelegate(username)->OnCheckInFinished( 157 checkin_info, checkin_info.IsValid() ? SUCCESS : SERVER_ERROR); 158 } 159 160 void GCMClientMock::RegisterFinished(std::string username, 161 std::string app_id, 162 std::string registrion_id) { 163 GetDelegate(username)->OnRegisterFinished( 164 app_id, registrion_id, registrion_id.empty() ? SERVER_ERROR : SUCCESS); 165 } 166 167 void GCMClientMock::SendFinished(std::string username, 168 std::string app_id, 169 std::string message_id) { 170 GetDelegate(username)->OnSendFinished(app_id, message_id, SUCCESS); 171 172 // Simulate send error if message id contains a hint. 173 if (message_id.find("error") != std::string::npos) { 174 base::MessageLoop::current()->PostDelayedTask( 175 FROM_HERE, 176 base::Bind(&GCMClientMock::MessageSendError, 177 base::Unretained(this), 178 username, 179 app_id, 180 message_id), 181 base::TimeDelta::FromMilliseconds(200)); 182 } 183 } 184 185 void GCMClientMock::MessageReceived(std::string username, 186 std::string app_id, 187 IncomingMessage message) { 188 GetDelegate(username)->OnMessageReceived(app_id, message); 189 } 190 191 void GCMClientMock::MessagesDeleted(std::string username, std::string app_id) { 192 GetDelegate(username)->OnMessagesDeleted(app_id); 193 } 194 195 void GCMClientMock::MessageSendError(std::string username, 196 std::string app_id, 197 std::string message_id) { 198 GetDelegate(username)->OnMessageSendError(app_id, message_id, NETWORK_ERROR); 199 } 200 201 } // namespace gcm 202