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 3 // found in the LICENSE file. 4 5 #include "extensions/browser/api/cast_channel/cast_message_util.h" 6 7 #include "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/values.h" 11 #include "extensions/common/api/cast_channel.h" 12 #include "extensions/common/api/cast_channel/cast_channel.pb.h" 13 14 namespace { 15 static const char kAuthNamespace[] = 16 "urn:x-cast:com.google.cast.tp.deviceauth"; 17 // Sender and receiver IDs to use for platform messages. 18 static const char kPlatformSenderId[] = "sender-0"; 19 static const char kPlatformReceiverId[] = "receiver-0"; 20 } // namespace 21 22 namespace extensions { 23 namespace core_api { 24 namespace cast_channel { 25 26 bool MessageInfoToCastMessage(const MessageInfo& message, 27 CastMessage* message_proto) { 28 DCHECK(message_proto); 29 if (!message.data) 30 return false; 31 32 message_proto->set_protocol_version(CastMessage_ProtocolVersion_CASTV2_1_0); 33 message_proto->set_source_id(message.source_id); 34 message_proto->set_destination_id(message.destination_id); 35 message_proto->set_namespace_(message.namespace_); 36 // Determine the type of the base::Value and set the message payload 37 // appropriately. 38 std::string data; 39 base::BinaryValue* real_value; 40 switch (message.data->GetType()) { 41 // JS string 42 case base::Value::TYPE_STRING: 43 if (message.data->GetAsString(&data)) { 44 message_proto->set_payload_type(CastMessage_PayloadType_STRING); 45 message_proto->set_payload_utf8(data); 46 } 47 break; 48 // JS ArrayBuffer 49 case base::Value::TYPE_BINARY: 50 real_value = static_cast<base::BinaryValue*>(message.data.get()); 51 if (real_value->GetBuffer()) { 52 message_proto->set_payload_type(CastMessage_PayloadType_BINARY); 53 message_proto->set_payload_binary(real_value->GetBuffer(), 54 real_value->GetSize()); 55 } 56 break; 57 default: 58 // Unknown value type. message_proto will remain uninitialized because 59 // payload_type is unset. 60 break; 61 } 62 return message_proto->IsInitialized(); 63 } 64 65 bool IsCastMessageValid(const CastMessage& message_proto) { 66 if (message_proto.namespace_().empty() || message_proto.source_id().empty() || 67 message_proto.destination_id().empty()) { 68 return false; 69 } 70 return (message_proto.payload_type() == CastMessage_PayloadType_STRING && 71 message_proto.has_payload_utf8()) || 72 (message_proto.payload_type() == CastMessage_PayloadType_BINARY && 73 message_proto.has_payload_binary()); 74 } 75 76 bool CastMessageToMessageInfo(const CastMessage& message_proto, 77 MessageInfo* message) { 78 DCHECK(message); 79 message->source_id = message_proto.source_id(); 80 message->destination_id = message_proto.destination_id(); 81 message->namespace_ = message_proto.namespace_(); 82 // Determine the type of the payload and fill base::Value appropriately. 83 scoped_ptr<base::Value> value; 84 switch (message_proto.payload_type()) { 85 case CastMessage_PayloadType_STRING: 86 if (message_proto.has_payload_utf8()) 87 value.reset(new base::StringValue(message_proto.payload_utf8())); 88 break; 89 case CastMessage_PayloadType_BINARY: 90 if (message_proto.has_payload_binary()) 91 value.reset(base::BinaryValue::CreateWithCopiedBuffer( 92 message_proto.payload_binary().data(), 93 message_proto.payload_binary().size())); 94 break; 95 default: 96 // Unknown payload type. value will remain unset. 97 break; 98 } 99 if (value.get()) { 100 DCHECK(!message->data.get()); 101 message->data.reset(value.release()); 102 return true; 103 } else { 104 return false; 105 } 106 } 107 108 std::string CastMessageToString(const CastMessage& message_proto) { 109 std::string out("{"); 110 out += "namespace = " + message_proto.namespace_(); 111 out += ", sourceId = " + message_proto.source_id(); 112 out += ", destId = " + message_proto.destination_id(); 113 out += ", type = " + base::IntToString(message_proto.payload_type()); 114 out += ", str = \"" + message_proto.payload_utf8() + "\"}"; 115 return out; 116 } 117 118 std::string AuthMessageToString(const DeviceAuthMessage& message) { 119 std::string out("{"); 120 if (message.has_challenge()) { 121 out += "challenge: {}, "; 122 } 123 if (message.has_response()) { 124 out += "response: {signature: ("; 125 out += base::UintToString(message.response().signature().length()); 126 out += " bytes), certificate: ("; 127 out += base::UintToString( 128 message.response().client_auth_certificate().length()); 129 out += " bytes)}"; 130 } 131 if (message.has_error()) { 132 out += ", error: {"; 133 out += base::IntToString(message.error().error_type()); 134 out += "}"; 135 } 136 out += "}"; 137 return out; 138 } 139 140 void CreateAuthChallengeMessage(CastMessage* message_proto) { 141 CHECK(message_proto); 142 DeviceAuthMessage auth_message; 143 auth_message.mutable_challenge(); 144 std::string auth_message_string; 145 auth_message.SerializeToString(&auth_message_string); 146 147 message_proto->set_protocol_version(CastMessage_ProtocolVersion_CASTV2_1_0); 148 message_proto->set_source_id(kPlatformSenderId); 149 message_proto->set_destination_id(kPlatformReceiverId); 150 message_proto->set_namespace_(kAuthNamespace); 151 message_proto->set_payload_type(CastMessage_PayloadType_BINARY); 152 message_proto->set_payload_binary(auth_message_string); 153 } 154 155 bool IsAuthMessage(const CastMessage& message) { 156 return message.namespace_() == kAuthNamespace; 157 } 158 159 } // namespace cast_channel 160 } // namespace core_api 161 } // namespace extensions 162