File: object_backed_native_handler.h

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (142 lines) | stat: -rw-r--r-- 5,715 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EXTENSIONS_RENDERER_OBJECT_BACKED_NATIVE_HANDLER_H_
#define EXTENSIONS_RENDERER_OBJECT_BACKED_NATIVE_HANDLER_H_

#include <string>
#include <vector>

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "extensions/renderer/native_handler.h"
#include "v8/include/v8-forward.h"
#include "v8/include/v8-persistent-handle.h"
#include "v8/include/v8-util.h"

namespace extensions {
class ScriptContext;

// An ObjectBackedNativeHandler is a factory for JS objects with functions on
// them that map to native C++ functions. Subclasses should call
// RouteHandlerFunction() in their constructor to define functions on the
// created JS objects.
class ObjectBackedNativeHandler : public NativeHandler {
 public:
  explicit ObjectBackedNativeHandler(ScriptContext* context);

  ObjectBackedNativeHandler(const ObjectBackedNativeHandler&) = delete;
  ObjectBackedNativeHandler& operator=(const ObjectBackedNativeHandler&) =
      delete;

  ~ObjectBackedNativeHandler() override;

  // NativeHandler:
  void Initialize() final;
  bool IsInitialized() final;
  // Create an object with bindings to the native functions defined through
  // RouteHandlerFunction().
  v8::Local<v8::Object> NewInstance() override;

  v8::Isolate* GetIsolate() const;

 protected:
  using HandlerFunction =
      base::RepeatingCallback<void(const v8::FunctionCallbackInfo<v8::Value>&)>;

  virtual void AddRoutes() = 0;

  // Installs a new 'route' from |name| to |handler_function|. This means that
  // NewInstance()s of this ObjectBackedNativeHandler will have a property
  // |name| which will be handled by |handler_function|.
  //
  // Routed functions are destroyed along with the destruction of this class,
  // and are never called back into, therefore it's safe for |handler_function|
  // to bind to base::Unretained.
  //
  // |feature_name| corresponds to the api feature the native handler is used
  // for. If the associated ScriptContext does not have access to that feature,
  // the |handler_function| is not invoked.
  // TODO(devlin): Deprecate the version that doesn't take a |feature_name|.
  void RouteHandlerFunction(const std::string& name,
                            HandlerFunction handler_function);
  void RouteHandlerFunction(const std::string& name,
                            const std::string& feature_name,
                            HandlerFunction handler_function);

  ScriptContext* context() const { return context_; }

  void Invalidate() override;

  // Returns true if the given |context| is allowed to access the given
  // |object|. This should be checked before returning any objects from another
  // context.
  // |allow_null_context| indicates that if there is no ScriptContext associated
  // with the |object|, it should be allowed.
  // TODO(devlin): It'd be nice to track down when when there's no ScriptContext
  // and remove |allow_null_context|.
  static bool ContextCanAccessObject(const v8::Local<v8::Context>& context,
                                     const v8::Local<v8::Object>& object,
                                     bool allow_null_context);

  // The following methods are convenience wrappers for methods on v8::Object
  // with the corresponding names.
  // Returns whether or not setting privates was successful.
  bool SetPrivate(v8::Local<v8::Object> obj,
                  const char* key,
                  v8::Local<v8::Value> value);
  static bool SetPrivate(v8::Local<v8::Context> context,
                         v8::Local<v8::Object> obj,
                         const char* key,
                         v8::Local<v8::Value> value);
  bool GetPrivate(v8::Local<v8::Object> obj,
                  const char* key,
                  v8::Local<v8::Value>* result);
  static bool GetPrivate(v8::Local<v8::Context> context,
                         v8::Local<v8::Object> obj,
                         const char* key,
                         v8::Local<v8::Value>* result);
  void DeletePrivate(v8::Local<v8::Object> obj, const char* key);
  static void DeletePrivate(v8::Local<v8::Context> context,
                            v8::Local<v8::Object> obj,
                            const char* key);

 private:
  // Callback for RouteHandlerFunction which routes the V8 call to the correct
  // base::Bound callback.
  static void Router(const v8::FunctionCallbackInfo<v8::Value>& args);

  enum InitState {
    kUninitialized,
    kInitializingRoutes,
    kInitialized,
  };
  InitState init_state_ = kUninitialized;

  // When RouteHandlerFunction is called we create a v8::Object to hold the data
  // we need when handling it in Router() - this is the base::Bound function to
  // route to.
  //
  // We need a v8::Object because it's possible for v8 to outlive the
  // base::Bound function; the lifetime of an ObjectBackedNativeHandler is the
  // lifetime of webkit's involvement with it, not the life of the v8 context.
  // A scenario when v8 will outlive us is if a frame holds onto the
  // contentWindow of an iframe after it's removed.
  //
  // So, we use v8::Objects here to hold that data as a weak reference. The
  // strong reference is stored in `handler_functions_`.
  using RouterData = std::vector<v8::Global<v8::Object>>;
  RouterData router_data_;

  // Owned list of HandlerFunctions.
  std::vector<std::unique_ptr<HandlerFunction>> handler_functions_;

  raw_ptr<ScriptContext, DanglingUntriaged> context_;

  v8::Global<v8::ObjectTemplate> object_template_;
};

}  // namespace extensions

#endif  // EXTENSIONS_RENDERER_OBJECT_BACKED_NATIVE_HANDLER_H_