OLD | NEW |
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/api_binding_hooks.h" | 5 #include "extensions/renderer/api_binding_hooks.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/supports_user_data.h" | 9 #include "base/supports_user_data.h" |
| 10 #include "extensions/renderer/api_signature.h" |
10 #include "gin/arguments.h" | 11 #include "gin/arguments.h" |
11 #include "gin/handle.h" | 12 #include "gin/handle.h" |
12 #include "gin/object_template_builder.h" | 13 #include "gin/object_template_builder.h" |
13 #include "gin/per_context_data.h" | 14 #include "gin/per_context_data.h" |
14 #include "gin/wrappable.h" | 15 #include "gin/wrappable.h" |
15 | 16 |
16 namespace extensions { | 17 namespace extensions { |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; | 123 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; |
123 request_hooks_[method_name] = hook; | 124 request_hooks_[method_name] = hook; |
124 } | 125 } |
125 | 126 |
126 void APIBindingHooks::RegisterJsSource(v8::Global<v8::String> source, | 127 void APIBindingHooks::RegisterJsSource(v8::Global<v8::String> source, |
127 v8::Global<v8::String> resource_name) { | 128 v8::Global<v8::String> resource_name) { |
128 js_hooks_source_ = std::move(source); | 129 js_hooks_source_ = std::move(source); |
129 js_resource_name_ = std::move(resource_name); | 130 js_resource_name_ = std::move(resource_name); |
130 } | 131 } |
131 | 132 |
132 bool APIBindingHooks::HandleRequest(const std::string& api_name, | 133 APIBindingHooks::RequestResult APIBindingHooks::HandleRequest( |
133 const std::string& method_name, | 134 const std::string& api_name, |
134 v8::Local<v8::Context> context, | 135 const std::string& method_name, |
135 const APISignature* signature, | 136 v8::Local<v8::Context> context, |
136 gin::Arguments* arguments) { | 137 const APISignature* signature, |
| 138 gin::Arguments* arguments, |
| 139 const ArgumentSpec::RefMap& type_refs) { |
137 // Easy case: a native custom hook. | 140 // Easy case: a native custom hook. |
138 auto request_hooks_iter = request_hooks_.find(method_name); | 141 auto request_hooks_iter = request_hooks_.find(method_name); |
139 if (request_hooks_iter != request_hooks_.end()) { | 142 if (request_hooks_iter != request_hooks_.end()) { |
140 request_hooks_iter->second.Run(signature, arguments); | 143 RequestResult result = |
141 return true; | 144 request_hooks_iter->second.Run(signature, arguments, type_refs); |
| 145 // Right now, it doesn't make sense to register a request handler that |
| 146 // doesn't handle the request. |
| 147 DCHECK_NE(RequestResult::NOT_HANDLED, result); |
| 148 return result; |
142 } | 149 } |
143 | 150 |
144 // Harder case: looking up a custom hook registered on the context (since | 151 // Harder case: looking up a custom hook registered on the context (since |
145 // these are JS, each context has a separate instance). | 152 // these are JS, each context has a separate instance). |
146 gin::PerContextData* per_context_data = gin::PerContextData::From(context); | 153 gin::PerContextData* per_context_data = gin::PerContextData::From(context); |
147 DCHECK(per_context_data); | 154 DCHECK(per_context_data); |
148 APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>( | 155 APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>( |
149 per_context_data->GetUserData(kExtensionAPIHooksPerContextKey)); | 156 per_context_data->GetUserData(kExtensionAPIHooksPerContextKey)); |
150 if (!data) | 157 if (!data) |
151 return false; | 158 return RequestResult::NOT_HANDLED; |
152 | 159 |
153 auto hook_interface_iter = data->hook_interfaces.find(api_name); | 160 auto hook_interface_iter = data->hook_interfaces.find(api_name); |
154 if (hook_interface_iter == data->hook_interfaces.end()) | 161 if (hook_interface_iter == data->hook_interfaces.end()) |
155 return false; | 162 return RequestResult::NOT_HANDLED; |
156 | 163 |
157 JSHookInterface* hook_interface = nullptr; | 164 JSHookInterface* hook_interface = nullptr; |
158 gin::Converter<JSHookInterface*>::FromV8( | 165 gin::Converter<JSHookInterface*>::FromV8( |
159 context->GetIsolate(), | 166 context->GetIsolate(), |
160 hook_interface_iter->second.Get(context->GetIsolate()), &hook_interface); | 167 hook_interface_iter->second.Get(context->GetIsolate()), &hook_interface); |
161 CHECK(hook_interface); | 168 CHECK(hook_interface); |
162 | 169 |
163 auto js_hook_iter = hook_interface->js_hooks()->find(method_name); | 170 auto js_hook_iter = hook_interface->js_hooks()->find(method_name); |
164 if (js_hook_iter == hook_interface->js_hooks()->end()) | 171 if (js_hook_iter == hook_interface->js_hooks()->end()) |
165 return false; | 172 return RequestResult::NOT_HANDLED; |
166 | 173 |
167 // Found a JS handler. | 174 // Found a JS handler. |
168 std::vector<v8::Local<v8::Value>> v8_args; | 175 std::vector<v8::Local<v8::Value>> v8_args; |
| 176 std::string error; |
| 177 if (!signature->ParseArgumentsToV8(arguments, type_refs, &v8_args, &error)) |
| 178 return RequestResult::INVALID_INVOCATION; |
| 179 |
169 // TODO(devlin): Right now, this doesn't support exceptions or return values, | 180 // TODO(devlin): Right now, this doesn't support exceptions or return values, |
170 // which we will need to at some point. | 181 // which we will need to at some point. |
171 if (arguments->GetRemaining(&v8_args)) { | 182 v8::Local<v8::Function> handler = |
172 v8::Local<v8::Function> handler = | 183 js_hook_iter->second.Get(context->GetIsolate()); |
173 js_hook_iter->second.Get(context->GetIsolate()); | 184 run_js_.Run(handler, context, v8_args.size(), v8_args.data()); |
174 run_js_.Run(handler, context, v8_args.size(), v8_args.data()); | |
175 } | |
176 | 185 |
177 return true; | 186 return RequestResult::HANDLED; |
178 } | 187 } |
179 | 188 |
180 void APIBindingHooks::InitializeInContext( | 189 void APIBindingHooks::InitializeInContext( |
181 v8::Local<v8::Context> context, | 190 v8::Local<v8::Context> context, |
182 const std::string& api_name) { | 191 const std::string& api_name) { |
183 if (js_hooks_source_.IsEmpty()) | 192 if (js_hooks_source_.IsEmpty()) |
184 return; | 193 return; |
185 | 194 |
186 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); | 195 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); |
187 v8::Local<v8::String> resource_name = | 196 v8::Local<v8::String> resource_name = |
188 js_resource_name_.Get(context->GetIsolate()); | 197 js_resource_name_.Get(context->GetIsolate()); |
189 v8::Local<v8::Script> script; | 198 v8::Local<v8::Script> script; |
190 v8::ScriptOrigin origin(resource_name); | 199 v8::ScriptOrigin origin(resource_name); |
191 if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) | 200 if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) |
192 return; | 201 return; |
193 v8::Local<v8::Value> func_as_value = script->Run(); | 202 v8::Local<v8::Value> func_as_value = script->Run(); |
194 v8::Local<v8::Function> function; | 203 v8::Local<v8::Function> function; |
195 if (!gin::ConvertFromV8(context->GetIsolate(), func_as_value, &function)) | 204 if (!gin::ConvertFromV8(context->GetIsolate(), func_as_value, &function)) |
196 return; | 205 return; |
197 v8::Local<v8::Object> api_hooks = CreateJSHookInterface(api_name, context); | 206 v8::Local<v8::Object> api_hooks = CreateJSHookInterface(api_name, context); |
198 v8::Local<v8::Value> args[] = {api_hooks}; | 207 v8::Local<v8::Value> args[] = {api_hooks}; |
199 run_js_.Run(function, context, arraysize(args), args); | 208 run_js_.Run(function, context, arraysize(args), args); |
200 } | 209 } |
201 | 210 |
202 } // namespace extensions | 211 } // namespace extensions |
OLD | NEW |