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

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

Issue 1945433002: [Extensions] Update more bindings and allow for multiple feature access (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/object_backed_native_handler.h" 5 #include "extensions/renderer/object_backed_native_handler.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/linked_ptr.h" 10 #include "base/memory/linked_ptr.h"
11 #include "content/public/child/worker_thread.h" 11 #include "content/public/child/worker_thread.h"
12 #include "extensions/common/extension_api.h" 12 #include "extensions/common/extension_api.h"
13 #include "extensions/renderer/console.h" 13 #include "extensions/renderer/console.h"
14 #include "extensions/renderer/module_system.h" 14 #include "extensions/renderer/module_system.h"
15 #include "extensions/renderer/script_context.h" 15 #include "extensions/renderer/script_context.h"
16 #include "extensions/renderer/script_context_set.h" 16 #include "extensions/renderer/script_context_set.h"
17 #include "extensions/renderer/v8_helpers.h" 17 #include "extensions/renderer/v8_helpers.h"
18 #include "third_party/WebKit/public/web/WebLocalFrame.h" 18 #include "third_party/WebKit/public/web/WebLocalFrame.h"
19 #include "v8/include/v8.h" 19 #include "v8/include/v8.h"
20 20
21 namespace extensions { 21 namespace extensions {
22 22
23 namespace { 23 namespace {
24
25 using HandlerFunctionCheck =
asargent_no_longer_on_chrome 2016/05/06 17:09:04 nit: this could use a comment
Devlin 2016/05/06 22:13:47 Done.
26 base::Callback<void(const v8::FunctionCallbackInfo<v8::Value>&,
27 const v8::Local<v8::Context>&)>;
28
24 // Key for the base::Bound routed function. 29 // Key for the base::Bound routed function.
25 const char* kHandlerFunction = "handler_function"; 30 const char* kHandlerFunction = "handler_function";
26 const char* kFeatureName = "feature_name"; 31
32 // Checks whether a given |context| has any of the |allowed_features|. This
33 // treats an empty |allowed_features| as indicating that any context has access.
34 bool IsContextAllowed(const std::vector<std::string>& allowed_features,
35 const v8::Local<v8::Context>& context) {
36 // We can't access the ScriptContextSet on a worker thread. Luckily, we also
37 // don't inject many bindings into worker threads.
38 // TODO(devlin): Figure out a way around this.
39 if (content::WorkerThread::GetCurrentId() == 0)
40 return true;
41 if (allowed_features.empty())
42 return true;
43 ScriptContext* script_context =
44 ScriptContextSet::GetContextByV8Context(context);
45 // TODO(devlin): Eventually, we should fail if script_context is null.
46 if (!script_context)
47 return true;
48 for (const std::string& feature : allowed_features) {
49 if (script_context->GetAvailability(feature).is_available())
50 return true;
51 }
52
53 return false;
54 }
55
56 // Checks whether the given |context| has access to any of the necessary
57 // |allowed_features| and calls |function|.
58 void ValidateAndCall(const ObjectBackedNativeHandler::HandlerFunction& function,
59 const std::vector<std::string>& allowed_features,
60 const v8::FunctionCallbackInfo<v8::Value>& args,
61 const v8::Local<v8::Context>& context) {
62 if (!IsContextAllowed(allowed_features, context)) {
63 NOTREACHED();
64 return;
65 }
66 function.Run(args);
67 }
68
27 } // namespace 69 } // namespace
28 70
29 ObjectBackedNativeHandler::ObjectBackedNativeHandler(ScriptContext* context) 71 ObjectBackedNativeHandler::ObjectBackedNativeHandler(ScriptContext* context)
30 : router_data_(context->isolate()), 72 : router_data_(context->isolate()),
31 context_(context), 73 context_(context),
32 object_template_(context->isolate(), 74 object_template_(context->isolate(),
33 v8::ObjectTemplate::New(context->isolate())) { 75 v8::ObjectTemplate::New(context->isolate())) {
34 } 76 }
35 77
36 ObjectBackedNativeHandler::~ObjectBackedNativeHandler() { 78 ObjectBackedNativeHandler::~ObjectBackedNativeHandler() {
37 } 79 }
38 80
39 v8::Local<v8::Object> ObjectBackedNativeHandler::NewInstance() { 81 v8::Local<v8::Object> ObjectBackedNativeHandler::NewInstance() {
40 return v8::Local<v8::ObjectTemplate>::New(GetIsolate(), object_template_) 82 return v8::Local<v8::ObjectTemplate>::New(GetIsolate(), object_template_)
41 ->NewInstance(); 83 ->NewInstance();
42 } 84 }
43 85
44 // static 86 // static
45 void ObjectBackedNativeHandler::Router( 87 void ObjectBackedNativeHandler::Router(
46 const v8::FunctionCallbackInfo<v8::Value>& args) { 88 const v8::FunctionCallbackInfo<v8::Value>& args) {
47 v8::Isolate* isolate = args.GetIsolate(); 89 v8::Isolate* isolate = args.GetIsolate();
48 v8::HandleScope handle_scope(isolate); 90 v8::HandleScope handle_scope(isolate);
49 v8::Local<v8::Object> data = args.Data().As<v8::Object>(); 91 v8::Local<v8::Object> data = args.Data().As<v8::Object>();
50 v8::Local<v8::Context> context = isolate->GetCurrentContext(); 92 v8::Local<v8::Context> context = isolate->GetCurrentContext();
51 93
52 v8::Local<v8::Value> handler_function_value; 94 v8::Local<v8::Value> handler_function_value;
53 v8::Local<v8::Value> feature_name_value;
54 // See comment in header file for why we do this. 95 // See comment in header file for why we do this.
55 if (!GetPrivate(context, data, kHandlerFunction, &handler_function_value) || 96 if (!GetPrivate(context, data, kHandlerFunction, &handler_function_value) ||
56 handler_function_value->IsUndefined() || 97 handler_function_value->IsUndefined()) {
57 !GetPrivate(context, data, kFeatureName, &feature_name_value) ||
58 !feature_name_value->IsString()) {
59 ScriptContext* script_context = 98 ScriptContext* script_context =
60 ScriptContextSet::GetContextByV8Context(context); 99 ScriptContextSet::GetContextByV8Context(context);
61 console::Error(script_context ? script_context->GetRenderFrame() : nullptr, 100 console::Error(script_context ? script_context->GetRenderFrame() : nullptr,
62 "Extension view no longer exists"); 101 "Extension view no longer exists");
63 return; 102 return;
64 } 103 }
65 104
66 // We can't access the ScriptContextSet on a worker thread. Luckily, we also
67 // don't inject many bindings into worker threads.
68 // TODO(devlin): Figure out a way around this.
69 if (content::WorkerThread::GetCurrentId() == 0) {
70 ScriptContext* script_context =
71 ScriptContextSet::GetContextByV8Context(context);
72 v8::Local<v8::String> feature_name_string =
73 feature_name_value->ToString(context).ToLocalChecked();
74 std::string feature_name = *v8::String::Utf8Value(feature_name_string);
75 // TODO(devlin): Eventually, we should fail if either script_context is null
76 // or feature_name is empty.
77 if (script_context && !feature_name.empty()) {
78 Feature::Availability availability =
79 script_context->GetAvailability(feature_name);
80 if (!availability.is_available()) {
81 DVLOG(1) << feature_name
82 << " is not available: " << availability.message();
83 return;
84 }
85 }
86 }
87 // This CHECK is *important*. Otherwise, we'll go around happily executing 105 // This CHECK is *important*. Otherwise, we'll go around happily executing
88 // something random. See crbug.com/548273. 106 // something random. See crbug.com/548273.
89 CHECK(handler_function_value->IsExternal()); 107 CHECK(handler_function_value->IsExternal());
90 static_cast<HandlerFunction*>( 108 static_cast<HandlerFunctionCheck*>(
91 handler_function_value.As<v8::External>()->Value())->Run(args); 109 handler_function_value.As<v8::External>()->Value())->Run(args, context);
92 110
93 // Verify that the return value, if any, is accessible by the context. 111 // Verify that the return value, if any, is accessible by the context.
94 v8::ReturnValue<v8::Value> ret = args.GetReturnValue(); 112 v8::ReturnValue<v8::Value> ret = args.GetReturnValue();
95 v8::Local<v8::Value> ret_value = ret.Get(); 113 v8::Local<v8::Value> ret_value = ret.Get();
96 if (ret_value->IsObject() && !ret_value->IsNull() && 114 if (ret_value->IsObject() && !ret_value->IsNull() &&
97 !ContextCanAccessObject(context, v8::Local<v8::Object>::Cast(ret_value), 115 !ContextCanAccessObject(context, v8::Local<v8::Object>::Cast(ret_value),
98 true)) { 116 true)) {
99 NOTREACHED() << "Insecure return value"; 117 NOTREACHED() << "Insecure return value";
100 ret.SetUndefined(); 118 ret.SetUndefined();
101 } 119 }
102 } 120 }
103 121
104 void ObjectBackedNativeHandler::RouteFunction( 122 void ObjectBackedNativeHandler::RouteFunction(
105 const std::string& name, 123 const std::string& name,
106 const HandlerFunction& handler_function) { 124 const HandlerFunction& handler_function) {
107 RouteFunction(name, "", handler_function); 125 RouteFunction(name, std::vector<std::string>(), handler_function);
108 } 126 }
109 127
110 void ObjectBackedNativeHandler::RouteFunction( 128 void ObjectBackedNativeHandler::RouteFunction(
111 const std::string& name, 129 const std::string& name,
112 const std::string& feature_name, 130 const std::string& feature_name,
113 const HandlerFunction& handler_function) { 131 const HandlerFunction& handler_function) {
132 RouteFunction(
133 name, std::vector<std::string>(1, feature_name), handler_function);
134 }
135
136 void ObjectBackedNativeHandler::RouteFunction(
137 const std::string& name,
138 const std::vector<std::string>& features,
139 const HandlerFunction& handler_function) {
114 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 140 v8::Isolate* isolate = v8::Isolate::GetCurrent();
115 v8::HandleScope handle_scope(isolate); 141 v8::HandleScope handle_scope(isolate);
116 v8::Context::Scope context_scope(context_->v8_context()); 142 v8::Context::Scope context_scope(context_->v8_context());
117 143
118 v8::Local<v8::Object> data = v8::Object::New(isolate); 144 v8::Local<v8::Object> data = v8::Object::New(isolate);
145 HandlerFunctionCheck check =
146 base::Bind(&ValidateAndCall, handler_function, features);
Devlin 2016/05/05 22:20:22 This callback trickery struck me as easier than st
119 SetPrivate(data, kHandlerFunction, 147 SetPrivate(data, kHandlerFunction,
120 v8::External::New(isolate, new HandlerFunction(handler_function))); 148 v8::External::New(isolate, new HandlerFunctionCheck(check)));
121 DCHECK(feature_name.empty() ||
122 ExtensionAPI::GetSharedInstance()->GetFeatureDependency(feature_name))
123 << feature_name;
124 SetPrivate(data, kFeatureName,
125 v8_helpers::ToV8StringUnsafe(isolate, feature_name));
126 v8::Local<v8::FunctionTemplate> function_template = 149 v8::Local<v8::FunctionTemplate> function_template =
127 v8::FunctionTemplate::New(isolate, Router, data); 150 v8::FunctionTemplate::New(isolate, Router, data);
128 v8::Local<v8::ObjectTemplate>::New(isolate, object_template_) 151 v8::Local<v8::ObjectTemplate>::New(isolate, object_template_)
129 ->Set(isolate, name.c_str(), function_template); 152 ->Set(isolate, name.c_str(), function_template);
130 router_data_.Append(data); 153 router_data_.Append(data);
131 } 154 }
132 155
133 v8::Isolate* ObjectBackedNativeHandler::GetIsolate() const { 156 v8::Isolate* ObjectBackedNativeHandler::GetIsolate() const {
134 return context_->isolate(); 157 return context_->isolate();
135 } 158 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 v8::Local<v8::Object> obj, 240 v8::Local<v8::Object> obj,
218 const char* key) { 241 const char* key) {
219 obj->DeletePrivate(context, 242 obj->DeletePrivate(context,
220 v8::Private::ForApi( 243 v8::Private::ForApi(
221 context->GetIsolate(), 244 context->GetIsolate(),
222 v8::String::NewFromUtf8(context->GetIsolate(), key))) 245 v8::String::NewFromUtf8(context->GetIsolate(), key)))
223 .FromJust(); 246 .FromJust();
224 } 247 }
225 248
226 } // namespace extensions 249 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698