| 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 "gin/arguments.h" | 10 #include "gin/arguments.h" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 } | 77 } |
| 78 | 78 |
| 79 v8::Isolate* isolate; | 79 v8::Isolate* isolate; |
| 80 | 80 |
| 81 std::map<std::string, v8::Global<v8::Object>> hook_interfaces; | 81 std::map<std::string, v8::Global<v8::Object>> hook_interfaces; |
| 82 }; | 82 }; |
| 83 | 83 |
| 84 gin::WrapperInfo JSHookInterface::kWrapperInfo = | 84 gin::WrapperInfo JSHookInterface::kWrapperInfo = |
| 85 {gin::kEmbedderNativeGin}; | 85 {gin::kEmbedderNativeGin}; |
| 86 | 86 |
| 87 // Creates and returns JS object for the hook interface to allow for | |
| 88 // registering custom hooks from JS. | |
| 89 v8::Local<v8::Object> CreateJSHookInterface(const std::string& api_name, | |
| 90 v8::Local<v8::Context> context) { | |
| 91 gin::PerContextData* per_context_data = gin::PerContextData::From(context); | |
| 92 DCHECK(per_context_data); | |
| 93 APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>( | |
| 94 per_context_data->GetUserData(kExtensionAPIHooksPerContextKey)); | |
| 95 if (!data) { | |
| 96 auto api_data = | |
| 97 base::MakeUnique<APIHooksPerContextData>(context->GetIsolate()); | |
| 98 data = api_data.get(); | |
| 99 per_context_data->SetUserData(kExtensionAPIHooksPerContextKey, | |
| 100 api_data.release()); | |
| 101 } | |
| 102 | |
| 103 DCHECK(data->hook_interfaces.find(api_name) == data->hook_interfaces.end()); | |
| 104 | |
| 105 gin::Handle<JSHookInterface> hooks = | |
| 106 gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name)); | |
| 107 CHECK(!hooks.IsEmpty()); | |
| 108 v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>(); | |
| 109 data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object); | |
| 110 | |
| 111 return hooks_object; | |
| 112 } | |
| 113 | |
| 114 } // namespace | 87 } // namespace |
| 115 | 88 |
| 116 APIBindingHooks::APIBindingHooks(const binding::RunJSFunction& run_js) | 89 APIBindingHooks::APIBindingHooks(const binding::RunJSFunction& run_js) |
| 117 : run_js_(run_js) {} | 90 : run_js_(run_js) {} |
| 118 APIBindingHooks::~APIBindingHooks() {} | 91 APIBindingHooks::~APIBindingHooks() {} |
| 119 | 92 |
| 120 void APIBindingHooks::RegisterHandleRequest(const std::string& method_name, | 93 void APIBindingHooks::RegisterHandleRequest(const std::string& method_name, |
| 121 const HandleRequestHook& hook) { | 94 const HandleRequestHook& hook) { |
| 122 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; | 95 DCHECK(!hooks_used_) << "Hooks must be registered before the first use!"; |
| 123 request_hooks_[method_name] = hook; | 96 request_hooks_[method_name] = hook; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 CHECK(hook_interface); | 134 CHECK(hook_interface); |
| 162 | 135 |
| 163 auto js_hook_iter = hook_interface->js_hooks()->find(method_name); | 136 auto js_hook_iter = hook_interface->js_hooks()->find(method_name); |
| 164 if (js_hook_iter == hook_interface->js_hooks()->end()) | 137 if (js_hook_iter == hook_interface->js_hooks()->end()) |
| 165 return false; | 138 return false; |
| 166 | 139 |
| 167 // Found a JS handler. | 140 // Found a JS handler. |
| 168 std::vector<v8::Local<v8::Value>> v8_args; | 141 std::vector<v8::Local<v8::Value>> v8_args; |
| 169 // TODO(devlin): Right now, this doesn't support exceptions or return values, | 142 // TODO(devlin): Right now, this doesn't support exceptions or return values, |
| 170 // which we will need to at some point. | 143 // which we will need to at some point. |
| 171 if (arguments->GetRemaining(&v8_args)) { | 144 if (arguments->Length() == 0 || arguments->GetRemaining(&v8_args)) { |
| 172 v8::Local<v8::Function> handler = | 145 v8::Local<v8::Function> handler = |
| 173 js_hook_iter->second.Get(context->GetIsolate()); | 146 js_hook_iter->second.Get(context->GetIsolate()); |
| 174 run_js_.Run(handler, context, v8_args.size(), v8_args.data()); | 147 run_js_.Run(handler, context, v8_args.size(), v8_args.data()); |
| 175 } | 148 } |
| 176 | 149 |
| 177 return true; | 150 return true; |
| 178 } | 151 } |
| 179 | 152 |
| 180 void APIBindingHooks::InitializeInContext( | 153 void APIBindingHooks::InitializeInContext( |
| 181 v8::Local<v8::Context> context, | 154 v8::Local<v8::Context> context, |
| 182 const std::string& api_name) { | 155 const std::string& api_name) { |
| 183 if (js_hooks_source_.IsEmpty()) | 156 if (js_hooks_source_.IsEmpty()) |
| 184 return; | 157 return; |
| 185 | 158 |
| 186 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); | 159 v8::Local<v8::String> source = js_hooks_source_.Get(context->GetIsolate()); |
| 187 v8::Local<v8::String> resource_name = | 160 v8::Local<v8::String> resource_name = |
| 188 js_resource_name_.Get(context->GetIsolate()); | 161 js_resource_name_.Get(context->GetIsolate()); |
| 189 v8::Local<v8::Script> script; | 162 v8::Local<v8::Script> script; |
| 190 v8::ScriptOrigin origin(resource_name); | 163 v8::ScriptOrigin origin(resource_name); |
| 191 if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) | 164 if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) |
| 192 return; | 165 return; |
| 193 v8::Local<v8::Value> func_as_value = script->Run(); | 166 v8::Local<v8::Value> func_as_value = script->Run(); |
| 194 v8::Local<v8::Function> function; | 167 v8::Local<v8::Function> function; |
| 195 if (!gin::ConvertFromV8(context->GetIsolate(), func_as_value, &function)) | 168 if (!gin::ConvertFromV8(context->GetIsolate(), func_as_value, &function)) |
| 196 return; | 169 return; |
| 197 v8::Local<v8::Object> api_hooks = CreateJSHookInterface(api_name, context); | 170 v8::Local<v8::Value> api_hooks = GetJSHookInterface(api_name, context); |
| 198 v8::Local<v8::Value> args[] = {api_hooks}; | 171 v8::Local<v8::Value> args[] = {api_hooks}; |
| 199 run_js_.Run(function, context, arraysize(args), args); | 172 run_js_.Run(function, context, arraysize(args), args); |
| 200 } | 173 } |
| 201 | 174 |
| 175 v8::Local<v8::Object> APIBindingHooks::GetJSHookInterface( |
| 176 const std::string& api_name, |
| 177 v8::Local<v8::Context> context) { |
| 178 gin::PerContextData* per_context_data = gin::PerContextData::From(context); |
| 179 DCHECK(per_context_data); |
| 180 APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>( |
| 181 per_context_data->GetUserData(kExtensionAPIHooksPerContextKey)); |
| 182 if (!data) { |
| 183 auto api_data = |
| 184 base::MakeUnique<APIHooksPerContextData>(context->GetIsolate()); |
| 185 data = api_data.get(); |
| 186 per_context_data->SetUserData(kExtensionAPIHooksPerContextKey, |
| 187 api_data.release()); |
| 188 } |
| 189 |
| 190 auto iter = data->hook_interfaces.find(api_name); |
| 191 if (iter != data->hook_interfaces.end()) |
| 192 return iter->second.Get(context->GetIsolate()); |
| 193 |
| 194 gin::Handle<JSHookInterface> hooks = |
| 195 gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name)); |
| 196 CHECK(!hooks.IsEmpty()); |
| 197 v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>(); |
| 198 data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object); |
| 199 |
| 200 return hooks_object; |
| 201 } |
| 202 |
| 202 } // namespace extensions | 203 } // namespace extensions |
| OLD | NEW |