| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/proximity_auth/messenger_impl.h" | 5 #include "components/proximity_auth/messenger_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
| 9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
| 10 #include "base/location.h" |
| 11 #include "base/thread_task_runner_handle.h" |
| 10 #include "base/values.h" | 12 #include "base/values.h" |
| 11 #include "components/proximity_auth/connection.h" | 13 #include "components/proximity_auth/connection.h" |
| 12 #include "components/proximity_auth/cryptauth/base64url.h" | 14 #include "components/proximity_auth/cryptauth/base64url.h" |
| 13 #include "components/proximity_auth/logging/logging.h" | 15 #include "components/proximity_auth/logging/logging.h" |
| 14 #include "components/proximity_auth/messenger_observer.h" | 16 #include "components/proximity_auth/messenger_observer.h" |
| 15 #include "components/proximity_auth/remote_status_update.h" | 17 #include "components/proximity_auth/remote_status_update.h" |
| 16 #include "components/proximity_auth/secure_context.h" | 18 #include "components/proximity_auth/secure_context.h" |
| 17 #include "components/proximity_auth/wire_message.h" | 19 #include "components/proximity_auth/wire_message.h" |
| 18 | 20 |
| 19 namespace proximity_auth { | 21 namespace proximity_auth { |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 // The key names of JSON fields for messages sent between the devices. | 24 // The key names of JSON fields for messages sent between the devices. |
| 23 const char kTypeKey[] = "type"; | 25 const char kTypeKey[] = "type"; |
| 24 const char kNameKey[] = "name"; | 26 const char kNameKey[] = "name"; |
| 25 const char kDataKey[] = "data"; | 27 const char kDataKey[] = "data"; |
| 26 const char kEncryptedDataKey[] = "encrypted_data"; | 28 const char kEncryptedDataKey[] = "encrypted_data"; |
| 27 | 29 |
| 28 // The types of messages that can be sent and received. | 30 // The types of messages that can be sent and received. |
| 29 const char kMessageTypeLocalEvent[] = "event"; | 31 const char kMessageTypeLocalEvent[] = "event"; |
| 30 const char kMessageTypeRemoteStatusUpdate[] = "status_update"; | 32 const char kMessageTypeRemoteStatusUpdate[] = "status_update"; |
| 31 const char kMessageTypeDecryptRequest[] = "decrypt_request"; | 33 const char kMessageTypeDecryptRequest[] = "decrypt_request"; |
| 32 const char kMessageTypeDecryptResponse[] = "decrypt_response"; | 34 const char kMessageTypeDecryptResponse[] = "decrypt_response"; |
| 33 const char kMessageTypeUnlockRequest[] = "unlock_request"; | 35 const char kMessageTypeUnlockRequest[] = "unlock_request"; |
| 34 const char kMessageTypeUnlockResponse[] = "unlock_response"; | 36 const char kMessageTypeUnlockResponse[] = "unlock_response"; |
| 35 | 37 |
| 36 // The name for an unlock event originating from the local device. | 38 // The name for an unlock event originating from the local device. |
| 37 const char kUnlockEventName[] = "easy_unlock"; | 39 const char kUnlockEventName[] = "easy_unlock"; |
| 38 | 40 |
| 41 // Messages sent and received from the iOS app when polling for it's lock screen |
| 42 // status. |
| 43 // TODO(tengs): Unify the iOS status update protocol with the existing Android |
| 44 // protocol, so we don't have this special case. |
| 45 const char kPollScreenState[] = "PollScreenState"; |
| 46 const char kScreenUnlocked[] = "Screen Unlocked"; |
| 47 const char kScreenLocked[] = "Screen Locked"; |
| 48 const int kIOSPollingIntervalSeconds = 5; |
| 49 |
| 39 // Serializes the |value| to a JSON string and returns the result. | 50 // Serializes the |value| to a JSON string and returns the result. |
| 40 std::string SerializeValueToJson(const base::Value& value) { | 51 std::string SerializeValueToJson(const base::Value& value) { |
| 41 std::string json; | 52 std::string json; |
| 42 base::JSONWriter::Write(value, &json); | 53 base::JSONWriter::Write(value, &json); |
| 43 return json; | 54 return json; |
| 44 } | 55 } |
| 45 | 56 |
| 46 // Returns the message type represented by the |message|. This is a convenience | 57 // Returns the message type represented by the |message|. This is a convenience |
| 47 // wrapper that should only be called when the |message| is known to specify its | 58 // wrapper that should only be called when the |message| is known to specify its |
| 48 // message type, i.e. this should not be called for untrusted input. | 59 // message type, i.e. this should not be called for untrusted input. |
| 49 std::string GetMessageType(const base::DictionaryValue& message) { | 60 std::string GetMessageType(const base::DictionaryValue& message) { |
| 50 std::string type; | 61 std::string type; |
| 51 message.GetString(kTypeKey, &type); | 62 message.GetString(kTypeKey, &type); |
| 52 return type; | 63 return type; |
| 53 } | 64 } |
| 54 | 65 |
| 55 } // namespace | 66 } // namespace |
| 56 | 67 |
| 57 MessengerImpl::MessengerImpl(scoped_ptr<Connection> connection, | 68 MessengerImpl::MessengerImpl(scoped_ptr<Connection> connection, |
| 58 scoped_ptr<SecureContext> secure_context) | 69 scoped_ptr<SecureContext> secure_context) |
| 59 : connection_(connection.Pass()), | 70 : connection_(connection.Pass()), |
| 60 secure_context_(secure_context.Pass()), | 71 secure_context_(secure_context.Pass()), |
| 61 weak_ptr_factory_(this) { | 72 weak_ptr_factory_(this) { |
| 62 DCHECK(connection_->IsConnected()); | 73 DCHECK(connection_->IsConnected()); |
| 63 connection_->AddObserver(this); | 74 connection_->AddObserver(this); |
| 75 |
| 76 // TODO(tengs): We need CryptAuth to report if the phone runs iOS or Android, |
| 77 // rather than relying on this heuristic. |
| 78 if (connection_->remote_device().bluetooth_type == RemoteDevice::BLUETOOTH_LE) |
| 79 PollScreenStateForIOS(); |
| 64 } | 80 } |
| 65 | 81 |
| 66 MessengerImpl::~MessengerImpl() { | 82 MessengerImpl::~MessengerImpl() { |
| 67 if (connection_) | 83 if (connection_) |
| 68 connection_->RemoveObserver(this); | 84 connection_->RemoveObserver(this); |
| 69 } | 85 } |
| 70 | 86 |
| 71 void MessengerImpl::AddObserver(MessengerObserver* observer) { | 87 void MessengerImpl::AddObserver(MessengerObserver* observer) { |
| 72 observers_.AddObserver(observer); | 88 observers_.AddObserver(observer); |
| 73 } | 89 } |
| 74 | 90 |
| 75 void MessengerImpl::RemoveObserver(MessengerObserver* observer) { | 91 void MessengerImpl::RemoveObserver(MessengerObserver* observer) { |
| 76 observers_.RemoveObserver(observer); | 92 observers_.RemoveObserver(observer); |
| 77 } | 93 } |
| 78 | 94 |
| 79 bool MessengerImpl::SupportsSignIn() const { | 95 bool MessengerImpl::SupportsSignIn() const { |
| 96 // TODO(tengs): Support sign-in for Bluetooth LE protocol. |
| 80 return (secure_context_->GetProtocolVersion() == | 97 return (secure_context_->GetProtocolVersion() == |
| 81 SecureContext::PROTOCOL_VERSION_THREE_ONE); | 98 SecureContext::PROTOCOL_VERSION_THREE_ONE) && |
| 99 connection_->remote_device().bluetooth_type != |
| 100 RemoteDevice::BLUETOOTH_LE; |
| 82 } | 101 } |
| 83 | 102 |
| 84 void MessengerImpl::DispatchUnlockEvent() { | 103 void MessengerImpl::DispatchUnlockEvent() { |
| 85 base::DictionaryValue message; | 104 base::DictionaryValue message; |
| 86 message.SetString(kTypeKey, kMessageTypeLocalEvent); | 105 message.SetString(kTypeKey, kMessageTypeLocalEvent); |
| 87 message.SetString(kNameKey, kUnlockEventName); | 106 message.SetString(kNameKey, kUnlockEventName); |
| 88 queued_messages_.push_back(PendingMessage(message)); | 107 queued_messages_.push_back(PendingMessage(message)); |
| 89 ProcessMessageQueue(); | 108 ProcessMessageQueue(); |
| 90 } | 109 } |
| 91 | 110 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 ProcessMessageQueue(); | 143 ProcessMessageQueue(); |
| 125 } | 144 } |
| 126 | 145 |
| 127 MessengerImpl::PendingMessage::PendingMessage() {} | 146 MessengerImpl::PendingMessage::PendingMessage() {} |
| 128 | 147 |
| 129 MessengerImpl::PendingMessage::PendingMessage( | 148 MessengerImpl::PendingMessage::PendingMessage( |
| 130 const base::DictionaryValue& message) | 149 const base::DictionaryValue& message) |
| 131 : json_message(SerializeValueToJson(message)), | 150 : json_message(SerializeValueToJson(message)), |
| 132 type(GetMessageType(message)) {} | 151 type(GetMessageType(message)) {} |
| 133 | 152 |
| 153 MessengerImpl::PendingMessage::PendingMessage(const std::string& message) |
| 154 : json_message(message), type(std::string()) {} |
| 155 |
| 134 MessengerImpl::PendingMessage::~PendingMessage() {} | 156 MessengerImpl::PendingMessage::~PendingMessage() {} |
| 135 | 157 |
| 136 void MessengerImpl::ProcessMessageQueue() { | 158 void MessengerImpl::ProcessMessageQueue() { |
| 137 if (pending_message_ || queued_messages_.empty() || | 159 if (pending_message_ || queued_messages_.empty() || |
| 138 connection_->is_sending_message()) | 160 connection_->is_sending_message()) |
| 139 return; | 161 return; |
| 140 | 162 |
| 141 pending_message_.reset(new PendingMessage(queued_messages_.front())); | 163 pending_message_.reset(new PendingMessage(queued_messages_.front())); |
| 142 queued_messages_.pop_front(); | 164 queued_messages_.pop_front(); |
| 143 | 165 |
| 144 secure_context_->Encode(pending_message_->json_message, | 166 secure_context_->Encode(pending_message_->json_message, |
| 145 base::Bind(&MessengerImpl::OnMessageEncoded, | 167 base::Bind(&MessengerImpl::OnMessageEncoded, |
| 146 weak_ptr_factory_.GetWeakPtr())); | 168 weak_ptr_factory_.GetWeakPtr())); |
| 147 } | 169 } |
| 148 | 170 |
| 149 void MessengerImpl::OnMessageEncoded(const std::string& encoded_message) { | 171 void MessengerImpl::OnMessageEncoded(const std::string& encoded_message) { |
| 150 connection_->SendMessage(make_scoped_ptr(new WireMessage(encoded_message))); | 172 connection_->SendMessage(make_scoped_ptr(new WireMessage(encoded_message))); |
| 151 } | 173 } |
| 152 | 174 |
| 153 void MessengerImpl::OnMessageDecoded(const std::string& decoded_message) { | 175 void MessengerImpl::OnMessageDecoded(const std::string& decoded_message) { |
| 176 // TODO(tengs): Unify the iOS status update protocol with the existing Android |
| 177 // protocol, so we don't have this special case. |
| 178 if (decoded_message == kScreenUnlocked || decoded_message == kScreenLocked) { |
| 179 RemoteStatusUpdate update; |
| 180 update.user_presence = |
| 181 (decoded_message == kScreenUnlocked ? USER_PRESENT : USER_ABSENT); |
| 182 update.secure_screen_lock_state = SECURE_SCREEN_LOCK_ENABLED; |
| 183 update.trust_agent_state = TRUST_AGENT_ENABLED; |
| 184 FOR_EACH_OBSERVER(MessengerObserver, observers_, |
| 185 OnRemoteStatusUpdate(update)); |
| 186 pending_message_.reset(); |
| 187 ProcessMessageQueue(); |
| 188 return; |
| 189 } |
| 190 |
| 154 // The decoded message should be a JSON string. | 191 // The decoded message should be a JSON string. |
| 155 scoped_ptr<base::Value> message_value = | 192 scoped_ptr<base::Value> message_value = |
| 156 base::JSONReader::Read(decoded_message); | 193 base::JSONReader::Read(decoded_message); |
| 157 if (!message_value || !message_value->IsType(base::Value::TYPE_DICTIONARY)) { | 194 if (!message_value || !message_value->IsType(base::Value::TYPE_DICTIONARY)) { |
| 158 PA_LOG(ERROR) << "Unable to parse message as JSON:\n" << decoded_message; | 195 PA_LOG(ERROR) << "Unable to parse message as JSON:\n" << decoded_message; |
| 159 return; | 196 return; |
| 160 } | 197 } |
| 161 | 198 |
| 162 base::DictionaryValue* message; | 199 base::DictionaryValue* message; |
| 163 bool success = message_value->GetAsDictionary(&message); | 200 bool success = message_value->GetAsDictionary(&message); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 } | 273 } |
| 237 FOR_EACH_OBSERVER(MessengerObserver, observers_, | 274 FOR_EACH_OBSERVER(MessengerObserver, observers_, |
| 238 OnDecryptResponse(response.Pass())); | 275 OnDecryptResponse(response.Pass())); |
| 239 } | 276 } |
| 240 | 277 |
| 241 void MessengerImpl::HandleUnlockResponseMessage( | 278 void MessengerImpl::HandleUnlockResponseMessage( |
| 242 const base::DictionaryValue& message) { | 279 const base::DictionaryValue& message) { |
| 243 FOR_EACH_OBSERVER(MessengerObserver, observers_, OnUnlockResponse(true)); | 280 FOR_EACH_OBSERVER(MessengerObserver, observers_, OnUnlockResponse(true)); |
| 244 } | 281 } |
| 245 | 282 |
| 283 void MessengerImpl::PollScreenStateForIOS() { |
| 284 if (!connection_->IsConnected()) |
| 285 return; |
| 286 |
| 287 // Sends message requesting screen state. |
| 288 queued_messages_.push_back(PendingMessage(std::string(kPollScreenState))); |
| 289 ProcessMessageQueue(); |
| 290 |
| 291 // Schedules the next message in |kPollingIntervalSeconds|. |
| 292 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 293 FROM_HERE, base::Bind(&MessengerImpl::PollScreenStateForIOS, |
| 294 weak_ptr_factory_.GetWeakPtr()), |
| 295 base::TimeDelta::FromSeconds(kIOSPollingIntervalSeconds)); |
| 296 } |
| 297 |
| 246 void MessengerImpl::OnConnectionStatusChanged(Connection* connection, | 298 void MessengerImpl::OnConnectionStatusChanged(Connection* connection, |
| 247 Connection::Status old_status, | 299 Connection::Status old_status, |
| 248 Connection::Status new_status) { | 300 Connection::Status new_status) { |
| 249 DCHECK_EQ(connection, connection_.get()); | 301 DCHECK_EQ(connection, connection_.get()); |
| 250 if (new_status == Connection::DISCONNECTED) { | 302 if (new_status == Connection::DISCONNECTED) { |
| 251 PA_LOG(INFO) << "Secure channel disconnected..."; | 303 PA_LOG(INFO) << "Secure channel disconnected..."; |
| 252 connection_->RemoveObserver(this); | 304 connection_->RemoveObserver(this); |
| 253 connection_.reset(); | |
| 254 FOR_EACH_OBSERVER(MessengerObserver, observers_, OnDisconnected()); | 305 FOR_EACH_OBSERVER(MessengerObserver, observers_, OnDisconnected()); |
| 255 // TODO(isherman): Determine whether it's also necessary/appropriate to fire | 306 // TODO(isherman): Determine whether it's also necessary/appropriate to fire |
| 256 // this notification from the destructor. | 307 // this notification from the destructor. |
| 257 } | 308 } |
| 258 } | 309 } |
| 259 | 310 |
| 260 void MessengerImpl::OnMessageReceived(const Connection& connection, | 311 void MessengerImpl::OnMessageReceived(const Connection& connection, |
| 261 const WireMessage& wire_message) { | 312 const WireMessage& wire_message) { |
| 262 secure_context_->Decode(wire_message.payload(), | 313 secure_context_->Decode(wire_message.payload(), |
| 263 base::Bind(&MessengerImpl::OnMessageDecoded, | 314 base::Bind(&MessengerImpl::OnMessageDecoded, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 293 } else { | 344 } else { |
| 294 PA_LOG(ERROR) << "Message of unknown type '" << pending_message_->type | 345 PA_LOG(ERROR) << "Message of unknown type '" << pending_message_->type |
| 295 << "' sent."; | 346 << "' sent."; |
| 296 } | 347 } |
| 297 | 348 |
| 298 pending_message_.reset(); | 349 pending_message_.reset(); |
| 299 ProcessMessageQueue(); | 350 ProcessMessageQueue(); |
| 300 } | 351 } |
| 301 | 352 |
| 302 } // namespace proximity_auth | 353 } // namespace proximity_auth |
| OLD | NEW |