Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(672)

Side by Side Diff: extensions/renderer/display_source_custom_bindings.cc

Issue 1471243002: chrome.displaySource custom bindings (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments from Antony Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/renderer/display_source_custom_bindings.h"
6
7 #include "base/bind.h"
8 #include "content/public/child/v8_value_converter.h"
9 #include "extensions/renderer/script_context.h"
10 #include "third_party/WebKit/public/platform/WebMediaStream.h"
11 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
12 #include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h"
13 #include "v8/include/v8.h"
14
15 namespace extensions {
16
17 using content::V8ValueConverter;
18
19 namespace {
20 const char kErrorNotSupported[] = "Not supported";
21 const char kInvalidSinkIdArg[] = "Invalid sink Id argument";
22 const char kInvalidAuthInfoArg[] = "Invalid authentication info argument";
23 const char kInvalidStreamArgs[] = "Invalid stream arguments";
24 const char kSessionAlreadyStarted[] = "The session has been already started";
25 const char kSessionAlreadyTerminating[] = "The session is already terminating";
26 const char kSessionNotFound[] = "Session not found";
27 } // namespace
28
29 DisplaySourceCustomBindings::DisplaySourceCustomBindings(ScriptContext* context)
30 : ObjectBackedNativeHandler(context),
31 weak_factory_(this) {
32 RouteFunction("StartSession",
33 base::Bind(&DisplaySourceCustomBindings::StartSession,
34 weak_factory_.GetWeakPtr()));
35 RouteFunction("TerminateSession",
36 base::Bind(&DisplaySourceCustomBindings::TerminateSession,
37 weak_factory_.GetWeakPtr()));
38 }
39
40 DisplaySourceCustomBindings::~DisplaySourceCustomBindings() {
41 }
42
43 void DisplaySourceCustomBindings::Invalidate() {
44 session_map_.clear();
45 terminate_callback_map_.clear();
46 weak_factory_.InvalidateWeakPtrs();
47 ObjectBackedNativeHandler::Invalidate();
48 }
49
50 namespace {
51
52 v8::Local<v8::Value> GetChildValue(v8::Local<v8::Object> value,
53 const std::string& key_name,
54 v8::Isolate* isolate) {
55 v8::Local<v8::Array> property_names(value->GetOwnPropertyNames());
56 for (uint32 i = 0; i < property_names->Length(); ++i) {
57 v8::Local<v8::Value> key(property_names->Get(i));
58 if (key_name == *v8::String::Utf8Value(key)) {
59 v8::TryCatch try_catch(isolate);
60 v8::Local<v8::Value> child_v8 = value->Get(key);
61 if (try_catch.HasCaught()) {
62 return v8::Null(isolate);
63 }
64 return child_v8;
65 }
66 }
67
68 return v8::Null(isolate);
69 }
70
71 } // namespace
72
73 void DisplaySourceCustomBindings::StartSession(
74 const v8::FunctionCallbackInfo<v8::Value>& args) {
75 CHECK_EQ(1, args.Length());
76 CHECK(args[0]->IsObject());
77 v8::Isolate* isolate = context()->isolate();
78 v8::Local<v8::Object> start_info = args[0].As<v8::Object>();
79
80 v8::Local<v8::Value> sink_id_val =
81 GetChildValue(start_info, "sinkId", isolate);
82 if (sink_id_val->IsNull() || sink_id_val->IsUndefined()) {
83 isolate->ThrowException(v8::Exception::Error(
84 v8::String::NewFromUtf8(isolate, kInvalidSinkIdArg)));
85 return;
86 }
87 const int sink_id = sink_id_val->ToInt32(isolate)->Value();
88 if (GetDisplaySession(sink_id)) {
89 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
90 isolate, kSessionAlreadyStarted)));
91 return;
92 }
93
94 v8::Local<v8::Value> video_stream_val =
95 GetChildValue(start_info, "videoTrack", isolate);
96 v8::Local<v8::Value> audio_stream_val =
97 GetChildValue(start_info, "audioTrack", isolate);
98
99 if ((video_stream_val->IsNull() || video_stream_val->IsUndefined()) &&
100 (audio_stream_val->IsNull() || audio_stream_val->IsUndefined())) {
101 isolate->ThrowException(v8::Exception::Error(
102 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
103 return;
104 }
105 blink::WebMediaStreamTrack audio_track, video_track;
106
107 if (!video_stream_val->IsNull() && !video_stream_val->IsUndefined()) {
108 CHECK(video_stream_val->IsObject());
109 video_track =
110 blink::WebDOMMediaStreamTrack::fromV8Value(
111 video_stream_val).component();
112 if (video_track.isNull()) {
113 isolate->ThrowException(v8::Exception::Error(
114 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
115 return;
116 }
117 }
118 if (!audio_stream_val->IsNull() && !audio_stream_val->IsUndefined()) {
119 CHECK(audio_stream_val->IsObject());
120 audio_track =
121 blink::WebDOMMediaStreamTrack::fromV8Value(
122 audio_stream_val).component();
123 if (audio_track.isNull()) {
124 isolate->ThrowException(v8::Exception::Error(
125 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
126 return;
127 }
128 }
129
130 v8::Local<v8::Value> auth_info_v8_val =
131 GetChildValue(start_info, "authenticationInfo", isolate);
132 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
133 scoped_ptr<base::Value> auth_info_val(
134 converter->FromV8Value(auth_info_v8_val, context()->v8_context()));
135 scoped_ptr<DisplaySourceAuthInfo> auth_info;
136 if (auth_info_val) {
137 auth_info = DisplaySourceAuthInfo::FromValue(*auth_info_val);
138 if (!auth_info) {
139 isolate->ThrowException(v8::Exception::Error(
140 v8::String::NewFromUtf8(isolate, kInvalidAuthInfoArg)));
141 return;
142 }
143 }
144
145 scoped_ptr<DisplaySourceSession> session =
146 DisplaySourceSessionFactory::CreateSession(
147 sink_id, video_track, audio_track, std::move(auth_info));
148 if (!session) {
149 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
150 isolate, kErrorNotSupported)));
151 return;
152 }
153
154 auto on_started_callback = base::Bind(
155 &DisplaySourceCustomBindings::OnSessionStarted,
156 weak_factory_.GetWeakPtr());
157 auto on_terminated_callback = base::Bind(
158 &DisplaySourceCustomBindings::OnSessionTerminated,
159 weak_factory_.GetWeakPtr());
160 auto on_error_callback = base::Bind(
161 &DisplaySourceCustomBindings::OnSessionError,
162 weak_factory_.GetWeakPtr());
163 session->SetCallbacks(on_started_callback,
164 on_terminated_callback,
165 on_error_callback);
166 session_map_.insert(std::make_pair(sink_id, std::move(session)));
167 session->Start();
168 }
169
170 void DisplaySourceCustomBindings::TerminateSession(
171 const v8::FunctionCallbackInfo<v8::Value>& args) {
172 CHECK_EQ(2, args.Length());
173 CHECK(args[0]->IsInt32());
174 CHECK(args[1]->IsNull() || args[1]->IsFunction());
175
176 v8::Isolate* isolate = context()->isolate();
177 v8::Global<v8::Function> terminate_callback;
178 if (!args[1]->IsNull())
179 terminate_callback.Reset(isolate, args[1].As<v8::Function>());
180
181 int sink_id = args[0]->ToInt32(args.GetIsolate())->Value();
182 DisplaySourceSession* session = GetDisplaySession(sink_id);
183 if (!session) {
184 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
185 isolate, kSessionNotFound)));
186 return;
187 }
188
189 if (session->state() == DisplaySourceSession::Terminating) {
190 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
191 isolate, kSessionAlreadyTerminating)));
192 return;
193 }
194
195 if (!terminate_callback.IsEmpty()) {
196 CHECK(terminate_callback_map_.find(sink_id) ==
197 terminate_callback_map_.end());
198 terminate_callback_map_.insert(
199 std::make_pair(sink_id, std::move(terminate_callback)));
200 }
201
202 session->Terminate();
203 }
204
205 void DisplaySourceCustomBindings::DispatchSessionStarted(int sink_id) const {
206 v8::Isolate* isolate = context()->isolate();
207 v8::HandleScope handle_scope(isolate);
208 v8::Context::Scope context_scope(context()->v8_context());
209 v8::Local<v8::Array> event_args = v8::Array::New(isolate, 1);
210 event_args->Set(0, v8::Integer::New(isolate, sink_id));
211 context()->DispatchEvent("displaySource.onSessionStarted", event_args);
212 }
213
214 void DisplaySourceCustomBindings::DispatchSessionTerminated(int sink_id) const {
215 v8::Isolate* isolate = context()->isolate();
216 v8::HandleScope handle_scope(isolate);
217 v8::Context::Scope context_scope(context()->v8_context());
218 v8::Local<v8::Array> event_args = v8::Array::New(isolate, 1);
219 event_args->Set(0, v8::Integer::New(isolate, sink_id));
220 context()->DispatchEvent("displaySource.onSessionTerminated", event_args);
221 }
222
223 void DisplaySourceCustomBindings::DispatchSessionError(
224 int sink_id,
225 DisplaySourceErrorType type,
226 const std::string& message) const {
227 v8::Isolate* isolate = context()->isolate();
228 v8::HandleScope handle_scope(isolate);
229 v8::Context::Scope context_scope(context()->v8_context());
230
231 api::display_source::ErrorInfo error_info;
232 error_info.type = type;
233 if (!message.empty())
234 error_info.description.reset(new std::string(message));
235
236 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
237 v8::Local<v8::Value> info_arg =
238 converter->ToV8Value(error_info.ToValue().get(),
239 context()->v8_context());
240
241 v8::Local<v8::Array> event_args = v8::Array::New(isolate, 2);
242 event_args->Set(0, v8::Integer::New(isolate, sink_id));
243 event_args->Set(1, info_arg);
244 context()->DispatchEvent("displaySource.onSessionErrorOccured", event_args);
245 }
246
247 DisplaySourceSession* DisplaySourceCustomBindings::GetDisplaySession(
248 int sink_id) const {
249 auto iter = session_map_.find(sink_id);
250 if (iter != session_map_.end())
251 return iter->second.get();
252 return nullptr;
253 }
254
255 void DisplaySourceCustomBindings::OnSessionStarted(int sink_id) {
256 DispatchSessionStarted(sink_id);
257 }
258
259 void DisplaySourceCustomBindings::OnSessionTerminated(int sink_id) {
260 DisplaySourceSession* session = GetDisplaySession(sink_id);
261 CHECK(session);
262 session_map_.erase(sink_id);
263
264 // Call a termination callback if needed.
265 auto iter = terminate_callback_map_.find(sink_id);
266 if (iter != terminate_callback_map_.end()) {
267 v8::Isolate* isolate = context()->isolate();
268 v8::Local<v8::Value> callback_args[1];
269 callback_args[0] = v8::Integer::New(isolate, sink_id);
270 context()->CallFunction(
271 v8::Local<v8::Function>::New(isolate, iter->second), 1,
272 callback_args);
273 terminate_callback_map_.erase(iter);
274 }
275
276 DispatchSessionTerminated(sink_id);
277 }
278
279 void DisplaySourceCustomBindings::OnSessionError(int sink_id,
280 DisplaySourceErrorType type,
281 const std::string& message) {
282 DisplaySourceSession* session = GetDisplaySession(sink_id);
283 CHECK(session);
284 if (session->state() == DisplaySourceSession::Establishing) {
285 // Error has occured before the session has actually started.
286 session_map_.erase(sink_id);
287 }
288
289 DispatchSessionError(sink_id, type, message);
290 }
291
292 } // extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698