Added documentation to web_view.js/web_view_experimental.js regarding the webview...
[chromium-blink-merge.git] / chrome / renderer / extensions / cast_streaming_native_handler.cc
blob8170f63adfce70409cb424022f9b6e291ec6c0a9
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.
5 #include "chrome/renderer/extensions/cast_streaming_native_handler.h"
7 #include <functional>
9 #include "base/base64.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h"
13 #include "chrome/common/extensions/api/cast_streaming_udp_transport.h"
14 #include "chrome/renderer/extensions/chrome_v8_context.h"
15 #include "chrome/renderer/media/cast_rtp_stream.h"
16 #include "chrome/renderer/media/cast_session.h"
17 #include "chrome/renderer/media/cast_udp_transport.h"
18 #include "content/public/renderer/v8_value_converter.h"
19 #include "net/base/host_port_pair.h"
20 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
21 #include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h"
23 using content::V8ValueConverter;
25 // Extension types.
26 using extensions::api::cast_streaming_rtp_stream::CodecSpecificParams;
27 using extensions::api::cast_streaming_rtp_stream::RtpParams;
28 using extensions::api::cast_streaming_rtp_stream::RtpPayloadParams;
29 using extensions::api::cast_streaming_udp_transport::IPEndPoint;
31 namespace extensions {
33 namespace {
34 const char kRtpStreamNotFound[] = "The RTP stream cannot be found";
35 const char kUdpTransportNotFound[] = "The UDP transport cannot be found";
36 const char kInvalidDestination[] = "Invalid destination";
37 const char kInvalidRtpParams[] = "Invalid value for RTP params";
38 const char kInvalidAesKey[] = "Invalid value for AES key";
39 const char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
40 const char kUnableToConvertArgs[] = "Unable to convert arguments";
41 const char kUnableToConvertParams[] = "Unable to convert params";
43 // These helper methods are used to convert between Extension API
44 // types and Cast types.
45 void ToCastCodecSpecificParams(const CodecSpecificParams& ext_params,
46 CastCodecSpecificParams* cast_params) {
47 cast_params->key = ext_params.key;
48 cast_params->value = ext_params.value;
51 void FromCastCodecSpecificParams(const CastCodecSpecificParams& cast_params,
52 CodecSpecificParams* ext_params) {
53 ext_params->key = cast_params.key;
54 ext_params->value = cast_params.value;
57 bool ToCastRtpPayloadParamsOrThrow(v8::Isolate* isolate,
58 const RtpPayloadParams& ext_params,
59 CastRtpPayloadParams* cast_params) {
60 cast_params->payload_type = ext_params.payload_type;
61 cast_params->codec_name = ext_params.codec_name;
62 cast_params->ssrc = ext_params.ssrc ? *ext_params.ssrc : 0;
63 cast_params->feedback_ssrc =
64 ext_params.feedback_ssrc ? *ext_params.feedback_ssrc : 0;
65 cast_params->clock_rate = ext_params.clock_rate ? *ext_params.clock_rate : 0;
66 cast_params->min_bitrate =
67 ext_params.min_bitrate ? *ext_params.min_bitrate : 0;
68 cast_params->max_bitrate =
69 ext_params.max_bitrate ? *ext_params.max_bitrate : 0;
70 cast_params->channels = ext_params.channels ? *ext_params.channels : 0;
71 cast_params->width = ext_params.width ? *ext_params.width : 0;
72 cast_params->height = ext_params.height ? *ext_params.height : 0;
73 if (ext_params.aes_key &&
74 !base::Base64Decode(*ext_params.aes_key, &cast_params->aes_key)) {
75 isolate->ThrowException(v8::Exception::Error(
76 v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
77 return false;
79 if (ext_params.aes_iv_mask &&
80 !base::Base64Decode(*ext_params.aes_iv_mask,
81 &cast_params->aes_iv_mask)) {
82 isolate->ThrowException(v8::Exception::Error(
83 v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
84 return false;
86 for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) {
87 CastCodecSpecificParams cast_codec_params;
88 ToCastCodecSpecificParams(*ext_params.codec_specific_params[i],
89 &cast_codec_params);
90 cast_params->codec_specific_params.push_back(cast_codec_params);
92 return true;
95 void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params,
96 RtpPayloadParams* ext_params) {
97 ext_params->payload_type = cast_params.payload_type;
98 ext_params->codec_name = cast_params.codec_name;
99 if (cast_params.ssrc)
100 ext_params->ssrc.reset(new int(cast_params.ssrc));
101 if (cast_params.feedback_ssrc)
102 ext_params->feedback_ssrc.reset(new int(cast_params.feedback_ssrc));
103 if (cast_params.clock_rate)
104 ext_params->clock_rate.reset(new int(cast_params.clock_rate));
105 if (cast_params.min_bitrate)
106 ext_params->min_bitrate.reset(new int(cast_params.min_bitrate));
107 if (cast_params.max_bitrate)
108 ext_params->max_bitrate.reset(new int(cast_params.max_bitrate));
109 if (cast_params.channels)
110 ext_params->channels.reset(new int(cast_params.channels));
111 if (cast_params.width)
112 ext_params->width.reset(new int(cast_params.width));
113 if (cast_params.height)
114 ext_params->height.reset(new int(cast_params.height));
115 for (size_t i = 0; i < cast_params.codec_specific_params.size(); ++i) {
116 linked_ptr<CodecSpecificParams> ext_codec_params(
117 new CodecSpecificParams());
118 FromCastCodecSpecificParams(cast_params.codec_specific_params[i],
119 ext_codec_params.get());
120 ext_params->codec_specific_params.push_back(ext_codec_params);
124 void FromCastRtpParams(const CastRtpParams& cast_params,
125 RtpParams* ext_params) {
126 std::copy(cast_params.rtcp_features.begin(), cast_params.rtcp_features.end(),
127 ext_params->rtcp_features.begin());
128 FromCastRtpPayloadParams(cast_params.payload, &ext_params->payload);
131 bool ToCastRtpParamsOrThrow(v8::Isolate* isolate,
132 const RtpParams& ext_params,
133 CastRtpParams* cast_params) {
134 std::copy(ext_params.rtcp_features.begin(), ext_params.rtcp_features.end(),
135 cast_params->rtcp_features.begin());
136 if (!ToCastRtpPayloadParamsOrThrow(isolate,
137 ext_params.payload,
138 &cast_params->payload)) {
139 return false;
141 return true;
144 } // namespace
146 CastStreamingNativeHandler::CastStreamingNativeHandler(ChromeV8Context* context)
147 : ObjectBackedNativeHandler(context),
148 last_transport_id_(0),
149 weak_factory_(this) {
150 RouteFunction("CreateSession",
151 base::Bind(&CastStreamingNativeHandler::CreateCastSession,
152 base::Unretained(this)));
153 RouteFunction("DestroyCastRtpStream",
154 base::Bind(&CastStreamingNativeHandler::DestroyCastRtpStream,
155 base::Unretained(this)));
156 RouteFunction("GetSupportedParamsCastRtpStream",
157 base::Bind(&CastStreamingNativeHandler::GetSupportedParamsCastRtpStream,
158 base::Unretained(this)));
159 RouteFunction("StartCastRtpStream",
160 base::Bind(&CastStreamingNativeHandler::StartCastRtpStream,
161 base::Unretained(this)));
162 RouteFunction("StopCastRtpStream",
163 base::Bind(&CastStreamingNativeHandler::StopCastRtpStream,
164 base::Unretained(this)));
165 RouteFunction("DestroyCastUdpTransport",
166 base::Bind(&CastStreamingNativeHandler::DestroyCastUdpTransport,
167 base::Unretained(this)));
168 RouteFunction("SetDestinationCastUdpTransport",
169 base::Bind(&CastStreamingNativeHandler::SetDestinationCastUdpTransport,
170 base::Unretained(this)));
173 CastStreamingNativeHandler::~CastStreamingNativeHandler() {
176 void CastStreamingNativeHandler::CreateCastSession(
177 const v8::FunctionCallbackInfo<v8::Value>& args) {
178 CHECK_EQ(3, args.Length());
179 CHECK(args[0]->IsObject());
180 CHECK(args[1]->IsObject());
181 CHECK(args[2]->IsFunction());
183 blink::WebDOMMediaStreamTrack track1 =
184 blink::WebDOMMediaStreamTrack::fromV8Value(args[0]);
185 if (track1.isNull())
186 return;
187 blink::WebDOMMediaStreamTrack track2 =
188 blink::WebDOMMediaStreamTrack::fromV8Value(args[1]);
189 if (track2.isNull())
190 return;
192 scoped_refptr<CastSession> session(new CastSession());
193 scoped_ptr<CastRtpStream> stream1(
194 new CastRtpStream(track1.component(), session));
195 scoped_ptr<CastRtpStream> stream2(
196 new CastRtpStream(track2.component(), session));
197 scoped_ptr<CastUdpTransport> udp_transport(
198 new CastUdpTransport(session));
200 create_callback_.reset(args[2].As<v8::Function>());
202 base::MessageLoop::current()->PostTask(
203 FROM_HERE,
204 base::Bind(
205 &CastStreamingNativeHandler::CallCreateCallback,
206 weak_factory_.GetWeakPtr(),
207 base::Passed(&stream1),
208 base::Passed(&stream2),
209 base::Passed(&udp_transport)));
212 void CastStreamingNativeHandler::CallCreateCallback(
213 scoped_ptr<CastRtpStream> stream1,
214 scoped_ptr<CastRtpStream> stream2,
215 scoped_ptr<CastUdpTransport> udp_transport) {
216 v8::Isolate* isolate = context()->isolate();
217 v8::HandleScope handle_scope(isolate);
218 v8::Context::Scope context_scope(context()->v8_context());
220 const int stream1_id = last_transport_id_++;
221 rtp_stream_map_[stream1_id] =
222 linked_ptr<CastRtpStream>(stream1.release());
223 const int stream2_id = last_transport_id_++;
224 rtp_stream_map_[stream2_id] =
225 linked_ptr<CastRtpStream>(stream2.release());
226 const int udp_id = last_transport_id_++;
227 udp_transport_map_[udp_id] =
228 linked_ptr<CastUdpTransport>(udp_transport.release());
230 v8::Handle<v8::Value> callback_args[3];
231 callback_args[0] = v8::Integer::New(isolate, stream1_id);
232 callback_args[1] = v8::Integer::New(isolate, stream2_id);
233 callback_args[2] = v8::Integer::New(isolate, udp_id);
234 context()->CallFunction(create_callback_.NewHandle(isolate),
235 3, callback_args);
236 create_callback_.reset();
239 void CastStreamingNativeHandler::DestroyCastRtpStream(
240 const v8::FunctionCallbackInfo<v8::Value>& args) {
241 CHECK_EQ(1, args.Length());
242 CHECK(args[0]->IsInt32());
244 const int transport_id = args[0]->ToInt32()->Value();
245 if (!GetRtpStreamOrThrow(transport_id))
246 return;
247 rtp_stream_map_.erase(transport_id);
250 void CastStreamingNativeHandler::GetSupportedParamsCastRtpStream(
251 const v8::FunctionCallbackInfo<v8::Value>& args) {
252 CHECK_EQ(1, args.Length());
253 CHECK(args[0]->IsInt32());
255 const int transport_id = args[0]->ToInt32()->Value();
256 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
257 if (!transport)
258 return;
260 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
261 std::vector<CastRtpParams> cast_params = transport->GetSupportedParams();
262 v8::Handle<v8::Array> result =
263 v8::Array::New(args.GetIsolate(),
264 static_cast<int>(cast_params.size()));
265 for (size_t i = 0; i < cast_params.size(); ++i) {
266 RtpParams params;
267 FromCastRtpParams(cast_params[i], &params);
268 scoped_ptr<base::DictionaryValue> params_value = params.ToValue();
269 result->Set(
270 static_cast<int>(i),
271 converter->ToV8Value(params_value.get(), context()->v8_context()));
273 args.GetReturnValue().Set(result);
276 void CastStreamingNativeHandler::StartCastRtpStream(
277 const v8::FunctionCallbackInfo<v8::Value>& args) {
278 CHECK_EQ(2, args.Length());
279 CHECK(args[0]->IsInt32());
280 CHECK(args[1]->IsObject());
282 const int transport_id = args[0]->ToInt32()->Value();
283 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
284 if (!transport)
285 return;
287 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
288 scoped_ptr<base::Value> params_value(
289 converter->FromV8Value(args[1], context()->v8_context()));
290 if (!params_value) {
291 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
292 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertParams)));
293 return;
295 scoped_ptr<RtpParams> params = RtpParams::FromValue(*params_value);
296 if (!params) {
297 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
298 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidRtpParams)));
299 return;
302 CastRtpParams cast_params;
303 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
304 if (!ToCastRtpParamsOrThrow(isolate, *params, &cast_params))
305 return;
306 transport->Start(cast_params);
309 void CastStreamingNativeHandler::StopCastRtpStream(
310 const v8::FunctionCallbackInfo<v8::Value>& args) {
311 CHECK_EQ(1, args.Length());
312 CHECK(args[0]->IsInt32());
314 const int transport_id = args[0]->ToInt32()->Value();
315 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
316 if (!transport)
317 return;
318 transport->Stop();
321 void CastStreamingNativeHandler::DestroyCastUdpTransport(
322 const v8::FunctionCallbackInfo<v8::Value>& args) {
323 CHECK_EQ(1, args.Length());
324 CHECK(args[0]->IsInt32());
326 const int transport_id = args[0]->ToInt32()->Value();
327 if (!GetUdpTransportOrThrow(transport_id))
328 return;
329 udp_transport_map_.erase(transport_id);
332 void CastStreamingNativeHandler::SetDestinationCastUdpTransport(
333 const v8::FunctionCallbackInfo<v8::Value>& args) {
334 CHECK_EQ(2, args.Length());
335 CHECK(args[0]->IsInt32());
336 CHECK(args[1]->IsObject());
338 const int transport_id = args[0]->ToInt32()->Value();
339 CastUdpTransport* transport = GetUdpTransportOrThrow(transport_id);
340 if (!transport)
341 return;
343 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
344 scoped_ptr<base::Value> destination_value(
345 converter->FromV8Value(args[1], context()->v8_context()));
346 if (!destination_value) {
347 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
348 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
349 return;
351 scoped_ptr<IPEndPoint> destination =
352 IPEndPoint::FromValue(*destination_value);
353 if (!destination) {
354 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
355 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
356 return;
358 net::IPAddressNumber ip;
359 if (!net::ParseIPLiteralToNumber(destination->address, &ip)) {
360 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
361 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
362 return;
364 transport->SetDestination(net::IPEndPoint(ip, destination->port));
367 CastRtpStream* CastStreamingNativeHandler::GetRtpStreamOrThrow(
368 int transport_id) const {
369 RtpStreamMap::const_iterator iter = rtp_stream_map_.find(
370 transport_id);
371 if (iter != rtp_stream_map_.end())
372 return iter->second.get();
373 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
374 isolate->ThrowException(v8::Exception::RangeError(v8::String::NewFromUtf8(
375 isolate, kRtpStreamNotFound)));
376 return NULL;
379 CastUdpTransport* CastStreamingNativeHandler::GetUdpTransportOrThrow(
380 int transport_id) const {
381 UdpTransportMap::const_iterator iter = udp_transport_map_.find(
382 transport_id);
383 if (iter != udp_transport_map_.end())
384 return iter->second.get();
385 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
386 isolate->ThrowException(v8::Exception::RangeError(
387 v8::String::NewFromUtf8(isolate, kUdpTransportNotFound)));
388 return NULL;
391 } // namespace extensions