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
3 // found in the LICENSE file.
4 
5 #ifndef EXTENSIONS_RENDERER_BINDINGS_API_BINDING_HOOKS_H_
6 #define EXTENSIONS_RENDERER_BINDINGS_API_BINDING_HOOKS_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/macros.h"
12 #include "v8/include/v8.h"
13 
14 namespace extensions {
15 class APIBindingHooksDelegate;
16 class APITypeReferenceMap;
17 class APISignature;
18 
19 // A class to register custom hooks for given API calls that need different
20 // handling. An instance exists for a single API, but can be used across
21 // multiple contexts (but only on the same thread).
22 // TODO(devlin): We have both C++ and JS custom bindings, but this only allows
23 // for registration of C++ handlers. Add JS support.
24 class APIBindingHooks {
25  public:
26   // The result of checking for hooks to handle a request.
27   struct RequestResult {
28     enum ResultCode {
29       HANDLED,              // A custom hook handled the request.
30       ARGUMENTS_UPDATED,    // The arguments were updated post-validation.
31       THROWN,               // An exception was thrown during parsing or
32                             // handling.
33       INVALID_INVOCATION,   // The request was called with invalid arguments.
34                             // |error| will contain the invocation error.
35       CONTEXT_INVALIDATED,  // The context was invalidated during the handling
36                             // of the API. Ideally, this wouldn't happen, but
37                             // could in certain circumstances.
38       NOT_HANDLED,          // The request was not handled.
39     };
40 
41     explicit RequestResult(ResultCode code);
42     RequestResult(ResultCode code, v8::Local<v8::Function> custom_callback);
43     RequestResult(std::string invocation_error);
44     RequestResult(const RequestResult& other);
45     ~RequestResult();
46 
47     ResultCode code;
48     v8::Local<v8::Function> custom_callback;
49     v8::Local<v8::Value> return_value;  // Only valid if code == HANDLED.
50     std::string error;
51   };
52 
53   explicit APIBindingHooks(const std::string& api_name);
54   ~APIBindingHooks();
55 
56   // Looks for any custom hooks associated with the given request, and, if any
57   // are found, runs them. Returns the result of running the hooks, if any.
58   RequestResult RunHooks(const std::string& method_name,
59                          v8::Local<v8::Context> context,
60                          const APISignature* signature,
61                          std::vector<v8::Local<v8::Value>>* arguments,
62                          const APITypeReferenceMap& type_refs);
63 
64   // Returns a JS interface that can be used to register hooks.
65   v8::Local<v8::Object> GetJSHookInterface(v8::Local<v8::Context> context);
66 
67   // Gets the custom-set JS callback for the given method, if one exists.
68   v8::Local<v8::Function> GetCustomJSCallback(const std::string& method_name,
69                                               v8::Local<v8::Context> context);
70 
71   // Creates a new JS event for the given |event_name|, if a custom event is
72   // provided. Returns true if an event was created.
73   bool CreateCustomEvent(v8::Local<v8::Context> context,
74                          const std::string& event_name,
75                          v8::Local<v8::Value>* event_out);
76 
77   // Performs any extra initialization on the template.
78   void InitializeTemplate(v8::Isolate* isolate,
79                           v8::Local<v8::ObjectTemplate> object_template,
80                           const APITypeReferenceMap& type_refs);
81 
82   // Performs any extra initialization on an instance of the API.
83   void InitializeInstance(v8::Local<v8::Context> context,
84                           v8::Local<v8::Object> instance);
85 
86   void SetDelegate(std::unique_ptr<APIBindingHooksDelegate> delegate);
87 
88  private:
89   // Updates the |arguments| by running |function| and settings arguments to the
90   // returned result.
91   bool UpdateArguments(v8::Local<v8::Function> function,
92                        v8::Local<v8::Context> context,
93                        std::vector<v8::Local<v8::Value>>* arguments);
94 
95   // The name of the associated API.
96   std::string api_name_;
97 
98   std::unique_ptr<APIBindingHooksDelegate> delegate_;
99 
100   DISALLOW_COPY_AND_ASSIGN(APIBindingHooks);
101 };
102 
103 }  // namespace extensions
104 
105 #endif  // EXTENSIONS_RENDERER_BINDINGS_API_BINDING_HOOKS_H_
106