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

Unified Diff: extensions/renderer/api_binding_hooks.cc

Issue 2947463002: [Extensions Bindings] Add a bindings/ subdirectory under renderer (Closed)
Patch Set: . Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « extensions/renderer/api_binding_hooks.h ('k') | extensions/renderer/api_binding_hooks_delegate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/api_binding_hooks.cc
diff --git a/extensions/renderer/api_binding_hooks.cc b/extensions/renderer/api_binding_hooks.cc
deleted file mode 100644
index 03d14190cc13b17a9e3df90d5d0f9aadb4089251..0000000000000000000000000000000000000000
--- a/extensions/renderer/api_binding_hooks.cc
+++ /dev/null
@@ -1,377 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/renderer/api_binding_hooks.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/supports_user_data.h"
-#include "extensions/renderer/api_binding_hooks_delegate.h"
-#include "extensions/renderer/api_signature.h"
-#include "gin/arguments.h"
-#include "gin/handle.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_context_data.h"
-#include "gin/wrappable.h"
-
-namespace extensions {
-
-namespace {
-
-// An interface to allow for registration of custom hooks from JavaScript.
-// Contains registered hooks for a single API.
-class JSHookInterface final : public gin::Wrappable<JSHookInterface> {
- public:
- explicit JSHookInterface(const std::string& api_name)
- : api_name_(api_name) {}
-
- static gin::WrapperInfo kWrapperInfo;
-
- // gin::Wrappable:
- gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) override {
- return Wrappable<JSHookInterface>::GetObjectTemplateBuilder(isolate)
- .SetMethod("setHandleRequest", &JSHookInterface::SetHandleRequest)
- .SetMethod("setUpdateArgumentsPreValidate",
- &JSHookInterface::SetUpdateArgumentsPreValidate)
- .SetMethod("setUpdateArgumentsPostValidate",
- &JSHookInterface::SetUpdateArgumentsPostValidate)
- .SetMethod("setCustomCallback", &JSHookInterface::SetCustomCallback);
- }
-
- void ClearHooks() {
- handle_request_hooks_.clear();
- pre_validation_hooks_.clear();
- post_validation_hooks_.clear();
- }
-
- v8::Local<v8::Function> GetHandleRequestHook(const std::string& method_name,
- v8::Isolate* isolate) const {
- return GetHookFromMap(handle_request_hooks_, method_name, isolate);
- }
-
- v8::Local<v8::Function> GetPreValidationHook(const std::string& method_name,
- v8::Isolate* isolate) const {
- return GetHookFromMap(pre_validation_hooks_, method_name, isolate);
- }
-
- v8::Local<v8::Function> GetPostValidationHook(const std::string& method_name,
- v8::Isolate* isolate) const {
- return GetHookFromMap(post_validation_hooks_, method_name, isolate);
- }
-
- v8::Local<v8::Function> GetCustomCallback(const std::string& method_name,
- v8::Isolate* isolate) const {
- return GetHookFromMap(custom_callback_hooks_, method_name, isolate);
- }
-
- private:
- using JSHooks = std::map<std::string, v8::Global<v8::Function>>;
-
- v8::Local<v8::Function> GetHookFromMap(const JSHooks& map,
- const std::string& method_name,
- v8::Isolate* isolate) const {
- auto iter = map.find(method_name);
- if (iter == map.end())
- return v8::Local<v8::Function>();
- return iter->second.Get(isolate);
- }
-
- void AddHookToMap(JSHooks* map,
- v8::Isolate* isolate,
- const std::string& method_name,
- v8::Local<v8::Function> hook) {
- std::string qualified_method_name =
- base::StringPrintf("%s.%s", api_name_.c_str(), method_name.c_str());
- v8::Global<v8::Function>& entry = (*map)[qualified_method_name];
- if (!entry.IsEmpty()) {
- NOTREACHED() << "Hooks can only be set once.";
- return;
- }
- entry.Reset(isolate, hook);
- }
-
- // Adds a hook to handle the implementation of the API method.
- void SetHandleRequest(v8::Isolate* isolate,
- const std::string& method_name,
- v8::Local<v8::Function> hook) {
- AddHookToMap(&handle_request_hooks_, isolate, method_name, hook);
- }
-
- // Adds a hook to update the arguments passed to the API method before we do
- // any kind of validation.
- void SetUpdateArgumentsPreValidate(v8::Isolate* isolate,
- const std::string& method_name,
- v8::Local<v8::Function> hook) {
- AddHookToMap(&pre_validation_hooks_, isolate, method_name, hook);
- }
-
- void SetUpdateArgumentsPostValidate(v8::Isolate* isolate,
- const std::string& method_name,
- v8::Local<v8::Function> hook) {
- AddHookToMap(&post_validation_hooks_, isolate, method_name, hook);
- }
-
- void SetCustomCallback(v8::Isolate* isolate,
- const std::string& method_name,
- v8::Local<v8::Function> hook) {
- AddHookToMap(&custom_callback_hooks_, isolate, method_name, hook);
- }
-
- std::string api_name_;
-
- JSHooks handle_request_hooks_;
- JSHooks pre_validation_hooks_;
- JSHooks post_validation_hooks_;
- JSHooks custom_callback_hooks_;
-
- DISALLOW_COPY_AND_ASSIGN(JSHookInterface);
-};
-
-const char kExtensionAPIHooksPerContextKey[] = "extension_api_hooks";
-
-struct APIHooksPerContextData : public base::SupportsUserData::Data {
- APIHooksPerContextData(v8::Isolate* isolate) : isolate(isolate) {}
- ~APIHooksPerContextData() override {
- v8::HandleScope scope(isolate);
- for (const auto& pair : hook_interfaces) {
- // We explicitly clear the hook data map here to remove all references to
- // v8 objects in order to avoid cycles.
- JSHookInterface* hooks = nullptr;
- gin::Converter<JSHookInterface*>::FromV8(
- isolate, pair.second.Get(isolate), &hooks);
- CHECK(hooks);
- hooks->ClearHooks();
- }
- }
-
- v8::Isolate* isolate;
-
- std::map<std::string, v8::Global<v8::Object>> hook_interfaces;
-};
-
-gin::WrapperInfo JSHookInterface::kWrapperInfo =
- {gin::kEmbedderNativeGin};
-
-// Gets the v8::Object of the JSHookInterface, optionally creating it if it
-// doesn't exist.
-v8::Local<v8::Object> GetJSHookInterfaceObject(
- const std::string& api_name,
- v8::Local<v8::Context> context,
- bool should_create) {
- gin::PerContextData* per_context_data = gin::PerContextData::From(context);
- DCHECK(per_context_data);
- APIHooksPerContextData* data = static_cast<APIHooksPerContextData*>(
- per_context_data->GetUserData(kExtensionAPIHooksPerContextKey));
- if (!data) {
- if (!should_create)
- return v8::Local<v8::Object>();
-
- auto api_data =
- base::MakeUnique<APIHooksPerContextData>(context->GetIsolate());
- data = api_data.get();
- per_context_data->SetUserData(kExtensionAPIHooksPerContextKey,
- std::move(api_data));
- }
-
- auto iter = data->hook_interfaces.find(api_name);
- if (iter != data->hook_interfaces.end())
- return iter->second.Get(context->GetIsolate());
-
- if (!should_create)
- return v8::Local<v8::Object>();
-
- gin::Handle<JSHookInterface> hooks =
- gin::CreateHandle(context->GetIsolate(), new JSHookInterface(api_name));
- CHECK(!hooks.IsEmpty());
- v8::Local<v8::Object> hooks_object = hooks.ToV8().As<v8::Object>();
- data->hook_interfaces[api_name].Reset(context->GetIsolate(), hooks_object);
-
- return hooks_object;
-}
-
-} // namespace
-
-APIBindingHooks::RequestResult::RequestResult(ResultCode code) : code(code) {}
-APIBindingHooks::RequestResult::RequestResult(
- ResultCode code,
- v8::Local<v8::Function> custom_callback)
- : code(code), custom_callback(custom_callback) {}
-APIBindingHooks::RequestResult::RequestResult(std::string invocation_error)
- : code(INVALID_INVOCATION), error(std::move(invocation_error)) {}
-APIBindingHooks::RequestResult::~RequestResult() {}
-APIBindingHooks::RequestResult::RequestResult(const RequestResult& other) =
- default;
-
-APIBindingHooks::APIBindingHooks(const std::string& api_name,
- const binding::RunJSFunctionSync& run_js)
- : api_name_(api_name), run_js_(run_js) {}
-APIBindingHooks::~APIBindingHooks() {}
-
-APIBindingHooks::RequestResult APIBindingHooks::RunHooks(
- const std::string& method_name,
- v8::Local<v8::Context> context,
- const APISignature* signature,
- std::vector<v8::Local<v8::Value>>* arguments,
- const APITypeReferenceMap& type_refs) {
- // Easy case: a native custom hook.
- if (delegate_) {
- RequestResult result = delegate_->HandleRequest(
- method_name, signature, context, arguments, type_refs);
- if (result.code != RequestResult::NOT_HANDLED)
- return result;
- }
-
- // Harder case: looking up a custom hook registered on the context (since
- // these are JS, each context has a separate instance).
- v8::Local<v8::Object> hook_interface_object =
- GetJSHookInterfaceObject(api_name_, context, false);
- if (hook_interface_object.IsEmpty())
- return RequestResult(RequestResult::NOT_HANDLED);
-
- v8::Isolate* isolate = context->GetIsolate();
-
- JSHookInterface* hook_interface = nullptr;
- gin::Converter<JSHookInterface*>::FromV8(
- isolate,
- hook_interface_object, &hook_interface);
- CHECK(hook_interface);
-
- v8::Local<v8::Function> pre_validate_hook =
- hook_interface->GetPreValidationHook(method_name, isolate);
- v8::TryCatch try_catch(isolate);
- if (!pre_validate_hook.IsEmpty()) {
- // TODO(devlin): What to do with the result of this function call? Can it
- // only fail in the case we've already thrown?
- UpdateArguments(pre_validate_hook, context, arguments);
- if (try_catch.HasCaught()) {
- try_catch.ReThrow();
- return RequestResult(RequestResult::THROWN);
- }
- }
-
- v8::Local<v8::Function> post_validate_hook =
- hook_interface->GetPostValidationHook(method_name, isolate);
- v8::Local<v8::Function> handle_request =
- hook_interface->GetHandleRequestHook(method_name, isolate);
- v8::Local<v8::Function> custom_callback =
- hook_interface->GetCustomCallback(method_name, isolate);
-
- // If both the post validation hook and the handle request hook are empty,
- // we're done...
- if (post_validate_hook.IsEmpty() && handle_request.IsEmpty())
- return RequestResult(RequestResult::NOT_HANDLED, custom_callback);
-
- {
- // ... otherwise, we have to validate the arguments.
- std::vector<v8::Local<v8::Value>> parsed_v8_args;
- std::string error;
- bool success = signature->ParseArgumentsToV8(context, *arguments, type_refs,
- &parsed_v8_args, &error);
- if (try_catch.HasCaught()) {
- try_catch.ReThrow();
- return RequestResult(RequestResult::THROWN);
- }
- if (!success)
- return RequestResult(std::move(error));
- arguments->swap(parsed_v8_args);
- }
-
- bool updated_args = false;
- if (!post_validate_hook.IsEmpty()) {
- updated_args = true;
- UpdateArguments(post_validate_hook, context, arguments);
- if (try_catch.HasCaught()) {
- try_catch.ReThrow();
- return RequestResult(RequestResult::THROWN);
- }
- }
-
- if (handle_request.IsEmpty()) {
- RequestResult::ResultCode result = updated_args
- ? RequestResult::ARGUMENTS_UPDATED
- : RequestResult::NOT_HANDLED;
- return RequestResult(result, custom_callback);
- }
-
- v8::Global<v8::Value> global_result =
- run_js_.Run(handle_request, context, arguments->size(),
- arguments->data());
- if (try_catch.HasCaught()) {
- try_catch.ReThrow();
- return RequestResult(RequestResult::THROWN);
- }
- RequestResult result(RequestResult::HANDLED, custom_callback);
- if (!global_result.IsEmpty())
- result.return_value = global_result.Get(isolate);
- return result;
-}
-
-v8::Local<v8::Object> APIBindingHooks::GetJSHookInterface(
- v8::Local<v8::Context> context) {
- return GetJSHookInterfaceObject(api_name_, context, true);
-}
-
-v8::Local<v8::Function> APIBindingHooks::GetCustomJSCallback(
- const std::string& name,
- v8::Local<v8::Context> context) {
- v8::Local<v8::Object> hooks =
- GetJSHookInterfaceObject(api_name_, context, false);
- if (hooks.IsEmpty())
- return v8::Local<v8::Function>();
- JSHookInterface* hook_interface = nullptr;
- gin::Converter<JSHookInterface*>::FromV8(context->GetIsolate(), hooks,
- &hook_interface);
- CHECK(hook_interface);
-
- return hook_interface->GetCustomCallback(name, context->GetIsolate());
-}
-
-bool APIBindingHooks::CreateCustomEvent(v8::Local<v8::Context> context,
- const std::string& event_name,
- v8::Local<v8::Value>* event_out) {
- return delegate_ &&
- delegate_->CreateCustomEvent(context, run_js_, event_name, event_out);
-}
-
-void APIBindingHooks::InitializeTemplate(
- v8::Isolate* isolate,
- v8::Local<v8::ObjectTemplate> object_template,
- const APITypeReferenceMap& type_refs) {
- if (delegate_)
- delegate_->InitializeTemplate(isolate, object_template, type_refs);
-}
-
-void APIBindingHooks::SetDelegate(
- std::unique_ptr<APIBindingHooksDelegate> delegate) {
- delegate_ = std::move(delegate);
-}
-
-bool APIBindingHooks::UpdateArguments(
- v8::Local<v8::Function> function,
- v8::Local<v8::Context> context,
- std::vector<v8::Local<v8::Value>>* arguments) {
- v8::Global<v8::Value> global_result;
- {
- v8::TryCatch try_catch(context->GetIsolate());
- global_result = run_js_.Run(function, context,
- arguments->size(), arguments->data());
- if (try_catch.HasCaught()) {
- try_catch.ReThrow();
- return false;
- }
- }
- DCHECK(!global_result.IsEmpty());
- v8::Local<v8::Value> result = global_result.Get(context->GetIsolate());
- std::vector<v8::Local<v8::Value>> new_args;
- if (result.IsEmpty() ||
- !gin::Converter<std::vector<v8::Local<v8::Value>>>::FromV8(
- context->GetIsolate(), result, &new_args)) {
- return false;
- }
- arguments->swap(new_args);
- return true;
-}
-
-} // namespace extensions
« no previous file with comments | « extensions/renderer/api_binding_hooks.h ('k') | extensions/renderer/api_binding_hooks_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698