| // 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 <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" |
| #include "third_party/abseil-cpp/absl/types/optional.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. |
| 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*(). |
| absl::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_ |