blob: 1532920a0d4c99e6a72e24e8542d3d3945aa41cb [file] [log] [blame]
[email protected]f55c90ee62014-04-12 00:50:031// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]4f1633f2013-03-09 14:26:242// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f55c90ee62014-04-12 00:50:035#ifndef EXTENSIONS_RENDERER_OBJECT_BACKED_NATIVE_HANDLER_H_
6#define EXTENSIONS_RENDERER_OBJECT_BACKED_NATIVE_HANDLER_H_
[email protected]4f1633f2013-03-09 14:26:247
8#include <string>
9#include <vector>
10
11#include "base/bind.h"
avi2d124c02015-12-23 06:36:4212#include "base/macros.h"
[email protected]b8ce52f2014-04-04 22:45:1513#include "extensions/renderer/native_handler.h"
[email protected]b61750a2014-04-04 18:27:5314#include "v8/include/v8-util.h"
[email protected]4f1633f2013-03-09 14:26:2415#include "v8/include/v8.h"
16
17namespace extensions {
[email protected]f55c90ee62014-04-12 00:50:0318class ScriptContext;
[email protected]4f1633f2013-03-09 14:26:2419
20// An ObjectBackedNativeHandler is a factory for JS objects with functions on
Devlin Cronind9ea8342018-01-27 06:00:0421// them that map to native C++ functions. Subclasses should call
22// RouteHandlerFunction() in their constructor to define functions on the
23// created JS objects.
[email protected]4f1633f2013-03-09 14:26:2424class ObjectBackedNativeHandler : public NativeHandler {
25 public:
[email protected]f55c90ee62014-04-12 00:50:0326 explicit ObjectBackedNativeHandler(ScriptContext* context);
dcheng9168b2f2014-10-21 12:38:2427 ~ObjectBackedNativeHandler() override;
[email protected]4f1633f2013-03-09 14:26:2428
Devlin Cronind9ea8342018-01-27 06:00:0429 // NativeHandler:
30 void Initialize() final;
Devlin Cronin6fed7f02018-01-31 22:38:2031 bool IsInitialized() final;
[email protected]4f1633f2013-03-09 14:26:2432 // Create an object with bindings to the native functions defined through
Devlin Cronind9ea8342018-01-27 06:00:0433 // RouteHandlerFunction().
tfarinaf85316f2015-04-29 17:03:4034 v8::Local<v8::Object> NewInstance() override;
[email protected]4f1633f2013-03-09 14:26:2435
[email protected]2a356872014-02-21 23:18:5236 v8::Isolate* GetIsolate() const;
37
rdevlin.croninc827ac22016-05-09 14:17:4938 protected:
Devlin Cronincc02a0c2019-01-03 22:15:0739 using HandlerFunction =
40 base::RepeatingCallback<void(const v8::FunctionCallbackInfo<v8::Value>&)>;
[email protected]4f1633f2013-03-09 14:26:2441
Devlin Cronind9ea8342018-01-27 06:00:0442 virtual void AddRoutes() = 0;
43
[email protected]4f1633f2013-03-09 14:26:2444 // Installs a new 'route' from |name| to |handler_function|. This means that
45 // NewInstance()s of this ObjectBackedNativeHandler will have a property
46 // |name| which will be handled by |handler_function|.
kalmanb0c1c502015-04-15 00:25:0647 //
48 // Routed functions are destroyed along with the destruction of this class,
49 // and are never called back into, therefore it's safe for |handler_function|
50 // to bind to base::Unretained.
rdevlin.cronin14ff9d02016-04-05 20:56:5551 //
rdevlin.croninc827ac22016-05-09 14:17:4952 // |feature_name| corresponds to the api feature the native handler is used
rdevlin.cronin14ff9d02016-04-05 20:56:5553 // for. If the associated ScriptContext does not have access to that feature,
54 // the |handler_function| is not invoked.
55 // TODO(devlin): Deprecate the version that doesn't take a |feature_name|.
Devlin Cronind9ea8342018-01-27 06:00:0456 void RouteHandlerFunction(const std::string& name,
Devlin Cronincc02a0c2019-01-03 22:15:0757 HandlerFunction handler_function);
Devlin Cronind9ea8342018-01-27 06:00:0458 void RouteHandlerFunction(const std::string& name,
59 const std::string& feature_name,
Devlin Cronincc02a0c2019-01-03 22:15:0760 HandlerFunction handler_function);
[email protected]4f1633f2013-03-09 14:26:2461
[email protected]f55c90ee62014-04-12 00:50:0362 ScriptContext* context() const { return context_; }
[email protected]4f1633f2013-03-09 14:26:2463
dcheng9168b2f2014-10-21 12:38:2464 void Invalidate() override;
[email protected]4f1633f2013-03-09 14:26:2465
rdevlin.cronina794ae42016-04-15 18:05:1166 // Returns true if the given |context| is allowed to access the given
67 // |object|. This should be checked before returning any objects from another
68 // context.
69 // |allow_null_context| indicates that if there is no ScriptContext associated
70 // with the |object|, it should be allowed.
71 // TODO(devlin): It'd be nice to track down when when there's no ScriptContext
72 // and remove |allow_null_context|.
73 static bool ContextCanAccessObject(const v8::Local<v8::Context>& context,
74 const v8::Local<v8::Object>& object,
75 bool allow_null_context);
76
jochen300abe232015-11-06 21:17:5377 // The following methods are convenience wrappers for methods on v8::Object
78 // with the corresponding names.
79 void SetPrivate(v8::Local<v8::Object> obj,
80 const char* key,
81 v8::Local<v8::Value> value);
82 static void SetPrivate(v8::Local<v8::Context> context,
83 v8::Local<v8::Object> obj,
84 const char* key,
85 v8::Local<v8::Value> value);
86 bool GetPrivate(v8::Local<v8::Object> obj,
87 const char* key,
88 v8::Local<v8::Value>* result);
89 static bool GetPrivate(v8::Local<v8::Context> context,
90 v8::Local<v8::Object> obj,
91 const char* key,
92 v8::Local<v8::Value>* result);
93 void DeletePrivate(v8::Local<v8::Object> obj, const char* key);
94 static void DeletePrivate(v8::Local<v8::Context> context,
95 v8::Local<v8::Object> obj,
96 const char* key);
97
[email protected]4f1633f2013-03-09 14:26:2498 private:
Devlin Cronind9ea8342018-01-27 06:00:0499 // Callback for RouteHandlerFunction which routes the V8 call to the correct
[email protected]d876ffdf2013-03-14 03:40:26100 // base::Bound callback.
[email protected]d8c5fbb2013-06-14 11:35:25101 static void Router(const v8::FunctionCallbackInfo<v8::Value>& args);
[email protected]4f1633f2013-03-09 14:26:24102
Devlin Cronind9ea8342018-01-27 06:00:04103 enum InitState {
104 kUninitialized,
105 kInitializingRoutes,
106 kInitialized,
107 };
108 InitState init_state_ = kUninitialized;
109
110 // When RouteHandlerFunction is called we create a v8::Object to hold the data
111 // we need when handling it in Router() - this is the base::Bound function to
[email protected]d876ffdf2013-03-14 03:40:26112 // route to.
113 //
114 // We need a v8::Object because it's possible for v8 to outlive the
115 // base::Bound function; the lifetime of an ObjectBackedNativeHandler is the
116 // lifetime of webkit's involvement with it, not the life of the v8 context.
117 // A scenario when v8 will outlive us is if a frame holds onto the
118 // contentWindow of an iframe after it's removed.
119 //
120 // So, we use v8::Objects here to hold that data, effectively refcounting
121 // the data. When |this| is destroyed we remove the base::Bound function from
122 // the object to indicate that it shoudn't be called.
[email protected]b61750a2014-04-04 18:27:53123 typedef v8::PersistentValueVector<v8::Object> RouterData;
[email protected]d876ffdf2013-03-14 03:40:26124 RouterData router_data_;
[email protected]4f1633f2013-03-09 14:26:24125
[email protected]f55c90ee62014-04-12 00:50:03126 ScriptContext* context_;
[email protected]4f1633f2013-03-09 14:26:24127
kalman83292b82015-03-12 16:40:25128 v8::Global<v8::ObjectTemplate> object_template_;
[email protected]4f1633f2013-03-09 14:26:24129
130 DISALLOW_COPY_AND_ASSIGN(ObjectBackedNativeHandler);
131};
132
[email protected]1002d3432013-06-13 09:04:54133} // namespace extensions
[email protected]4f1633f2013-03-09 14:26:24134
[email protected]f55c90ee62014-04-12 00:50:03135#endif // EXTENSIONS_RENDERER_OBJECT_BACKED_NATIVE_HANDLER_H_