File: background_script_executor.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (149 lines) | stat: -rw-r--r-- 5,994 bytes parent folder | download | duplicates (9)
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_