File: runtime_api.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (352 lines) | stat: -rw-r--r-- 12,282 bytes parent folder | download | duplicates (2)
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
// 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_RUNTIME_RUNTIME_API_H_
#define EXTENSIONS_BROWSER_API_RUNTIME_RUNTIME_API_H_

#include <memory>
#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "extensions/browser/api/runtime/runtime_api_delegate.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/events/lazy_event_dispatch_util.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/lazy_context_task_queue.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_manager_observer.h"
#include "extensions/browser/update_observer.h"
#include "extensions/common/api/runtime.h"
#include "extensions/common/extension_id.h"

namespace base {
class Version;
}

namespace content {
class BrowserContext;
}

class PrefRegistrySimple;

namespace extensions {

namespace api::runtime {
struct PlatformInfo;
}

class Extension;
class ExtensionRegistry;

// Runtime API dispatches onStartup, onInstalled, and similar events to
// extensions. There is one instance shared between a browser context and
// its related incognito instance.
class RuntimeAPI : public BrowserContextKeyedAPI,
                   public ExtensionRegistryObserver,
                   public UpdateObserver,
                   public ProcessManagerObserver,
                   public LazyEventDispatchUtil::Observer {
 public:
  // The status of the restartAfterDelay request.
  enum class RestartAfterDelayStatus {
    // The request was made by a different extension other than the first one to
    // invoke the restartAfterDelay runtime API.
    FAILED_NOT_FIRST_EXTENSION,

    // The request came too soon after a previous restart induced by the
    // restartAfterDelay API. It failed to be scheduled as requested, and was
    // instead throttled.
    FAILED_THROTTLED,

    // Any previously scheduled restart was successfully canceled.
    SUCCESS_RESTART_CANCELED,

    // A restart was successfully scheduled.
    SUCCESS_RESTART_SCHEDULED,
  };

  // After this many suspiciously fast consecutive reloads, an extension will
  // get disabled.
  static constexpr int kFastReloadCount = 5;

  // Same as above, but we increase the fast reload count for unpacked
  // extensions.
  static constexpr int kUnpackedFastReloadCount = 30;

  static BrowserContextKeyedAPIFactory<RuntimeAPI>* GetFactoryInstance();

  static void RegisterPrefs(PrefRegistrySimple* registry);

  explicit RuntimeAPI(content::BrowserContext* context);

  RuntimeAPI(const RuntimeAPI&) = delete;
  RuntimeAPI& operator=(const RuntimeAPI&) = delete;

  ~RuntimeAPI() override;

  void ReloadExtension(const ExtensionId& extension_id);
  bool CheckForUpdates(const ExtensionId& extension_id,
                       RuntimeAPIDelegate::UpdateCheckCallback callback);
  void OpenURL(const GURL& uninstall_url);
  bool GetPlatformInfo(api::runtime::PlatformInfo* info);
  bool RestartDevice(std::string* error_message);

  RestartAfterDelayStatus RestartDeviceAfterDelay(
      const ExtensionId& extension_id,
      int seconds_from_now);

  bool OpenOptionsPage(const Extension* extension,
                       content::BrowserContext* browser_context);

 private:
  friend class BrowserContextKeyedAPIFactory<RuntimeAPI>;
  friend class RestartAfterDelayApiTest;

  // ExtensionRegistryObserver implementation.
  void OnExtensionLoaded(content::BrowserContext* browser_context,
                         const Extension* extension) override;
  void OnExtensionUninstalled(content::BrowserContext* browser_context,
                              const Extension* extension,
                              UninstallReason reason) override;

  // LazyEventDispatchUtil::Observer:
  void OnExtensionInstalledAndLoaded(
      content::BrowserContext* browser_context,
      const Extension* extension,
      const base::Version& previous_version) override;

  // Cancels any previously scheduled restart request.
  void MaybeCancelRunningDelayedRestartTimer();

  // Handler for the signal from ExtensionSystem::ready().
  void OnExtensionsReady();

  RestartAfterDelayStatus ScheduleDelayedRestart(const base::Time& now,
                                                 int seconds_from_now);

  // Called when the delayed restart timer times out so that it attempts to
  // execute the restart request scheduled earlier.
  void OnDelayedRestartTimerTimeout();

  // BrowserContextKeyedAPI implementation:
  static const char* service_name() { return "RuntimeAPI"; }
  static const bool kServiceRedirectedInIncognito = true;
  static const bool kServiceIsNULLWhileTesting = true;
  void Shutdown() override;

  // extensions::UpdateObserver overrides:
  void OnAppUpdateAvailable(const Extension& extension) override;
  void OnChromeUpdateAvailable() override;

  // ProcessManagerObserver implementation:
  void OnBackgroundHostStartup(const Extension* extension) override;

  void AllowNonKioskAppsInRestartAfterDelayForTesting();

  void set_min_duration_between_restarts_for_testing(base::TimeDelta delta) {
    minimum_duration_between_restarts_ = delta;
  }

  std::unique_ptr<RuntimeAPIDelegate> delegate_;

  raw_ptr<content::BrowserContext> browser_context_;

  // Listen to extension notifications.
  base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
      extension_registry_observation_{this};
  base::ScopedObservation<ProcessManager, ProcessManagerObserver>
      process_manager_observation_{this};

  // The ID of the first extension to call the restartAfterDelay API. Any other
  // extensions to call this API after that will fail.
  std::string schedule_restart_first_extension_id_;

  // The timer that will trigger a device restart when it times out.
  base::OneShotTimer restart_after_delay_timer_;

  // The minimum allowed duration between two successive restarts caused by
  // restartAfterDelay calls.
  base::TimeDelta minimum_duration_between_restarts_;

  // The last restart time which was a result of a successful call to
  // chrome.runtime.restartAfterDelay().
  base::Time last_delayed_restart_time_;

  // True if we should dispatch the chrome.runtime.onInstalled event with
  // reason "chrome_update" upon loading each extension.
  bool dispatch_chrome_updated_event_;

  bool did_read_delayed_restart_preferences_;
  bool was_last_restart_due_to_delayed_restart_api_;

  base::WeakPtrFactory<RuntimeAPI> weak_ptr_factory_{this};
};

template <>
void BrowserContextKeyedAPIFactory<RuntimeAPI>::DeclareFactoryDependencies();

class RuntimeEventRouter {
 public:
  // Dispatches the onStartup event to all currently-loaded extensions.
  static void DispatchOnStartupEvent(content::BrowserContext* context,
                                     const ExtensionId& extension_id);

