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

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

Issue 2657613005: [Extensions Bindings] Add chrome.runtime.lastError support (Closed)
Patch Set: . Created 3 years, 10 months 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/native_extension_bindings_system.h" 5 #include "extensions/renderer/native_extension_bindings_system.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "content/public/common/content_switches.h" 9 #include "content/public/common/content_switches.h"
10 #include "extensions/common/constants.h" 10 #include "extensions/common/constants.h"
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 const SendEventListenerIPCMethod& send_event_listener_ipc) 131 const SendEventListenerIPCMethod& send_event_listener_ipc)
132 : send_request_ipc_(send_request_ipc), 132 : send_request_ipc_(send_request_ipc),
133 send_event_listener_ipc_(send_event_listener_ipc), 133 send_event_listener_ipc_(send_event_listener_ipc),
134 api_system_( 134 api_system_(
135 base::Bind(&CallJsFunction), 135 base::Bind(&CallJsFunction),
136 base::Bind(&CallJsFunctionSync), 136 base::Bind(&CallJsFunctionSync),
137 base::Bind(&GetAPISchema), 137 base::Bind(&GetAPISchema),
138 base::Bind(&NativeExtensionBindingsSystem::SendRequest, 138 base::Bind(&NativeExtensionBindingsSystem::SendRequest,
139 base::Unretained(this)), 139 base::Unretained(this)),
140 base::Bind(&NativeExtensionBindingsSystem::OnEventListenerChanged, 140 base::Bind(&NativeExtensionBindingsSystem::OnEventListenerChanged,
141 base::Unretained(this))), 141 base::Unretained(this)),
142 APILastError(base::Bind(&GetRuntime))),
142 weak_factory_(this) {} 143 weak_factory_(this) {}
143 144
144 NativeExtensionBindingsSystem::~NativeExtensionBindingsSystem() {} 145 NativeExtensionBindingsSystem::~NativeExtensionBindingsSystem() {}
145 146
146 void NativeExtensionBindingsSystem::DidCreateScriptContext( 147 void NativeExtensionBindingsSystem::DidCreateScriptContext(
147 ScriptContext* context) {} 148 ScriptContext* context) {}
148 149
149 void NativeExtensionBindingsSystem::WillReleaseScriptContext( 150 void NativeExtensionBindingsSystem::WillReleaseScriptContext(
150 ScriptContext* context) {} 151 ScriptContext* context) {}
151 152
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 // creation, but also when e.g. permissions change. We need to be checking 195 // creation, but also when e.g. permissions change. We need to be checking
195 // for whether or not the API already exists on the object as well as 196 // for whether or not the API already exists on the object as well as
196 // if we need to remove any existing APIs. 197 // if we need to remove any existing APIs.
197 if (!context->IsAnyFeatureAvailableToContext(*map_entry.second, 198 if (!context->IsAnyFeatureAvailableToContext(*map_entry.second,
198 CheckAliasStatus::NOT_ALLOWED)) 199 CheckAliasStatus::NOT_ALLOWED))
199 continue; 200 continue;
200 201
201 v8::Local<v8::String> api_name = 202 v8::Local<v8::String> api_name =
202 gin::StringToSymbol(v8_context->GetIsolate(), map_entry.first); 203 gin::StringToSymbol(v8_context->GetIsolate(), map_entry.first);
203 v8::Maybe<bool> success = chrome->SetAccessor( 204 v8::Maybe<bool> success = chrome->SetAccessor(
204 v8_context, api_name, &GetAPIHelper, nullptr, api_name); 205 v8_context, api_name, &BindingAccessor, nullptr, api_name);
205 if (!success.IsJust() || !success.FromJust()) { 206 if (!success.IsJust() || !success.FromJust()) {
206 LOG(ERROR) << "Failed to create API on Chrome object."; 207 LOG(ERROR) << "Failed to create API on Chrome object.";
207 return; 208 return;
208 } 209 }
209 } 210 }
210 } 211 }
211 212
212 void NativeExtensionBindingsSystem::DispatchEventInContext( 213 void NativeExtensionBindingsSystem::DispatchEventInContext(
213 const std::string& event_name, 214 const std::string& event_name,
214 const base::ListValue* event_args, 215 const base::ListValue* event_args,
215 const base::DictionaryValue* filtering_info, 216 const base::DictionaryValue* filtering_info,
216 ScriptContext* context) { 217 ScriptContext* context) {
217 v8::HandleScope handle_scope(context->isolate()); 218 v8::HandleScope handle_scope(context->isolate());
218 v8::Context::Scope context_scope(context->v8_context()); 219 v8::Context::Scope context_scope(context->v8_context());
219 // TODO(devlin): Take into account |filtering_info|. 220 // TODO(devlin): Take into account |filtering_info|.
220 api_system_.FireEventInContext(event_name, context->v8_context(), 221 api_system_.FireEventInContext(event_name, context->v8_context(),
221 *event_args); 222 *event_args);
222 } 223 }
223 224
224 void NativeExtensionBindingsSystem::HandleResponse( 225 void NativeExtensionBindingsSystem::HandleResponse(
225 int request_id, 226 int request_id,
226 bool success, 227 bool success,
227 const base::ListValue& response, 228 const base::ListValue& response,
228 const std::string& error) { 229 const std::string& error) {
229 api_system_.CompleteRequest(request_id, response); 230 api_system_.CompleteRequest(request_id, response, error);
230 } 231 }
231 232
232 RequestSender* NativeExtensionBindingsSystem::GetRequestSender() { 233 RequestSender* NativeExtensionBindingsSystem::GetRequestSender() {
233 return nullptr; 234 return nullptr;
234 } 235 }
235 236
236 // static 237 void NativeExtensionBindingsSystem::BindingAccessor(
237 void NativeExtensionBindingsSystem::GetAPIHelper(
238 v8::Local<v8::Name> name, 238 v8::Local<v8::Name> name,
239 const v8::PropertyCallbackInfo<v8::Value>& info) { 239 const v8::PropertyCallbackInfo<v8::Value>& info) {
240 v8::Isolate* isolate = info.GetIsolate(); 240 v8::Isolate* isolate = info.GetIsolate();
241 v8::HandleScope handle_scope(isolate); 241 v8::HandleScope handle_scope(isolate);
242 v8::Local<v8::Context> context = info.Holder()->CreationContext(); 242 v8::Local<v8::Context> context = info.Holder()->CreationContext();
243
244 // We use info.Data() to store a real name here instead of using the provided
245 // one to handle any weirdness from the caller (non-existent strings, etc).
246 v8::Local<v8::String> api_name = info.Data().As<v8::String>();
247 v8::Local<v8::Object> binding = GetAPIHelper(context, api_name);
248 if (!binding.IsEmpty())
249 info.GetReturnValue().Set(binding);
250 }
251
252 // static
253 v8::Local<v8::Object> NativeExtensionBindingsSystem::GetAPIHelper(
254 v8::Local<v8::Context> context,
255 v8::Local<v8::String> api_name) {
243 gin::PerContextData* per_context_data = gin::PerContextData::From(context); 256 gin::PerContextData* per_context_data = gin::PerContextData::From(context);
244 if (!per_context_data) 257 if (!per_context_data)
245 return; // Context is shutting down. 258 return v8::Local<v8::Object>(); // Context is shutting down.
246 BindingsSystemPerContextData* data = 259 BindingsSystemPerContextData* data =
247 static_cast<BindingsSystemPerContextData*>( 260 static_cast<BindingsSystemPerContextData*>(
248 per_context_data->GetUserData(kBindingsSystemPerContextKey)); 261 per_context_data->GetUserData(kBindingsSystemPerContextKey));
249 CHECK(data); 262 CHECK(data);
250 if (!data->bindings_system) { 263 if (!data->bindings_system) {
251 NOTREACHED() << "Context outlived bindings system."; 264 NOTREACHED() << "Context outlived bindings system.";
252 return; 265 return v8::Local<v8::Object>();
253 } 266 }
254 267
268 v8::Isolate* isolate = context->GetIsolate();
255 v8::Local<v8::Object> apis; 269 v8::Local<v8::Object> apis;
256 if (data->api_object.IsEmpty()) { 270 if (data->api_object.IsEmpty()) {
257 apis = v8::Object::New(isolate); 271 apis = v8::Object::New(isolate);
258 data->api_object = v8::Global<v8::Object>(isolate, apis); 272 data->api_object = v8::Global<v8::Object>(isolate, apis);
259 } else { 273 } else {
260 apis = data->api_object.Get(isolate); 274 apis = data->api_object.Get(isolate);
261 } 275 }
262 276
263 // We use info.Data() to store a real name here instead of using the provided 277 v8::Local<v8::Object> result;
264 // one to handle any weirdness from the caller (non-existent strings, etc).
265 v8::Local<v8::String> api_name = info.Data().As<v8::String>();
266 v8::Local<v8::Value> result;
267 v8::Maybe<bool> has_property = apis->HasRealNamedProperty(context, api_name); 278 v8::Maybe<bool> has_property = apis->HasRealNamedProperty(context, api_name);
268 if (!has_property.IsJust()) 279 if (!has_property.IsJust())
269 return; 280 return v8::Local<v8::Object>();
270 281
271 if (has_property.FromJust()) { 282 if (has_property.FromJust()) {
272 result = apis->GetRealNamedProperty(context, api_name).ToLocalChecked(); 283 v8::Local<v8::Value> value =
284 apis->GetRealNamedProperty(context, api_name).ToLocalChecked();
285 DCHECK(value->IsObject());
286 result = value.As<v8::Object>();
273 } else { 287 } else {
274 ScriptContext* script_context = 288 ScriptContext* script_context =
275 ScriptContextSet::GetContextByV8Context(context); 289 ScriptContextSet::GetContextByV8Context(context);
276 std::string api_name_string; 290 std::string api_name_string;
277 CHECK(gin::Converter<std::string>::FromV8(isolate, api_name, 291 CHECK(gin::Converter<std::string>::FromV8(isolate, api_name,
278 &api_name_string)); 292 &api_name_string));
279 v8::Local<v8::Object> hooks_interface; 293 v8::Local<v8::Object> hooks_interface;
280 APIBindingsSystem& api_system = data->bindings_system->api_system_; 294 APIBindingsSystem& api_system = data->bindings_system->api_system_;
281 result = api_system.CreateAPIInstance( 295 result = api_system.CreateAPIInstance(
282 api_name_string, context, isolate, 296 api_name_string, context, isolate,
283 base::Bind(&IsAPIMethodAvailable, script_context), &hooks_interface); 297 base::Bind(&IsAPIMethodAvailable, script_context), &hooks_interface);
284 298
285 gin::Handle<APIBindingBridge> bridge_handle = gin::CreateHandle( 299 gin::Handle<APIBindingBridge> bridge_handle = gin::CreateHandle(
286 isolate, 300 isolate,
287 new APIBindingBridge(context, result, hooks_interface, 301 new APIBindingBridge(context, result, hooks_interface,
288 script_context->GetExtensionID(), 302 script_context->GetExtensionID(),
289 script_context->GetContextTypeDescription(), 303 script_context->GetContextTypeDescription(),
290 base::Bind(&CallJsFunction))); 304 base::Bind(&CallJsFunction)));
291 v8::Local<v8::Value> native_api_bridge = bridge_handle.ToV8(); 305 v8::Local<v8::Value> native_api_bridge = bridge_handle.ToV8();
292 306
293 script_context->module_system()->OnNativeBindingCreated(api_name_string, 307 script_context->module_system()->OnNativeBindingCreated(api_name_string,
294 native_api_bridge); 308 native_api_bridge);
295 309
296 v8::Maybe<bool> success = 310 v8::Maybe<bool> success =
297 apis->CreateDataProperty(context, api_name, result); 311 apis->CreateDataProperty(context, api_name, result);
298 if (!success.IsJust() || !success.FromJust()) 312 if (!success.IsJust() || !success.FromJust())
299 return; 313 return v8::Local<v8::Object>();
300 } 314 }
301 info.GetReturnValue().Set(result); 315 return result;
316 }
317
318 v8::Local<v8::Object> NativeExtensionBindingsSystem::GetRuntime(
319 v8::Local<v8::Context> context) {
320 return GetAPIHelper(context,
321 gin::StringToSymbol(context->GetIsolate(), "runtime"));
302 } 322 }
303 323
304 void NativeExtensionBindingsSystem::SendRequest( 324 void NativeExtensionBindingsSystem::SendRequest(
305 std::unique_ptr<APIBinding::Request> request, 325 std::unique_ptr<APIBinding::Request> request,
306 v8::Local<v8::Context> context) { 326 v8::Local<v8::Context> context) {
307 ScriptContext* script_context = 327 ScriptContext* script_context =
308 ScriptContextSet::GetContextByV8Context(context); 328 ScriptContextSet::GetContextByV8Context(context);
309 329
310 GURL url; 330 GURL url;
311 blink::WebLocalFrame* frame = script_context->web_frame(); 331 blink::WebLocalFrame* frame = script_context->web_frame();
(...skipping 19 matching lines...) Expand all
331 351
332 void NativeExtensionBindingsSystem::OnEventListenerChanged( 352 void NativeExtensionBindingsSystem::OnEventListenerChanged(
333 const std::string& event_name, 353 const std::string& event_name,
334 binding::EventListenersChanged change, 354 binding::EventListenersChanged change,
335 v8::Local<v8::Context> context) { 355 v8::Local<v8::Context> context) {
336 send_event_listener_ipc_.Run( 356 send_event_listener_ipc_.Run(
337 change, ScriptContextSet::GetContextByV8Context(context), event_name); 357 change, ScriptContextSet::GetContextByV8Context(context), event_name);
338 } 358 }
339 359
340 } // namespace extensions 360 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698