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

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: Report errors via 'chrome.runtime.lastError' 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 kInvalidStreamArgs[] = "Invalid stream arguments";
22 const char kSessionAlreadyStarted[] = "The session has been already started";
23 const char kSessionAlreadyTerminating[] = "The session is already terminating";
24 const char kSessionNotFound[] = "Session not found";
25 } // namespace
26
27 DisplaySourceCustomBindings::DisplaySourceCustomBindings(ScriptContext* context)
28 : ObjectBackedNativeHandler(context),
29 weak_factory_(this) {
30 RouteFunction("StartSession",
31 base::Bind(&DisplaySourceCustomBindings::StartSession,
32 weak_factory_.GetWeakPtr()));
33 RouteFunction("TerminateSession",
34 base::Bind(&DisplaySourceCustomBindings::TerminateSession,
35 weak_factory_.GetWeakPtr()));
36 }
37
38 DisplaySourceCustomBindings::~DisplaySourceCustomBindings() {
39 }
40
41 void DisplaySourceCustomBindings::Invalidate() {
42 session_map_.clear();
43 weak_factory_.InvalidateWeakPtrs();
44 ObjectBackedNativeHandler::Invalidate();
45 }
46
47 namespace {
48
49 v8::Local<v8::Value> GetChildValue(v8::Local<v8::Object> value,
50 const std::string& key_name,
51 v8::Isolate* isolate) {
52 v8::Local<v8::Array> property_names(value->GetOwnPropertyNames());
53 for (uint32 i = 0; i < property_names->Length(); ++i) {
54 v8::Local<v8::Value> key(property_names->Get(i));
55 if (key_name == *v8::String::Utf8Value(key)) {
56 v8::TryCatch try_catch(isolate);
57 v8::Local<v8::Value> child_v8 = value->Get(key);
58 if (try_catch.HasCaught()) {
59 return v8::Null(isolate);
60 }
61 return child_v8;
62 }
63 }
64
65 return v8::Null(isolate);
66 }
67
68 } // namespace
69
70 void DisplaySourceCustomBindings::StartSession(
71 const v8::FunctionCallbackInfo<v8::Value>& args) {
72 CHECK_EQ(1, args.Length());
73 CHECK(args[0]->IsObject());
74 v8::Isolate* isolate = context()->isolate();
75 v8::Local<v8::Object> start_info = args[0].As<v8::Object>();
76
77 v8::Local<v8::Value> sink_id_val =
78 GetChildValue(start_info, "sinkId", isolate);
79 CHECK(sink_id_val->IsInt32());
80 const int sink_id = sink_id_val->ToInt32(isolate)->Value();
81 if (GetDisplaySession(sink_id)) {
82 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
83 isolate, kSessionAlreadyStarted)));
84 return;
85 }
86
87 v8::Local<v8::Value> video_stream_val =
88 GetChildValue(start_info, "videoTrack", isolate);
89 v8::Local<v8::Value> audio_stream_val =
90 GetChildValue(start_info, "audioTrack", isolate);
91
92 if ((video_stream_val->IsNull() || video_stream_val->IsUndefined()) &&
93 (audio_stream_val->IsNull() || audio_stream_val->IsUndefined())) {
94 isolate->ThrowException(v8::Exception::Error(
95 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
96 return;
97 }
98
99 blink::WebMediaStreamTrack audio_track, video_track;
100
101 if (!video_stream_val->IsNull() && !video_stream_val->IsUndefined()) {
102 CHECK(video_stream_val->IsObject());
103 video_track =
104 blink::WebDOMMediaStreamTrack::fromV8Value(
105 video_stream_val).component();
106 if (video_track.isNull()) {
107 isolate->ThrowException(v8::Exception::Error(
108 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
109 return;
110 }
111 }
112 if (!audio_stream_val->IsNull() && !audio_stream_val->IsUndefined()) {
113 CHECK(audio_stream_val->IsObject());
114 audio_track =
115 blink::WebDOMMediaStreamTrack::fromV8Value(
116 audio_stream_val).component();
117 if (audio_track.isNull()) {
118 isolate->ThrowException(v8::Exception::Error(
119 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
120 return;
121 }
122 }
123
124 scoped_ptr<DisplaySourceAuthInfo> auth_info;
125 v8::Local<v8::Value> auth_info_v8_val =
126 GetChildValue(start_info, "authenticationInfo", isolate);
127 if (!auth_info_v8_val->IsNull()) {
128 CHECK(auth_info_v8_val->IsObject());
129 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
130 scoped_ptr<base::Value> auth_info_val(
131 converter->FromV8Value(auth_info_v8_val, context()->v8_context()));
132 CHECK(auth_info_val);
133 auth_info = DisplaySourceAuthInfo::FromValue(*auth_info_val);
134 }
135
136 scoped_ptr<DisplaySourceSession> session =
137 DisplaySourceSessionFactory::CreateSession(
138 sink_id, video_track, audio_track, std::move(auth_info));
139 if (!session) {
140 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
141 isolate, kErrorNotSupported)));
142 return;
143 }
144
145 auto on_started_callback = base::Bind(
146 &DisplaySourceCustomBindings::OnSessionStarted,
147 weak_factory_.GetWeakPtr());
148 auto on_terminated_callback = base::Bind(
149 &DisplaySourceCustomBindings::OnSessionTerminated,
150 weak_factory_.GetWeakPtr());
151 auto on_error_callback = base::Bind(
152 &DisplaySourceCustomBindings::OnSessionError,
153 weak_factory_.GetWeakPtr());
154 session->SetCallbacks(on_started_callback,
155 on_terminated_callback,
156 on_error_callback);
157 session_map_.insert(std::make_pair(sink_id, std::move(session)));
158 session->Start();
159 }
160
161 void DisplaySourceCustomBindings::TerminateSession(
162 const v8::FunctionCallbackInfo<v8::Value>& args) {
163 CHECK_EQ(1, args.Length());
164 CHECK(args[0]->IsInt32());
165
166 v8::Isolate* isolate = context()->isolate();
167 int sink_id = args[0]->ToInt32(args.GetIsolate())->Value();
168 DisplaySourceSession* session = GetDisplaySession(sink_id);
169 if (!session) {
170 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
171 isolate, kSessionNotFound)));
172 return;
173 }
174
175 if (session->state() == DisplaySourceSession::Terminating) {
176 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
177 isolate, kSessionAlreadyTerminating)));
178 return;
179 }
180
181 session->Terminate();
asargent_no_longer_on_chrome 2015/12/07 21:47:49 I'm assuming we rely on the concrete implementatio
Mikhail 2015/12/08 07:44:44 Done.
182 }
183
184 void DisplaySourceCustomBindings::DispatchSessionStarted(int sink_id) const {
185 v8::Isolate* isolate = context()->isolate();
186 v8::HandleScope handle_scope(isolate);
187 v8::Context::Scope context_scope(context()->v8_context());
188 v8::Local<v8::Array> event_args = v8::Array::New(isolate, 1);
189 event_args->Set(0, v8::Integer::New(isolate, sink_id));
190 context()->DispatchEvent("displaySource.onSessionStarted", event_args);
191 }
192
193 void DisplaySourceCustomBindings::DispatchSessionTerminated(int sink_id) const {
194 v8::Isolate* isolate = context()->isolate();
195 v8::HandleScope handle_scope(isolate);
196 v8::Context::Scope context_scope(context()->v8_context());
197 v8::Local<v8::Array> event_args = v8::Array::New(isolate, 1);
198 event_args->Set(0, v8::Integer::New(isolate, sink_id));
199 context()->DispatchEvent("displaySource.onSessionTerminated", event_args);
200 }
201
202 void DisplaySourceCustomBindings::DispatchSessionError(
203 int sink_id,
204 DisplaySourceErrorType type,
205 const std::string& message) const {
206 v8::Isolate* isolate = context()->isolate();
207 v8::HandleScope handle_scope(isolate);
208 v8::Context::Scope context_scope(context()->v8_context());
209
210 api::display_source::ErrorInfo error_info;
211 error_info.type = type;
212 if (!message.empty())
213 error_info.description.reset(new std::string(message));
214
215 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
216 v8::Local<v8::Value> info_arg =
217 converter->ToV8Value(error_info.ToValue().get(),
218 context()->v8_context());
219
220 v8::Local<v8::Array> event_args = v8::Array::New(isolate, 2);
221 event_args->Set(0, v8::Integer::New(isolate, sink_id));
222 event_args->Set(1, info_arg);
223 context()->DispatchEvent("displaySource.onSessionErrorOccured", event_args);
224 }
225
226 DisplaySourceSession* DisplaySourceCustomBindings::GetDisplaySession(
227 int sink_id) const {
228 auto iter = session_map_.find(sink_id);
229 if (iter != session_map_.end())
230 return iter->second.get();
231 return nullptr;
232 }
233
234 void DisplaySourceCustomBindings::OnSessionStarted(int sink_id) {
235 DispatchSessionStarted(sink_id);
236 }
237
238 void DisplaySourceCustomBindings::OnSessionTerminated(int sink_id) {
239 DisplaySourceSession* session = GetDisplaySession(sink_id);
240 CHECK(session);
241 session_map_.erase(sink_id);
242 DispatchSessionTerminated(sink_id);
243 }
244
245 void DisplaySourceCustomBindings::OnSessionError(int sink_id,
246 DisplaySourceErrorType type,
247 const std::string& message) {
248 DisplaySourceSession* session = GetDisplaySession(sink_id);
249 CHECK(session);
250 if (session->state() == DisplaySourceSession::Establishing) {
251 // Error has occured before the session has actually started.
252 session_map_.erase(sink_id);
253 }
254
255 DispatchSessionError(sink_id, type, message);
256 }
257
258 } // extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698