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 143 144 145 146 147 148 149
|
// Copyright 2022 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_BACKGROUND_SCRIPT_EXECUTOR_H_
#define EXTENSIONS_BROWSER_BACKGROUND_SCRIPT_EXECUTOR_H_
#include <memory>
#include <optional>
#include <string>
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/browsertest_util.h"
#include "extensions/common/extension_id.h"
namespace content {
class BrowserContext;
} // namespace content
namespace extensions {
class Extension;
class ExtensionRegistry;
class ProcessManager;
class ScriptResultQueue;
// A helper class to execute a script in an extension's background context,
// either its service worker or its (possibly lazy) background page.
// Returning results:
// Return results with chrome.test.sendScriptResult(). This can be called
// either synchronously or asynchronously from the injected script.
// For compatibility with legacy scripts, background page contexts can choose
// send results via window.domAutomationController.send(). New code should not
// do this.
// This class is designed for single-use executions and is only meant to be used
// in tests.
class BackgroundScriptExecutor {
public:
// The manner in which the script will use to send the result.
enum class ResultCapture {
// No result will be captured. The caller only cares about injecting the
// script and may wait for another signal of execution.
kNone,
// Result sent with chrome.test.sendScriptResult().
kSendScriptResult,
// Result sent with window.domAutomationController.send().
// DON'T USE. This is only here for backwards compatibility with tests that
// were written before chrome.test.sendScriptResult() exists, and this
// doesn't work with service worker contexts.
kWindowDomAutomationController,
};
explicit BackgroundScriptExecutor(content::BrowserContext* browser_context);
~BackgroundScriptExecutor();
// Executes the given `script` and waits for execution to complete, returning
// the result. `script_user_activation` is used to determine whether the
// script executes with a user gesture, and must be be `kDontActivate` for
// service worker-based extensions.
base::Value ExecuteScript(
const ExtensionId& extension_id,
const std::string& script,
ResultCapture result_capture,
browsertest_util::ScriptUserActivation script_user_activation =
browsertest_util::ScriptUserActivation::kDontActivate);
// Static variant of the above.
static base::Value ExecuteScript(
content::BrowserContext* browser_context,
const ExtensionId& extension_id,
const std::string& script,
ResultCapture result_capture,
browsertest_util::ScriptUserActivation script_user_activation =
browsertest_util::ScriptUserActivation::kDontActivate);
// Executes the given `script` and returns immediately, without waiting for
// the script to finish. `script_user_activation` is used to determine
// whether the script executes with a user gesture, and must be
// `kDontActivate` for service worker-based extensions.
bool ExecuteScriptAsync(
const ExtensionId& extension_id,
const std::string& script,
ResultCapture result_capture,
browsertest_util::ScriptUserActivation script_user_activation =
browsertest_util::ScriptUserActivation::kDontActivate);
// Static variant of the above. Inherently, this cannot handle a result
// (because it is not returned synchronously and there's no exposed instance
// of BackgroundScriptExecutor).
static bool ExecuteScriptAsync(
content::BrowserContext* browser_context,
const ExtensionId& extension_id,
const std::string& script,
browsertest_util::ScriptUserActivation script_user_activation =
browsertest_util::ScriptUserActivation::kDontActivate);
// Waits for the result of the script execution; for use with
// `ExecuteScriptAsync()`.
base::Value WaitForResult();
private:
enum class BackgroundType {
kServiceWorker,
kPage,
};
// Helper method to execute the script in a service worker context.
bool ExecuteScriptInServiceWorker();
// Helper method to execute the script in a background page context.
bool ExecuteScriptInBackgroundPage(
browsertest_util::ScriptUserActivation script_user_activation);
// Method to ADD_FAILURE() to the currently-running test with the given
// `message` and other debugging info, like the injected script and associated
// extension.
void AddTestFailure(const std::string& message);
// The associated BrowserContext. Must outlive this object.
const raw_ptr<content::BrowserContext> browser_context_;
// The associated ExtensionRegistry; tied to `browser_context_`.
const raw_ptr<ExtensionRegistry> registry_;
// The associated ProcessManager; tied to `browser_context_`.
const raw_ptr<ProcessManager> process_manager_;
// The type of background context the extension uses; lazily instantiated in
// ExecuteScript*().
std::optional<BackgroundType> background_type_;
// The method the script will use to send the result.
ResultCapture result_capture_method_ = ResultCapture::kNone;
// The DOMMessageQueue used for retrieving results from background page-based
// extensions with `ResultCapture::kWindowDomAutomationController`.
std::unique_ptr<content::DOMMessageQueue> message_queue_;
// The ScriptResultQueue for retrieving results from contexts using
// `ResultCapture::kSendScriptResult`.
std::unique_ptr<ScriptResultQueue> script_result_queue_;
// The associated Extension.
raw_ptr<const Extension, FlakyDanglingUntriaged> extension_ = nullptr;
// The script to inject; cached mostly for logging purposes.
std::string script_;
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_BACKGROUND_SCRIPT_EXECUTOR_H_
|