  // Dispatches the onInstalled event to the given extension.
  static void DispatchOnInstalledEvent(void* context_id,
                                       const ExtensionId& extension_id,
                                       const base::Version& old_version,
                                       bool chrome_updated);

  // Dispatches the onUpdateAvailable event to the given extension.
  static void DispatchOnUpdateAvailableEvent(content::BrowserContext* context,
                                             const ExtensionId& extension_id,
                                             const base::Value::Dict* manifest);

  // Dispatches the onBrowserUpdateAvailable event to all extensions.
  static void DispatchOnBrowserUpdateAvailableEvent(
      content::BrowserContext* context);

  // Dispatches the onRestartRequired event to the given app.
  static void DispatchOnRestartRequiredEvent(
      content::BrowserContext* context,
      const std::string& app_id,
      api::runtime::OnRestartRequiredReason reason);

  // Does any work needed at extension uninstall (e.g. load uninstall url).
  static void OnExtensionUninstalled(content::BrowserContext* context,
                                     const ExtensionId& extension_id,
                                     UninstallReason reason);
};

class RuntimeGetBackgroundPageFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.getBackgroundPage",
                             RUNTIME_GETBACKGROUNDPAGE)

 protected:
  ~RuntimeGetBackgroundPageFunction() override = default;
  ResponseAction Run() override;

 private:
  void OnPageLoaded(
      std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info);
};

class RuntimeOpenOptionsPageFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.openOptionsPage", RUNTIME_OPENOPTIONSPAGE)

 protected:
  ~RuntimeOpenOptionsPageFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeSetUninstallURLFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.setUninstallURL", RUNTIME_SETUNINSTALLURL)

 protected:
  ~RuntimeSetUninstallURLFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeReloadFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.reload", RUNTIME_RELOAD)

 protected:
  ~RuntimeReloadFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeRequestUpdateCheckFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.requestUpdateCheck",
                             RUNTIME_REQUESTUPDATECHECK)

 protected:
  ~RuntimeRequestUpdateCheckFunction() override = default;
  ResponseAction Run() override;

 private:
  void CheckComplete(const RuntimeAPIDelegate::UpdateCheckResult& result);
};

class RuntimeRestartFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.restart", RUNTIME_RESTART)

 protected:
  ~RuntimeRestartFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeRestartAfterDelayFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.restartAfterDelay",
                             RUNTIME_RESTARTAFTERDELAY)

 protected:
  ~RuntimeRestartAfterDelayFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeGetPlatformInfoFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.getPlatformInfo", RUNTIME_GETPLATFORMINFO)

 protected:
  ~RuntimeGetPlatformInfoFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeGetPackageDirectoryEntryFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.getPackageDirectoryEntry",
                             RUNTIME_GETPACKAGEDIRECTORYENTRY)

 protected:
  ~RuntimeGetPackageDirectoryEntryFunction() override = default;
  ResponseAction Run() override;
};

class RuntimeGetContextsFunction : public ExtensionFunction {
 public:
  DECLARE_EXTENSION_FUNCTION("runtime.getContexts", RUNTIME_GETCONTEXTS)

  RuntimeGetContextsFunction();
  RuntimeGetContextsFunction(const RuntimeGetContextsFunction&) = delete;
  RuntimeGetContextsFunction& operator=(const RuntimeGetContextsFunction&) =
      delete;

 private:
  // ExtensionFunction:
  ~RuntimeGetContextsFunction() override;
  ResponseAction Run() override;

  // Returns the context for the extension background service worker, if the
  // worker is active. Otherwise, returns nullopt.
  std::optional<api::runtime::ExtensionContext> GetWorkerContext();

  // Returns a collection of all frame-based extension contexts for the
  // extension.
  std::vector<api::runtime::ExtensionContext> GetFrameContexts();

  // Helper methods to return tab id, frame id and window id for a given
  // context.
  int GetTabId(content::WebContents& web_contents);
  int GetFrameId(content::RenderFrameHost& host);
  int GetWindowId(content::WebContents& web_contents);
};

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_RUNTIME_RUNTIME_API_H_