Home | History | Annotate | Download | only in cast_channel
      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