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
|
// 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_BROWSER_API_TEST_UTILS_H_
#define EXTENSIONS_BROWSER_API_TEST_UTILS_H_
#include <memory>
#include <optional>
#include <string>
#include <variant>
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "extensions/browser/extension_function.h"
namespace content {
class BrowserContext;
}
namespace extensions {
class ExtensionFunctionDispatcher;
namespace api_test_utils {
// A helper class to handle waiting for a function response.
class SendResponseHelper {
public:
explicit SendResponseHelper(ExtensionFunction* function);
SendResponseHelper(const SendResponseHelper&) = delete;
SendResponseHelper& operator=(const SendResponseHelper&) = delete;
~SendResponseHelper();
bool has_response() { return response_.get() != nullptr; }
// Asserts a response has been posted (has_response()) and returns the value.
bool GetResponse();
// Waits until a response is posted.
void WaitForResponse();
private:
// Response handler.
void OnResponse(ExtensionFunction::ResponseType response,
base::Value::List results,
const std::string& error,
mojom::ExtraResponseDataPtr);
base::RunLoop run_loop_;
std::unique_ptr<bool> response_;
};
// The mode a function is supposed to be run with.
enum class FunctionMode {
kNone,
kIncognito,
};
// Get `key` from `val` as the specified type. If `key` does not exist, or is
// not of the specified type, adds a failure to the current test and returns
// false, 0, empty string, etc.
bool GetBoolean(const base::Value::Dict& val, const std::string& key);
int GetInteger(const base::Value::Dict& val, const std::string& key);
std::string GetString(const base::Value::Dict& val, const std::string& key);
base::Value::List GetList(const base::Value::Dict& val, const std::string& key);
base::Value::Dict GetDict(const base::Value::Dict& val, const std::string& key);
// If `val` is a dictionary, return it as one, otherwise create an empty one.
base::Value::Dict ToDict(std::optional<base::ValueView> val);
// If `val` is a list, return it as one, otherwise create an empty one.
base::Value::List ToList(std::optional<base::ValueView> val);
// Currently, we allow either a string for the args, which is parsed to a list,
// or an already-constructed list.
using ArgsType = std::variant<std::string, base::Value::List>;
// Run `function` with `args` and return the result. Adds an error to the
// current test if `function` returns an error. Takes ownership of
// `function`. The caller takes ownership of the result.
std::optional<base::Value> RunFunctionWithDelegateAndReturnSingleResult(
scoped_refptr<ExtensionFunction> function,
ArgsType args,
std::unique_ptr<ExtensionFunctionDispatcher> dispatcher,
FunctionMode mode);
// RunFunctionWithDelegateAndReturnSingleResult, except with a NULL
// implementation of the Delegate.
std::optional<base::Value> RunFunctionAndReturnSingleResult(
scoped_refptr<ExtensionFunction> function,
ArgsType args,
content::BrowserContext* context,
FunctionMode mode = FunctionMode::kNone);
// Run `function` with `args` and return the resulting error. Adds an error to
// the current test if `function` returns a result. Takes ownership of
// `function`.
std::string RunFunctionAndReturnError(scoped_refptr<ExtensionFunction> function,
ArgsType args,
content::BrowserContext* context,
FunctionMode mode = FunctionMode::kNone);
// Run `function` with `args` and return the error if set, otherwise the result.
base::expected<base::Value::List, std::string> RunFunctionAndReturnExpected(
scoped_refptr<ExtensionFunction> function,
ArgsType args,
content::BrowserContext* context,
FunctionMode mode = FunctionMode::kNone);
// Create and run `function` with `args`. Works with both synchronous and async
// functions. Ownership of `function` remains with the caller.
//
// TODO(aa): It would be nice if `args` could be validated against the schema
// that `function` expects. That way, we know that we are testing something
// close to what the bindings would actually send.
//
// TODO(aa): I'm concerned that this style won't scale to all the bits and bobs
// we're going to need to frob for all the different extension functions. But
// we can refactor when we see what is needed.
bool RunFunction(scoped_refptr<ExtensionFunction> function,
ArgsType args,
content::BrowserContext* context,
FunctionMode mode = FunctionMode::kNone);
bool RunFunction(scoped_refptr<ExtensionFunction> function,
ArgsType args,
std::unique_ptr<ExtensionFunctionDispatcher> dispatcher,
FunctionMode mode);
} // namespace api_test_utils
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_TEST_UTILS_H_
|