Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / chrome / renderer / extensions / cast_streaming_native_handler.cc
blobb923ca49013f623c84a0c269098345f1ed3e9063
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>
8 #include <iterator>
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h"
14 #include "chrome/common/extensions/api/cast_streaming_udp_transport.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 "extensions/renderer/script_context.h"
20 #include "net/base/host_port_pair.h"
21 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
22 #include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h"
24 using content::V8ValueConverter;
26 // Extension types.
27 using extensions::api::cast_streaming_rtp_stream::CodecSpecificParams;
28 using extensions::api::cast_streaming_rtp_stream::RtpParams;
29 using extensions::api::cast_streaming_rtp_stream::RtpPayloadParams;
30 using extensions::api::cast_streaming_udp_transport::IPEndPoint;
32 namespace extensions {
34 namespace {
35 const char kRtpStreamNotFound[] = "The RTP stream cannot be found";
36 const char kUdpTransportNotFound[] = "The UDP transport cannot be found";
37 const char kInvalidDestination[] = "Invalid destination";
38 const char kInvalidRtpParams[] = "Invalid value for RTP params";
39 const char kInvalidAesKey[] = "Invalid value for AES key";
40 const char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
41 const char kInvalidStreamArgs[] = "Invalid stream arguments";
42 const char kUnableToConvertArgs[] = "Unable to convert arguments";
43 const char kUnableToConvertParams[] = "Unable to convert params";
45 // These helper methods are used to convert between Extension API
46 // types and Cast types.
47 void ToCastCodecSpecificParams(const CodecSpecificParams& ext_params,
48 CastCodecSpecificParams* cast_params) {
49 cast_params->key = ext_params.key;
50 cast_params->value = ext_params.value;
53 void FromCastCodecSpecificParams(const CastCodecSpecificParams& cast_params,
54 CodecSpecificParams* ext_params) {
55 ext_params->key = cast_params.key;
56 ext_params->value = cast_params.value;
59 namespace {
60 bool HexDecode(const std::string& input, std::string* output) {
61 std::vector<uint8> bytes;
62 if (!base::HexStringToBytes(input, &bytes))
63 return false;
64 output->assign(reinterpret_cast<const char*>(&bytes[0]), bytes.size());
65 return true;
67 } // namespace
69 bool ToCastRtpPayloadParamsOrThrow(v8::Isolate* isolate,
70 const RtpPayloadParams& ext_params,
71 CastRtpPayloadParams* cast_params) {
72 cast_params->payload_type = ext_params.payload_type;
73 cast_params->max_latency_ms = ext_params.max_latency;
74 cast_params->min_latency_ms =
75 ext_params.min_latency ? *ext_params.min_latency : ext_params.max_latency;
76 cast_params->codec_name = ext_params.codec_name;
77 cast_params->ssrc = ext_params.ssrc;
78 cast_params->feedback_ssrc = ext_params.feedback_ssrc;
79 cast_params->clock_rate = ext_params.clock_rate ? *ext_params.clock_rate : 0;
80 cast_params->min_bitrate =
81 ext_params.min_bitrate ? *ext_params.min_bitrate : 0;
82 cast_params->max_bitrate =
83 ext_params.max_bitrate ? *ext_params.max_bitrate : 0;
84 cast_params->channels = ext_params.channels ? *ext_params.channels : 0;
85 cast_params->max_frame_rate =
86 ext_params.max_frame_rate ? *ext_params.max_frame_rate : 0.0;
87 cast_params->width = ext_params.width ? *ext_params.width : 0;
88 cast_params->height = ext_params.height ? *ext_params.height : 0;
89 if (ext_params.aes_key &&
90 !HexDecode(*ext_params.aes_key, &cast_params->aes_key)) {
91 isolate->ThrowException(v8::Exception::Error(
92 v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
93 return false;
95 if (ext_params.aes_iv_mask &&
96 !HexDecode(*ext_params.aes_iv_mask, &cast_params->aes_iv_mask)) {
97 isolate->ThrowException(v8::Exception::Error(
98 v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
99 return false;
101 for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) {
102 CastCodecSpecificParams cast_codec_params;
103 ToCastCodecSpecificParams(*ext_params.codec_specific_params[i],
104 &cast_codec_params);
105 cast_params->codec_specific_params.push_back(cast_codec_params);
107 return true;
110 void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params,
111 RtpPayloadParams* ext_params) {
112 ext_params->payload_type = cast_params.payload_type;
113 ext_params->max_latency = cast_params.max_latency_ms;
114 ext_params->min_latency.reset(new int(cast_params.min_latency_ms));
115 ext_params->codec_name = cast_params.codec_name;
116 ext_params->ssrc = cast_params.ssrc;
117 ext_params->feedback_ssrc = cast_params.feedback_ssrc;
118 if (cast_params.clock_rate)
119 ext_params->clock_rate.reset(new int(cast_params.clock_rate));
120 if (cast_params.min_bitrate)
121 ext_params->min_bitrate.reset(new int(cast_params.min_bitrate));
122 if (cast_params.max_bitrate)
123 ext_params->max_bitrate.reset(new int(cast_params.max_bitrate));
124 if (cast_params.channels)
125 ext_params->channels.reset(new int(cast_params.channels));
126 if (cast_params.max_frame_rate > 0.0)
127 ext_params->max_frame_rate.reset(new double(cast_params.max_frame_rate));
128 if (cast_params.width)
129 ext_params->width.reset(new int(cast_params.width));
130 if (cast_params.height)
131 ext_params->height.reset(new int(cast_params.height));
132 for (size_t i = 0; i < cast_params.codec_specific_params.size(); ++i) {
133 linked_ptr<CodecSpecificParams> ext_codec_params(
134 new CodecSpecificParams());
135 FromCastCodecSpecificParams(cast_params.codec_specific_params[i],
136 ext_codec_params.get());
137 ext_params->codec_specific_params.push_back(ext_codec_params);
141 void FromCastRtpParams(const CastRtpParams& cast_params,
142 RtpParams* ext_params) {
143 std::copy(cast_params.rtcp_features.begin(),
144 cast_params.rtcp_features.end(),
145 std::back_inserter(ext_params->rtcp_features));
146 FromCastRtpPayloadParams(cast_params.payload, &ext_params->payload);
149 bool ToCastRtpParamsOrThrow(v8::Isolate* isolate,
150 const RtpParams& ext_params,
151 CastRtpParams* cast_params) {
152 std::copy(ext_params.rtcp_features.begin(),
153 ext_params.rtcp_features.end(),
154 std::back_inserter(cast_params->rtcp_features));
155 if (!ToCastRtpPayloadParamsOrThrow(isolate,
156 ext_params.payload,
157 &cast_params->payload)) {
158 return false;
160 return true;
163 } // namespace
165 CastStreamingNativeHandler::CastStreamingNativeHandler(ScriptContext* context)
166 : ObjectBackedNativeHandler(context),
167 last_transport_id_(1),
168 weak_factory_(this) {
169 RouteFunction("CreateSession",
170 base::Bind(&CastStreamingNativeHandler::CreateCastSession,
171 base::Unretained(this)));
172 RouteFunction("DestroyCastRtpStream",
173 base::Bind(&CastStreamingNativeHandler::DestroyCastRtpStream,
174 base::Unretained(this)));
175 RouteFunction("GetSupportedParamsCastRtpStream",
176 base::Bind(&CastStreamingNativeHandler::GetSupportedParamsCastRtpStream,
177 base::Unretained(this)));
178 RouteFunction("StartCastRtpStream",
179 base::Bind(&CastStreamingNativeHandler::StartCastRtpStream,
180 base::Unretained(this)));
181 RouteFunction("StopCastRtpStream",
182 base::Bind(&CastStreamingNativeHandler::StopCastRtpStream,
183 base::Unretained(this)));
184 RouteFunction("DestroyCastUdpTransport",
185 base::Bind(&CastStreamingNativeHandler::DestroyCastUdpTransport,
186 base::Unretained(this)));
187 RouteFunction("SetDestinationCastUdpTransport",
188 base::Bind(&CastStreamingNativeHandler::SetDestinationCastUdpTransport,
189 base::Unretained(this)));
190 RouteFunction("SetOptionsCastUdpTransport",
191 base::Bind(&CastStreamingNativeHandler::SetOptionsCastUdpTransport,
192 base::Unretained(this)));
193 RouteFunction("ToggleLogging",
194 base::Bind(&CastStreamingNativeHandler::ToggleLogging,
195 base::Unretained(this)));
196 RouteFunction("GetRawEvents",
197 base::Bind(&CastStreamingNativeHandler::GetRawEvents,
198 base::Unretained(this)));
199 RouteFunction("GetStats",
200 base::Bind(&CastStreamingNativeHandler::GetStats,
201 base::Unretained(this)));
204 CastStreamingNativeHandler::~CastStreamingNativeHandler() {
207 void CastStreamingNativeHandler::CreateCastSession(
208 const v8::FunctionCallbackInfo<v8::Value>& args) {
209 CHECK_EQ(3, args.Length());
210 CHECK(args[2]->IsFunction());
212 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
213 if ((args[0]->IsNull() || args[0]->IsUndefined()) &&
214 (args[1]->IsNull() || args[1]->IsUndefined())) {
215 isolate->ThrowException(v8::Exception::Error(
216 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
217 return;
220 scoped_refptr<CastSession> session(new CastSession());
221 scoped_ptr<CastRtpStream> stream1, stream2;
222 if (!args[0]->IsNull() && !args[0]->IsUndefined()) {
223 CHECK(args[0]->IsObject());
224 blink::WebDOMMediaStreamTrack track =
225 blink::WebDOMMediaStreamTrack::fromV8Value(args[0]);
226 if (track.isNull()) {
227 isolate->ThrowException(v8::Exception::Error(
228 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
229 return;
231 stream1.reset(new CastRtpStream(track.component(), session));
233 if (!args[1]->IsNull() && !args[1]->IsUndefined()) {
234 CHECK(args[1]->IsObject());
235 blink::WebDOMMediaStreamTrack track =
236 blink::WebDOMMediaStreamTrack::fromV8Value(args[1]);
237 if (track.isNull()) {
238 isolate->ThrowException(v8::Exception::Error(
239 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
240 return;
242 stream2.reset(new CastRtpStream(track.component(), session));
244 scoped_ptr<CastUdpTransport> udp_transport(
245 new CastUdpTransport(session));
247 // TODO(imcheng): Use a weak reference to ensure we don't call into an
248 // invalid context when the callback is invoked.
249 create_callback_.reset(args[2].As<v8::Function>());
251 base::MessageLoop::current()->PostTask(
252 FROM_HERE,
253 base::Bind(
254 &CastStreamingNativeHandler::CallCreateCallback,
255 weak_factory_.GetWeakPtr(),
256 base::Passed(&stream1),
257 base::Passed(&stream2),
258 base::Passed(&udp_transport)));
261 void CastStreamingNativeHandler::CallCreateCallback(
262 scoped_ptr<CastRtpStream> stream1,
263 scoped_ptr<CastRtpStream> stream2,
264 scoped_ptr<CastUdpTransport> udp_transport) {
265 v8::Isolate* isolate = context()->isolate();
266 v8::HandleScope handle_scope(isolate);
267 v8::Context::Scope context_scope(context()->v8_context());
269 v8::Handle<v8::Value> callback_args[3];
270 callback_args[0] = v8::Null(isolate);
271 callback_args[1] = v8::Null(isolate);
273 if (stream1) {
274 const int stream1_id = last_transport_id_++;
275 callback_args[0] = v8::Integer::New(isolate, stream1_id);
276 rtp_stream_map_[stream1_id] =
277 linked_ptr<CastRtpStream>(stream1.release());
279 if (stream2) {
280 const int stream2_id = last_transport_id_++;
281 callback_args[1] = v8::Integer::New(isolate, stream2_id);
282 rtp_stream_map_[stream2_id] =
283 linked_ptr<CastRtpStream>(stream2.release());
285 const int udp_id = last_transport_id_++;
286 udp_transport_map_[udp_id] =
287 linked_ptr<CastUdpTransport>(udp_transport.release());
288 callback_args[2] = v8::Integer::New(isolate, udp_id);
289 context()->CallFunction(create_callback_.NewHandle(isolate),
290 3, callback_args);
291 create_callback_.reset();
294 void CastStreamingNativeHandler::CallStartCallback(int stream_id) {
295 v8::Isolate* isolate = context()->isolate();
296 v8::HandleScope handle_scope(isolate);
297 v8::Context::Scope context_scope(context()->v8_context());
298 v8::Handle<v8::Array> event_args = v8::Array::New(isolate, 1);
299 event_args->Set(0, v8::Integer::New(isolate, stream_id));
300 context()->DispatchEvent("cast.streaming.rtpStream.onStarted", event_args);
303 void CastStreamingNativeHandler::CallStopCallback(int stream_id) {
304 v8::Isolate* isolate = context()->isolate();
305 v8::HandleScope handle_scope(isolate);
306 v8::Context::Scope context_scope(context()->v8_context());
307 v8::Handle<v8::Array> event_args = v8::Array::New(isolate, 1);
308 event_args->Set(0, v8::Integer::New(isolate, stream_id));
309 context()->DispatchEvent("cast.streaming.rtpStream.onStopped", event_args);
312 void CastStreamingNativeHandler::CallErrorCallback(int stream_id,
313 const std::string& message) {
314 v8::Isolate* isolate = context()->isolate();
315 v8::HandleScope handle_scope(isolate);
316 v8::Context::Scope context_scope(context()->v8_context());
317 v8::Handle<v8::Array> event_args = v8::Array::New(isolate, 2);
318 event_args->Set(0, v8::Integer::New(isolate, stream_id));
319 event_args->Set(
321 v8::String::NewFromUtf8(
322 isolate, message.data(), v8::String::kNormalString, message.size()));
323 context()->DispatchEvent("cast.streaming.rtpStream.onError", event_args);
326 void CastStreamingNativeHandler::DestroyCastRtpStream(
327 const v8::FunctionCallbackInfo<v8::Value>& args) {
328 CHECK_EQ(1, args.Length());
329 CHECK(args[0]->IsInt32());
331 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
332 if (!GetRtpStreamOrThrow(transport_id))
333 return;
334 rtp_stream_map_.erase(transport_id);
337 void CastStreamingNativeHandler::GetSupportedParamsCastRtpStream(
338 const v8::FunctionCallbackInfo<v8::Value>& args) {
339 CHECK_EQ(1, args.Length());
340 CHECK(args[0]->IsInt32());
342 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
343 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
344 if (!transport)
345 return;
347 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
348 std::vector<CastRtpParams> cast_params = transport->GetSupportedParams();
349 v8::Handle<v8::Array> result =
350 v8::Array::New(args.GetIsolate(),
351 static_cast<int>(cast_params.size()));
352 for (size_t i = 0; i < cast_params.size(); ++i) {
353 RtpParams params;
354 FromCastRtpParams(cast_params[i], &params);
355 scoped_ptr<base::DictionaryValue> params_value = params.ToValue();
356 result->Set(
357 static_cast<int>(i),
358 converter->ToV8Value(params_value.get(), context()->v8_context()));
360 args.GetReturnValue().Set(result);
363 void CastStreamingNativeHandler::StartCastRtpStream(
364 const v8::FunctionCallbackInfo<v8::Value>& args) {
365 CHECK_EQ(2, args.Length());
366 CHECK(args[0]->IsInt32());
367 CHECK(args[1]->IsObject());
369 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
370 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
371 if (!transport)
372 return;
374 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
375 scoped_ptr<base::Value> params_value(
376 converter->FromV8Value(args[1], context()->v8_context()));
377 if (!params_value) {
378 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
379 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertParams)));
380 return;
382 scoped_ptr<RtpParams> params = RtpParams::FromValue(*params_value);
383 if (!params) {
384 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
385 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidRtpParams)));
386 return;
389 CastRtpParams cast_params;
390 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
391 if (!ToCastRtpParamsOrThrow(isolate, *params, &cast_params))
392 return;
394 base::Closure start_callback =
395 base::Bind(&CastStreamingNativeHandler::CallStartCallback,
396 weak_factory_.GetWeakPtr(),
397 transport_id);
398 base::Closure stop_callback =
399 base::Bind(&CastStreamingNativeHandler::CallStopCallback,
400 weak_factory_.GetWeakPtr(),
401 transport_id);
402 CastRtpStream::ErrorCallback error_callback =
403 base::Bind(&CastStreamingNativeHandler::CallErrorCallback,
404 weak_factory_.GetWeakPtr(),
405 transport_id);
406 transport->Start(cast_params, start_callback, stop_callback, error_callback);
409 void CastStreamingNativeHandler::StopCastRtpStream(
410 const v8::FunctionCallbackInfo<v8::Value>& args) {
411 CHECK_EQ(1, args.Length());
412 CHECK(args[0]->IsInt32());
414 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
415 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
416 if (!transport)
417 return;
418 transport->Stop();
421 void CastStreamingNativeHandler::DestroyCastUdpTransport(
422 const v8::FunctionCallbackInfo<v8::Value>& args) {
423 CHECK_EQ(1, args.Length());
424 CHECK(args[0]->IsInt32());
426 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
427 if (!GetUdpTransportOrThrow(transport_id))
428 return;
429 udp_transport_map_.erase(transport_id);
432 void CastStreamingNativeHandler::SetDestinationCastUdpTransport(
433 const v8::FunctionCallbackInfo<v8::Value>& args) {
434 CHECK_EQ(2, args.Length());
435 CHECK(args[0]->IsInt32());
436 CHECK(args[1]->IsObject());
438 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
439 CastUdpTransport* transport = GetUdpTransportOrThrow(transport_id);
440 if (!transport)
441 return;
443 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
444 scoped_ptr<base::Value> destination_value(
445 converter->FromV8Value(args[1], context()->v8_context()));
446 if (!destination_value) {
447 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
448 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
449 return;
451 scoped_ptr<IPEndPoint> destination =
452 IPEndPoint::FromValue(*destination_value);
453 if (!destination) {
454 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
455 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
456 return;
458 net::IPAddressNumber ip;
459 if (!net::ParseIPLiteralToNumber(destination->address, &ip)) {
460 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
461 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
462 return;
464 transport->SetDestination(net::IPEndPoint(ip, destination->port));
467 void CastStreamingNativeHandler::SetOptionsCastUdpTransport(
468 const v8::FunctionCallbackInfo<v8::Value>& args) {
469 CHECK_EQ(2, args.Length());
470 CHECK(args[0]->IsInt32());
471 CHECK(args[1]->IsObject());
473 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
474 CastUdpTransport* transport = GetUdpTransportOrThrow(transport_id);
475 if (!transport)
476 return;
478 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
479 base::Value* options_value =
480 converter->FromV8Value(args[1], context()->v8_context());
481 base::DictionaryValue* options;
482 if (!options_value || !options_value->GetAsDictionary(&options)) {
483 delete options_value;
484 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
485 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
486 return;
488 transport->SetOptions(make_scoped_ptr(options));
491 void CastStreamingNativeHandler::ToggleLogging(
492 const v8::FunctionCallbackInfo<v8::Value>& args) {
493 CHECK_EQ(2, args.Length());
494 CHECK(args[0]->IsInt32());
495 CHECK(args[1]->IsBoolean());
497 const int stream_id = args[0]->ToInt32(args.GetIsolate())->Value();
498 CastRtpStream* stream = GetRtpStreamOrThrow(stream_id);
499 if (!stream)
500 return;
502 const bool enable = args[1]->ToBoolean(args.GetIsolate())->Value();
503 stream->ToggleLogging(enable);
506 void CastStreamingNativeHandler::GetRawEvents(
507 const v8::FunctionCallbackInfo<v8::Value>& args) {
508 CHECK_EQ(3, args.Length());
509 CHECK(args[0]->IsInt32());
510 CHECK(args[1]->IsNull() || args[1]->IsString());
511 CHECK(args[2]->IsFunction());
513 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
514 // TODO(imcheng): Use a weak reference to ensure we don't call into an
515 // invalid context when the callback is invoked.
516 linked_ptr<ScopedPersistent<v8::Function> > callback(
517 new ScopedPersistent<v8::Function>(args[2].As<v8::Function>()));
518 std::string extra_data;
519 if (!args[1]->IsNull()) {
520 extra_data = *v8::String::Utf8Value(args[1]);
523 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
524 if (!transport)
525 return;
527 get_raw_events_callbacks_.insert(std::make_pair(transport_id, callback));
529 transport->GetRawEvents(
530 base::Bind(&CastStreamingNativeHandler::CallGetRawEventsCallback,
531 weak_factory_.GetWeakPtr(),
532 transport_id),
533 extra_data);
536 void CastStreamingNativeHandler::GetStats(
537 const v8::FunctionCallbackInfo<v8::Value>& args) {
538 CHECK_EQ(2, args.Length());
539 CHECK(args[0]->IsInt32());
540 CHECK(args[1]->IsFunction());
541 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
542 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
543 if (!transport)
544 return;
546 // TODO(imcheng): Use a weak reference to ensure we don't call into an
547 // invalid context when the callback is invoked.
548 linked_ptr<ScopedPersistent<v8::Function> > callback(
549 new ScopedPersistent<v8::Function>(args[1].As<v8::Function>()));
550 get_stats_callbacks_.insert(std::make_pair(transport_id, callback));
552 transport->GetStats(
553 base::Bind(&CastStreamingNativeHandler::CallGetStatsCallback,
554 weak_factory_.GetWeakPtr(),
555 transport_id));
558 void CastStreamingNativeHandler::CallGetRawEventsCallback(
559 int transport_id,
560 scoped_ptr<base::BinaryValue> raw_events) {
561 v8::Isolate* isolate = context()->isolate();
562 v8::HandleScope handle_scope(isolate);
563 v8::Context::Scope context_scope(context()->v8_context());
565 RtpStreamCallbackMap::iterator it =
566 get_raw_events_callbacks_.find(transport_id);
567 if (it == get_raw_events_callbacks_.end())
568 return;
569 v8::Handle<v8::Value> callback_args[1];
570 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
571 callback_args[0] =
572 converter->ToV8Value(raw_events.get(), context()->v8_context());
573 context()->CallFunction(it->second->NewHandle(isolate), 1, callback_args);
574 get_raw_events_callbacks_.erase(it);
577 void CastStreamingNativeHandler::CallGetStatsCallback(
578 int transport_id,
579 scoped_ptr<base::DictionaryValue> stats) {
580 v8::Isolate* isolate = context()->isolate();
581 v8::HandleScope handle_scope(isolate);
582 v8::Context::Scope context_scope(context()->v8_context());
584 RtpStreamCallbackMap::iterator it = get_stats_callbacks_.find(transport_id);
585 if (it == get_stats_callbacks_.end())
586 return;
588 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
589 v8::Handle<v8::Value> callback_args[1];
590 callback_args[0] = converter->ToV8Value(stats.get(), context()->v8_context());
591 context()->CallFunction(it->second->NewHandle(isolate), 1, callback_args);
592 get_stats_callbacks_.erase(it);
595 CastRtpStream* CastStreamingNativeHandler::GetRtpStreamOrThrow(
596 int transport_id) const {
597 RtpStreamMap::const_iterator iter = rtp_stream_map_.find(
598 transport_id);
599 if (iter != rtp_stream_map_.end())
600 return iter->second.get();
601 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
602 isolate->ThrowException(v8::Exception::RangeError(v8::String::NewFromUtf8(
603 isolate, kRtpStreamNotFound)));
604 return NULL;
607 CastUdpTransport* CastStreamingNativeHandler::GetUdpTransportOrThrow(
608 int transport_id) const {
609 UdpTransportMap::const_iterator iter = udp_transport_map_.find(
610 transport_id);
611 if (iter != udp_transport_map_.end())
612 return iter->second.get();
613 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
614 isolate->ThrowException(v8::Exception::RangeError(
615 v8::String::NewFromUtf8(isolate, kUdpTransportNotFound)));
616 return NULL;
619 } // namespace extensions