Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / chrome / renderer / extensions / cast_streaming_native_handler.cc
blob9b50ae1db578a73b63ff6c0d5c2392ba93c4966c
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->codec_name = ext_params.codec_name;
75 cast_params->ssrc = ext_params.ssrc;
76 cast_params->feedback_ssrc = ext_params.feedback_ssrc;
77 cast_params->clock_rate = ext_params.clock_rate ? *ext_params.clock_rate : 0;
78 cast_params->min_bitrate =
79 ext_params.min_bitrate ? *ext_params.min_bitrate : 0;
80 cast_params->max_bitrate =
81 ext_params.max_bitrate ? *ext_params.max_bitrate : 0;
82 cast_params->channels = ext_params.channels ? *ext_params.channels : 0;
83 cast_params->max_frame_rate =
84 ext_params.max_frame_rate ? *ext_params.max_frame_rate : 0.0;
85 cast_params->width = ext_params.width ? *ext_params.width : 0;
86 cast_params->height = ext_params.height ? *ext_params.height : 0;
87 if (ext_params.aes_key &&
88 !HexDecode(*ext_params.aes_key, &cast_params->aes_key)) {
89 isolate->ThrowException(v8::Exception::Error(
90 v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
91 return false;
93 if (ext_params.aes_iv_mask &&
94 !HexDecode(*ext_params.aes_iv_mask, &cast_params->aes_iv_mask)) {
95 isolate->ThrowException(v8::Exception::Error(
96 v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
97 return false;
99 for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) {
100 CastCodecSpecificParams cast_codec_params;
101 ToCastCodecSpecificParams(*ext_params.codec_specific_params[i],
102 &cast_codec_params);
103 cast_params->codec_specific_params.push_back(cast_codec_params);
105 return true;
108 void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params,
109 RtpPayloadParams* ext_params) {
110 ext_params->payload_type = cast_params.payload_type;
111 ext_params->max_latency = cast_params.max_latency_ms;
112 ext_params->codec_name = cast_params.codec_name;
113 ext_params->ssrc = cast_params.ssrc;
114 ext_params->feedback_ssrc = cast_params.feedback_ssrc;
115 if (cast_params.clock_rate)
116 ext_params->clock_rate.reset(new int(cast_params.clock_rate));
117 if (cast_params.min_bitrate)
118 ext_params->min_bitrate.reset(new int(cast_params.min_bitrate));
119 if (cast_params.max_bitrate)
120 ext_params->max_bitrate.reset(new int(cast_params.max_bitrate));
121 if (cast_params.channels)
122 ext_params->channels.reset(new int(cast_params.channels));
123 if (cast_params.max_frame_rate > 0.0)
124 ext_params->max_frame_rate.reset(new double(cast_params.max_frame_rate));
125 if (cast_params.width)
126 ext_params->width.reset(new int(cast_params.width));
127 if (cast_params.height)
128 ext_params->height.reset(new int(cast_params.height));
129 for (size_t i = 0; i < cast_params.codec_specific_params.size(); ++i) {
130 linked_ptr<CodecSpecificParams> ext_codec_params(
131 new CodecSpecificParams());
132 FromCastCodecSpecificParams(cast_params.codec_specific_params[i],
133 ext_codec_params.get());
134 ext_params->codec_specific_params.push_back(ext_codec_params);
138 void FromCastRtpParams(const CastRtpParams& cast_params,
139 RtpParams* ext_params) {
140 std::copy(cast_params.rtcp_features.begin(),
141 cast_params.rtcp_features.end(),
142 std::back_inserter(ext_params->rtcp_features));
143 FromCastRtpPayloadParams(cast_params.payload, &ext_params->payload);
146 bool ToCastRtpParamsOrThrow(v8::Isolate* isolate,
147 const RtpParams& ext_params,
148 CastRtpParams* cast_params) {
149 std::copy(ext_params.rtcp_features.begin(),
150 ext_params.rtcp_features.end(),
151 std::back_inserter(cast_params->rtcp_features));
152 if (!ToCastRtpPayloadParamsOrThrow(isolate,
153 ext_params.payload,
154 &cast_params->payload)) {
155 return false;
157 return true;
160 } // namespace
162 CastStreamingNativeHandler::CastStreamingNativeHandler(ScriptContext* context)
163 : ObjectBackedNativeHandler(context),
164 last_transport_id_(1),
165 weak_factory_(this) {
166 RouteFunction("CreateSession",
167 base::Bind(&CastStreamingNativeHandler::CreateCastSession,
168 base::Unretained(this)));
169 RouteFunction("DestroyCastRtpStream",
170 base::Bind(&CastStreamingNativeHandler::DestroyCastRtpStream,
171 base::Unretained(this)));
172 RouteFunction("GetSupportedParamsCastRtpStream",
173 base::Bind(&CastStreamingNativeHandler::GetSupportedParamsCastRtpStream,
174 base::Unretained(this)));
175 RouteFunction("StartCastRtpStream",
176 base::Bind(&CastStreamingNativeHandler::StartCastRtpStream,
177 base::Unretained(this)));
178 RouteFunction("StopCastRtpStream",
179 base::Bind(&CastStreamingNativeHandler::StopCastRtpStream,
180 base::Unretained(this)));
181 RouteFunction("DestroyCastUdpTransport",
182 base::Bind(&CastStreamingNativeHandler::DestroyCastUdpTransport,
183 base::Unretained(this)));
184 RouteFunction("SetDestinationCastUdpTransport",
185 base::Bind(&CastStreamingNativeHandler::SetDestinationCastUdpTransport,
186 base::Unretained(this)));
187 RouteFunction("ToggleLogging",
188 base::Bind(&CastStreamingNativeHandler::ToggleLogging,
189 base::Unretained(this)));
190 RouteFunction("GetRawEvents",
191 base::Bind(&CastStreamingNativeHandler::GetRawEvents,
192 base::Unretained(this)));
193 RouteFunction("GetStats",
194 base::Bind(&CastStreamingNativeHandler::GetStats,
195 base::Unretained(this)));
198 CastStreamingNativeHandler::~CastStreamingNativeHandler() {
201 void CastStreamingNativeHandler::CreateCastSession(
202 const v8::FunctionCallbackInfo<v8::Value>& args) {
203 CHECK_EQ(3, args.Length());
204 CHECK(args[2]->IsFunction());
206 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
207 if ((args[0]->IsNull() || args[0]->IsUndefined()) &&
208 (args[1]->IsNull() || args[1]->IsUndefined())) {
209 isolate->ThrowException(v8::Exception::Error(
210 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
211 return;
214 scoped_refptr<CastSession> session(new CastSession());
215 scoped_ptr<CastRtpStream> stream1, stream2;
216 if (!args[0]->IsNull() && !args[0]->IsUndefined()) {
217 CHECK(args[0]->IsObject());
218 blink::WebDOMMediaStreamTrack track =
219 blink::WebDOMMediaStreamTrack::fromV8Value(args[0]);
220 if (track.isNull()) {
221 isolate->ThrowException(v8::Exception::Error(
222 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
223 return;
225 stream1.reset(new CastRtpStream(track.component(), session));
227 if (!args[1]->IsNull() && !args[1]->IsUndefined()) {
228 CHECK(args[1]->IsObject());
229 blink::WebDOMMediaStreamTrack track =
230 blink::WebDOMMediaStreamTrack::fromV8Value(args[1]);
231 if (track.isNull()) {
232 isolate->ThrowException(v8::Exception::Error(
233 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
234 return;
236 stream2.reset(new CastRtpStream(track.component(), session));
238 scoped_ptr<CastUdpTransport> udp_transport(
239 new CastUdpTransport(session));
241 // TODO(imcheng): Use a weak reference to ensure we don't call into an
242 // invalid context when the callback is invoked.
243 create_callback_.reset(args[2].As<v8::Function>());
245 base::MessageLoop::current()->PostTask(
246 FROM_HERE,
247 base::Bind(
248 &CastStreamingNativeHandler::CallCreateCallback,
249 weak_factory_.GetWeakPtr(),
250 base::Passed(&stream1),
251 base::Passed(&stream2),
252 base::Passed(&udp_transport)));
255 void CastStreamingNativeHandler::CallCreateCallback(
256 scoped_ptr<CastRtpStream> stream1,
257 scoped_ptr<CastRtpStream> stream2,
258 scoped_ptr<CastUdpTransport> udp_transport) {
259 v8::Isolate* isolate = context()->isolate();
260 v8::HandleScope handle_scope(isolate);
261 v8::Context::Scope context_scope(context()->v8_context());
263 v8::Handle<v8::Value> callback_args[3];
264 callback_args[0] = v8::Null(isolate);
265 callback_args[1] = v8::Null(isolate);
267 if (stream1) {
268 const int stream1_id = last_transport_id_++;
269 callback_args[0] = v8::Integer::New(isolate, stream1_id);
270 rtp_stream_map_[stream1_id] =
271 linked_ptr<CastRtpStream>(stream1.release());
273 if (stream2) {
274 const int stream2_id = last_transport_id_++;
275 callback_args[1] = v8::Integer::New(isolate, stream2_id);
276 rtp_stream_map_[stream2_id] =
277 linked_ptr<CastRtpStream>(stream2.release());
279 const int udp_id = last_transport_id_++;
280 udp_transport_map_[udp_id] =
281 linked_ptr<CastUdpTransport>(udp_transport.release());
282 callback_args[2] = v8::Integer::New(isolate, udp_id);
283 context()->CallFunction(create_callback_.NewHandle(isolate),
284 3, callback_args);
285 create_callback_.reset();
288 void CastStreamingNativeHandler::CallStartCallback(int stream_id) {
289 v8::Isolate* isolate = context()->isolate();
290 v8::HandleScope handle_scope(isolate);
291 v8::Context::Scope context_scope(context()->v8_context());
292 v8::Handle<v8::Array> event_args = v8::Array::New(isolate, 1);
293 event_args->Set(0, v8::Integer::New(isolate, stream_id));
294 context()->DispatchEvent("cast.streaming.rtpStream.onStarted", event_args);
297 void CastStreamingNativeHandler::CallStopCallback(int stream_id) {
298 v8::Isolate* isolate = context()->isolate();
299 v8::HandleScope handle_scope(isolate);
300 v8::Context::Scope context_scope(context()->v8_context());
301 v8::Handle<v8::Array> event_args = v8::Array::New(isolate, 1);
302 event_args->Set(0, v8::Integer::New(isolate, stream_id));
303 context()->DispatchEvent("cast.streaming.rtpStream.onStopped", event_args);
306 void CastStreamingNativeHandler::CallErrorCallback(int stream_id,
307 const std::string& message) {
308 v8::Isolate* isolate = context()->isolate();
309 v8::HandleScope handle_scope(isolate);
310 v8::Context::Scope context_scope(context()->v8_context());
311 v8::Handle<v8::Array> event_args = v8::Array::New(isolate, 2);
312 event_args->Set(0, v8::Integer::New(isolate, stream_id));
313 event_args->Set(
315 v8::String::NewFromUtf8(
316 isolate, message.data(), v8::String::kNormalString, message.size()));
317 context()->DispatchEvent("cast.streaming.rtpStream.onError", event_args);
320 void CastStreamingNativeHandler::DestroyCastRtpStream(
321 const v8::FunctionCallbackInfo<v8::Value>& args) {
322 CHECK_EQ(1, args.Length());
323 CHECK(args[0]->IsInt32());
325 const int transport_id = args[0]->ToInt32()->Value();
326 if (!GetRtpStreamOrThrow(transport_id))
327 return;
328 rtp_stream_map_.erase(transport_id);
331 void CastStreamingNativeHandler::GetSupportedParamsCastRtpStream(
332 const v8::FunctionCallbackInfo<v8::Value>& args) {
333 CHECK_EQ(1, args.Length());
334 CHECK(args[0]->IsInt32());
336 const int transport_id = args[0]->ToInt32()->Value();
337 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
338 if (!transport)
339 return;
341 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
342 std::vector<CastRtpParams> cast_params = transport->GetSupportedParams();
343 v8::Handle<v8::Array> result =
344 v8::Array::New(args.GetIsolate(),
345 static_cast<int>(cast_params.size()));
346 for (size_t i = 0; i < cast_params.size(); ++i) {
347 RtpParams params;
348 FromCastRtpParams(cast_params[i], &params);
349 scoped_ptr<base::DictionaryValue> params_value = params.ToValue();
350 result->Set(
351 static_cast<int>(i),
352 converter->ToV8Value(params_value.get(), context()->v8_context()));
354 args.GetReturnValue().Set(result);
357 void CastStreamingNativeHandler::StartCastRtpStream(
358 const v8::FunctionCallbackInfo<v8::Value>& args) {
359 CHECK_EQ(2, args.Length());
360 CHECK(args[0]->IsInt32());
361 CHECK(args[1]->IsObject());
363 const int transport_id = args[0]->ToInt32()->Value();
364 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
365 if (!transport)
366 return;
368 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
369 scoped_ptr<base::Value> params_value(
370 converter->FromV8Value(args[1], context()->v8_context()));
371 if (!params_value) {
372 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
373 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertParams)));
374 return;
376 scoped_ptr<RtpParams> params = RtpParams::FromValue(*params_value);
377 if (!params) {
378 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
379 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidRtpParams)));
380 return;
383 CastRtpParams cast_params;
384 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
385 if (!ToCastRtpParamsOrThrow(isolate, *params, &cast_params))
386 return;
388 base::Closure start_callback =
389 base::Bind(&CastStreamingNativeHandler::CallStartCallback,
390 weak_factory_.GetWeakPtr(),
391 transport_id);
392 base::Closure stop_callback =
393 base::Bind(&CastStreamingNativeHandler::CallStopCallback,
394 weak_factory_.GetWeakPtr(),
395 transport_id);
396 CastRtpStream::ErrorCallback error_callback =
397 base::Bind(&CastStreamingNativeHandler::CallErrorCallback,
398 weak_factory_.GetWeakPtr(),
399 transport_id);
400 transport->Start(cast_params, start_callback, stop_callback, error_callback);
403 void CastStreamingNativeHandler::StopCastRtpStream(
404 const v8::FunctionCallbackInfo<v8::Value>& args) {
405 CHECK_EQ(1, args.Length());
406 CHECK(args[0]->IsInt32());
408 const int transport_id = args[0]->ToInt32()->Value();
409 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
410 if (!transport)
411 return;
412 transport->Stop();
415 void CastStreamingNativeHandler::DestroyCastUdpTransport(
416 const v8::FunctionCallbackInfo<v8::Value>& args) {
417 CHECK_EQ(1, args.Length());
418 CHECK(args[0]->IsInt32());
420 const int transport_id = args[0]->ToInt32()->Value();
421 if (!GetUdpTransportOrThrow(transport_id))
422 return;
423 udp_transport_map_.erase(transport_id);
426 void CastStreamingNativeHandler::SetDestinationCastUdpTransport(
427 const v8::FunctionCallbackInfo<v8::Value>& args) {
428 CHECK_EQ(2, args.Length());
429 CHECK(args[0]->IsInt32());
430 CHECK(args[1]->IsObject());
432 const int transport_id = args[0]->ToInt32()->Value();
433 CastUdpTransport* transport = GetUdpTransportOrThrow(transport_id);
434 if (!transport)
435 return;
437 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
438 scoped_ptr<base::Value> destination_value(
439 converter->FromV8Value(args[1], context()->v8_context()));
440 if (!destination_value) {
441 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
442 v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
443 return;
445 scoped_ptr<IPEndPoint> destination =
446 IPEndPoint::FromValue(*destination_value);
447 if (!destination) {
448 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
449 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
450 return;
452 net::IPAddressNumber ip;
453 if (!net::ParseIPLiteralToNumber(destination->address, &ip)) {
454 args.GetIsolate()->ThrowException(v8::Exception::TypeError(
455 v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
456 return;
458 transport->SetDestination(net::IPEndPoint(ip, destination->port));
461 void CastStreamingNativeHandler::ToggleLogging(
462 const v8::FunctionCallbackInfo<v8::Value>& args) {
463 CHECK_EQ(2, args.Length());
464 CHECK(args[0]->IsInt32());
465 CHECK(args[1]->IsBoolean());
467 const int stream_id = args[0]->ToInt32()->Value();
468 CastRtpStream* stream = GetRtpStreamOrThrow(stream_id);
469 if (!stream)
470 return;
472 const bool enable = args[1]->ToBoolean()->Value();
473 stream->ToggleLogging(enable);
476 void CastStreamingNativeHandler::GetRawEvents(
477 const v8::FunctionCallbackInfo<v8::Value>& args) {
478 CHECK_EQ(3, args.Length());
479 CHECK(args[0]->IsInt32());
480 CHECK(args[1]->IsNull() || args[1]->IsString());
481 CHECK(args[2]->IsFunction());
483 const int transport_id = args[0]->ToInt32()->Value();
484 // TODO(imcheng): Use a weak reference to ensure we don't call into an
485 // invalid context when the callback is invoked.
486 linked_ptr<ScopedPersistent<v8::Function> > callback(
487 new ScopedPersistent<v8::Function>(args[2].As<v8::Function>()));
488 std::string extra_data;
489 if (!args[1]->IsNull()) {
490 extra_data = *v8::String::Utf8Value(args[1]);
493 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
494 if (!transport)
495 return;
497 get_raw_events_callbacks_.insert(std::make_pair(transport_id, callback));
499 transport->GetRawEvents(
500 base::Bind(&CastStreamingNativeHandler::CallGetRawEventsCallback,
501 weak_factory_.GetWeakPtr(),
502 transport_id),
503 extra_data);
506 void CastStreamingNativeHandler::GetStats(
507 const v8::FunctionCallbackInfo<v8::Value>& args) {
508 CHECK_EQ(2, args.Length());
509 CHECK(args[0]->IsInt32());
510 CHECK(args[1]->IsFunction());
511 const int transport_id = args[0]->ToInt32()->Value();
512 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
513 if (!transport)
514 return;
516 // TODO(imcheng): Use a weak reference to ensure we don't call into an
517 // invalid context when the callback is invoked.
518 linked_ptr<ScopedPersistent<v8::Function> > callback(
519 new ScopedPersistent<v8::Function>(args[1].As<v8::Function>()));
520 get_stats_callbacks_.insert(std::make_pair(transport_id, callback));
522 transport->GetStats(
523 base::Bind(&CastStreamingNativeHandler::CallGetStatsCallback,
524 weak_factory_.GetWeakPtr(),
525 transport_id));
528 void CastStreamingNativeHandler::CallGetRawEventsCallback(
529 int transport_id,
530 scoped_ptr<base::BinaryValue> raw_events) {
531 v8::Isolate* isolate = context()->isolate();
532 v8::HandleScope handle_scope(isolate);
533 v8::Context::Scope context_scope(context()->v8_context());
535 RtpStreamCallbackMap::iterator it =
536 get_raw_events_callbacks_.find(transport_id);
537 if (it == get_raw_events_callbacks_.end())
538 return;
539 v8::Handle<v8::Value> callback_args[1];
540 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
541 callback_args[0] =
542 converter->ToV8Value(raw_events.get(), context()->v8_context());
543 context()->CallFunction(it->second->NewHandle(isolate), 1, callback_args);
544 get_raw_events_callbacks_.erase(it);
547 void CastStreamingNativeHandler::CallGetStatsCallback(
548 int transport_id,
549 scoped_ptr<base::DictionaryValue> stats) {
550 v8::Isolate* isolate = context()->isolate();
551 v8::HandleScope handle_scope(isolate);
552 v8::Context::Scope context_scope(context()->v8_context());
554 RtpStreamCallbackMap::iterator it = get_stats_callbacks_.find(transport_id);
555 if (it == get_stats_callbacks_.end())
556 return;
558 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
559 v8::Handle<v8::Value> callback_args[1];
560 callback_args[0] = converter->ToV8Value(stats.get(), context()->v8_context());
561 context()->CallFunction(it->second->NewHandle(isolate), 1, callback_args);
562 get_stats_callbacks_.erase(it);
565 CastRtpStream* CastStreamingNativeHandler::GetRtpStreamOrThrow(
566 int transport_id) const {
567 RtpStreamMap::const_iterator iter = rtp_stream_map_.find(
568 transport_id);
569 if (iter != rtp_stream_map_.end())
570 return iter->second.get();
571 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
572 isolate->ThrowException(v8::Exception::RangeError(v8::String::NewFromUtf8(
573 isolate, kRtpStreamNotFound)));
574 return NULL;
577 CastUdpTransport* CastStreamingNativeHandler::GetUdpTransportOrThrow(
578 int transport_id) const {
579 UdpTransportMap::const_iterator iter = udp_transport_map_.find(
580 transport_id);
581 if (iter != udp_transport_map_.end())
582 return iter->second.get();
583 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
584 isolate->ThrowException(v8::Exception::RangeError(
585 v8::String::NewFromUtf8(isolate, kUdpTransportNotFound)));
586 return NULL;
589 } // namespace extensions