summaryrefslogtreecommitdiff
path: root/chromium/extensions/browser/api/cast_channel/cast_message_util.cc
blob: 76fa2d0218a874a9b176f09d3246688bd6234e51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/browser/api/cast_channel/cast_message_util.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "extensions/common/api/cast_channel.h"
#include "extensions/common/api/cast_channel/cast_channel.pb.h"

namespace {
static const char kAuthNamespace[] =
    "urn:x-cast:com.google.cast.tp.deviceauth";
// Sender and receiver IDs to use for platform messages.
static const char kPlatformSenderId[] = "sender-0";
static const char kPlatformReceiverId[] = "receiver-0";
}  // namespace

namespace extensions {
namespace api {
namespace cast_channel {

bool MessageInfoToCastMessage(const MessageInfo& message,
                              CastMessage* message_proto) {
  DCHECK(message_proto);
  if (!message.data)
    return false;

  message_proto->set_protocol_version(CastMessage_ProtocolVersion_CASTV2_1_0);
  message_proto->set_source_id(message.source_id);
  message_proto->set_destination_id(message.destination_id);
  message_proto->set_namespace_(message.namespace_);
  // Determine the type of the base::Value and set the message payload
  // appropriately.
  std::string data;
  base::BinaryValue* real_value;
  switch (message.data->GetType()) {
    // JS string
    case base::Value::TYPE_STRING:
      if (message.data->GetAsString(&data)) {
        message_proto->set_payload_type(CastMessage_PayloadType_STRING);
        message_proto->set_payload_utf8(data);
      }
      break;
    // JS ArrayBuffer
    case base::Value::TYPE_BINARY:
      real_value = static_cast<base::BinaryValue*>(message.data.get());
      if (real_value->GetBuffer()) {
        message_proto->set_payload_type(CastMessage_PayloadType_BINARY);
        message_proto->set_payload_binary(real_value->GetBuffer(),
                                          real_value->GetSize());
      }
      break;
    default:
      // Unknown value type.  message_proto will remain uninitialized because
      // payload_type is unset.
      break;
  }
  return message_proto->IsInitialized();
}

bool IsCastMessageValid(const CastMessage& message_proto) {
  if (message_proto.namespace_().empty() || message_proto.source_id().empty() ||
      message_proto.destination_id().empty()) {
    return false;
  }
  return (message_proto.payload_type() == CastMessage_PayloadType_STRING &&
          message_proto.has_payload_utf8()) ||
         (message_proto.payload_type() == CastMessage_PayloadType_BINARY &&
          message_proto.has_payload_binary());
}

bool CastMessageToMessageInfo(const CastMessage& message_proto,
                              MessageInfo* message) {
  DCHECK(message);
  message->source_id = message_proto.source_id();
  message->destination_id = message_proto.destination_id();
  message->namespace_ = message_proto.namespace_();
  // Determine the type of the payload and fill base::Value appropriately.
  scoped_ptr<base::Value> value;
  switch (message_proto.payload_type()) {
  case CastMessage_PayloadType_STRING:
    if (message_proto.has_payload_utf8())
      value.reset(new base::StringValue(message_proto.payload_utf8()));
    break;
  case CastMessage_PayloadType_BINARY:
    if (message_proto.has_payload_binary())
      value.reset(base::BinaryValue::CreateWithCopiedBuffer(
        message_proto.payload_binary().data(),
        message_proto.payload_binary().size()));
    break;
  default:
    // Unknown payload type. value will remain unset.
    break;
  }
  if (value.get()) {
    DCHECK(!message->data.get());
    message->data.reset(value.release());
    return true;
  } else {
    return false;
  }
}

std::string CastMessageToString(const CastMessage& message_proto) {
  std::string out("{");
  out += "namespace = " + message_proto.namespace_();
  out += ", sourceId = " + message_proto.source_id();
  out += ", destId = " + message_proto.destination_id();
  out += ", type = " + base::IntToString(message_proto.payload_type());
  out += ", str = \"" + message_proto.payload_utf8() + "\"}";
  return out;
}

std::string AuthMessageToString(const DeviceAuthMessage& message) {
  std::string out("{");
  if (message.has_challenge()) {
    out += "challenge: {}, ";
  }
  if (message.has_response()) {
    out += "response: {signature: (";
    out += base::SizeTToString(message.response().signature().length());
    out += " bytes), certificate: (";
    out += base::SizeTToString(
        message.response().client_auth_certificate().length());
    out += " bytes)}";
  }
  if (message.has_error()) {
    out += ", error: {";
    out += base::IntToString(message.error().error_type());
    out += "}";
  }
  out += "}";
  return out;
}

void CreateAuthChallengeMessage(CastMessage* message_proto) {
  CHECK(message_proto);
  DeviceAuthMessage auth_message;
  auth_message.mutable_challenge();
  std::string auth_message_string;
  auth_message.SerializeToString(&auth_message_string);

  message_proto->set_protocol_version(CastMessage_ProtocolVersion_CASTV2_1_0);
  message_proto->set_source_id(kPlatformSenderId);
  message_proto->set_destination_id(kPlatformReceiverId);
  message_proto->set_namespace_(kAuthNamespace);
  message_proto->set_payload_type(CastMessage_PayloadType_BINARY);
  message_proto->set_payload_binary(auth_message_string);
}

bool IsAuthMessage(const CastMessage& message) {
  return message.namespace_() == kAuthNamespace;
}

}  // namespace cast_channel
}  // namespace api
}  // namespace extensions