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
|
// Copyright 2017 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_BINDINGS_JS_RUNNER_H_
#define EXTENSIONS_RENDERER_BINDINGS_JS_RUNNER_H_
#include <memory>
#include <optional>
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "v8/include/v8.h"
namespace base {
class Value;
}
namespace extensions {
// A helper class to execute JS functions safely.
class JSRunner {
public:
// Returns the instance of the JSRunner for the specified `context`.
static JSRunner* Get(v8::Local<v8::Context> context);
// Sets the instance for a given `context`.
static void SetInstanceForContext(v8::Local<v8::Context> context,
std::unique_ptr<JSRunner> runner);
// Clears the instance for a given `context`.
static void ClearInstanceForContext(v8::Local<v8::Context> context);
virtual ~JSRunner() {}
// Called with the result of executing the function, as well as the context
// it was executed in. Note: This callback is *not* guaranteed to be invoked
// (and won't be if, for instance, the context is destroyed before this is
// ran).
// NOTE(devlin): We could easily change that if desired.
using ResultCallback = base::OnceCallback<void(v8::Local<v8::Context>,
std::optional<base::Value>)>;
// Calls the given `function` in the specified `context` and with the provided
// arguments. JS may be executed asynchronously if it has been suspended in
// the context.
void RunJSFunction(v8::Local<v8::Function> function,
v8::Local<v8::Context> context,
base::span<v8::Local<v8::Value>> args);
// Same as above, but if a `callback` is provided, it will be called with the
// results of the function running.
virtual void RunJSFunction(v8::Local<v8::Function> function,
v8::Local<v8::Context> context,
base::span<v8::Local<v8::Value>> args,
ResultCallback callback) = 0;
// Executes the given `function` synchronously and returns the result. This
// should *only* be called in direct response to script running, since it
// bypasses script suspension.
virtual v8::MaybeLocal<v8::Value> RunJSFunctionSync(
v8::Local<v8::Function> function,
v8::Local<v8::Context> context,
base::span<v8::Local<v8::Value>> args) = 0;
// Sets a global instance for testing that will be returned instead of the
// per-context version (if any).
static void SetInstanceForTesting(JSRunner* runner);
// Returns the global testing instance.
static JSRunner* GetInstanceForTesting();
protected:
// Returns the address of the first element in `args` or nullptr if the span
// is empty.
// TODO(crbug.com/351564777): This potentially can be removed once other
// APIs migrate from C-style arrays to spans.
v8::Local<v8::Value>* GetArgv(base::span<v8::Local<v8::Value>> args) {
return args.empty() ? nullptr : &args[0];
}
};
} // namespace extensions
#endif // EXTENSIONS_RENDERER_BINDINGS_JS_RUNNER_H_
|