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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; | 96 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; |
96 request_hooks_[method_name] = hook; | 97 request_hooks_[method_name] = hook; |
97 } | 98 } |
98 | 99 |
99 void APIBindingHooks::RegisterJsSource(v8::Global<v8::String> source, | 100 void APIBindingHooks::RegisterJsSource(v8::Global<v8::String> source, |
100 v8::Global<v8::String> resource_name) { | 101 v8::Global<v8::String> resource_name) { |
101 js_hooks_source_ = std::move(source); | 102 js_hooks_source_ = std::move(source); |
102 js_resource_name_ = std::move(resource_name); | 103 js_resource_name_ = std::move(resource_name); |
103 } | 104 } |
104 | 105 |
105 bool APIBindingHooks::HandleRequest(const std::string& api_name, | 106 APIBindingHooks::RequestResult APIBindingHooks::HandleRequest( |
106 const std::string& method_name, | 107 const std::string& api_name, |
107 v8::Local<v8::Context> context, | 108 const std::string& method_name, |
108 const APISignature* signature, | 109 v8::Local<v8::Context> context, |
109 gin::Arguments* arguments) { | 110 const APISignature* signature, |
| 111 gin::Arguments* arguments, |
| 112 const ArgumentSpec::RefMap& type_refs) { |
110 // Easy case: a native custom hook. | 113 // Easy case: a native custom hook. |
111 auto request_hooks_iter = request_hooks_.find(method_name); | 114 auto request_hooks_iter = request_hooks_.find(method_name); |
112 if (request_hooks_iter != request_hooks_.end()) { | 115 if (request_hooks_iter != request_hooks_.end()) { |
113 request_hooks_iter->second.Run(signature, arguments); | 116 RequestResult result = |
114 return true; | 117 request_hooks_iter->second.Run(signature, arguments, type_refs); |
| 118 // Right now, it doesn't make sense to register a request handler that |
| 119 // doesn't handle the request. |
| 120 DCHECK_NE(RequestResult::NOT_HANDLED, result); |
| 121 return result; |
115 } | 122 } |
116 | 123 |
117 // Harder case: looking up a custom hook registered on the context (since | 124 // Harder case: looking up a custom hook registered on the context (since |
118 // these are JS, each context has a separate instance). | 125 // these are JS, each context has a separate instance). |
119 gin::PerContextData* per_context_data = gin::PerContextData::From(context); | 126 gin::PerContextData* per_context_data = gin::PerContextData::From(context); |
120 DCHECK(per_context_data); | 127 DCHECK(per_context_data); |
121 APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>( | 128 APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>( |
122 per_context_data->GetUserData(kExtensionAPIHooksPerContextKey)); | 129 per_context_data->GetUserData(kExtensionAPIHooksPerContextKey)); |
123 if (!data) | 130 if (!data) |
124 return false; | 131 return RequestResult::NOT_HANDLED; |
125 | 132 |
126 auto hook_interface_iter = data->hook_interfaces.find(api_name); | 133 auto hook_interface_iter = data->hook_interfaces.find(api_name); |
127 if (hook_interface_iter == data->hook_interfaces.end()) | 134 if (hook_interface_iter == data->hook_interfaces.end()) |
128 return false; | 135 return RequestResult::NOT_HANDLED; |
129 | 136 |
130 JSHookInterface* hook_interface = nullptr; | 137 JSHookInterface* hook_interface = nullptr; |
131 gin::Converter<JSHookInterface*>::FromV8( | 138 gin::Converter<JSHookInterface*>::FromV8( |
132 context->GetIsolate(), | 139 context->GetIsolate(), |
133 hook_interface_iter->second.Get(context->GetIsolate()), &hook_interface); | 140 hook_interface_iter->second.Get(context->GetIsolate()), &hook_interface); |
134 CHECK(hook_interface); | 141 CHECK(hook_interface); |
135 | 142 |
136 auto js_hook_iter = hook_interface->js_hooks()->find(method_name); | 143 auto js_hook_iter = hook_interface->js_hooks()->find(method_name); |
137 if (js_hook_iter == hook_interface->js_hooks()->end()) | 144 if (js_hook_iter == hook_interface->js_hooks()->end()) |
138 return false; | 145 return RequestResult::NOT_HANDLED; |
139 | 146 |
140 // Found a JS handler. | 147 // Found a JS handler. |
141 std::vector<v8::Local<v8::Value>> v8_args; | 148 std::vector<v8::Local<v8::Value>> v8_args; |
| 149 std::string error; |
| 150 if (!signature->ParseArgumentsToV8(arguments, type_refs, &v8_args, &error)) |
| 151 return RequestResult::INVALID_INVOCATION; |
| 152 |
142 // TODO(devlin): Right now, this doesn't support exceptions or return values, | 153 // TODO(devlin): Right now, this doesn't support exceptions or return values, |
143 // which we will need to at some point. | 154 // which we will need to at some point. |
144 if (arguments->Length() == 0 || arguments->GetRemaining(&v8_args)) { | 155 v8::Local<v8::Function> handler = |
145 v8::Local<v8::Function> handler = | 156 js_hook_iter->second.Get(context->GetIsolate()); |
146 js_hook_iter->second.Get(context->GetIsolate()); | 157 run_js_.Run(handler, context, v8_args.size(), v8_args.data()); |
147 run_js_.Run(handler, context, v8_args.size(), v8_args.data()); | |
148 } | |
149 | 158 |
150 return true; | 159 return RequestResult::HANDLED; |
151 } | 160 } |
152 | 161 |
153 void APIBindingHooks::InitializeInContext( | 162 void APIBindingHooks::InitializeInContext( |
154 v8::Local<v8::Context> context, | 163 v8::Local<v8::Context> context, |
155 const std::string& api_name) { | 164 const std::string& api_name) { |
156 if (js_hooks_source_.IsEmpty()) | 165 if (js_hooks_source_.IsEmpty()) |
157 return; | 166 return; |
158 | 167 |
159 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); | 168 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); |
160 v8::Local<v8::String> resource_name = | 169 v8::Local<v8::String> resource_name = |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 gin::Handle<JSHookInterface> hooks = | 203 gin::Handle<JSHookInterface> hooks = |
195 gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name)); | 204 gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name)); |
196 CHECK(!hooks.IsEmpty()); | 205 CHECK(!hooks.IsEmpty()); |
197 v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>(); | 206 v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>(); |
198 data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object); | 207 data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object); |
199 | 208 |
200 return hooks_object; | 209 return hooks_object; |
201 } | 210 } |
202 | 211 |
203 } // namespace extensions | 212 } // namespace extensions |
OLD | NEW |