File: process_manager.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 (448 lines) | stat: -rw-r--r-- 19,669 bytes parent folder | download | duplicates (5)
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
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
// Copyright 2013 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_PROCESS_MANAGER_H_
#define EXTENSIONS_BROWSER_PROCESS_MANAGER_H_

#include <stdint.h>

#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_multi_source_observation.h"
#include "base/uuid.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/devtools_agent_host_observer.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/service_worker_external_request_result.h"
#include "content/public/browser/service_worker_external_request_timeout_type.h"
#include "extensions/browser/activity.h"
#include "extensions/browser/extension_host_observer.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/service_worker/worker_id.h"
#include "extensions/browser/service_worker/worker_id_set.h"
#include "extensions/common/extension_id.h"

class GURL;

namespace content {
class BrowserContext;
class DevToolsAgentHost;
class RenderFrameHost;
class SiteInstance;
class WebContents;
}  // namespace content

namespace extensions {

class Extension;
class ExtensionHost;
class ExtensionRegistry;
class ProcessManagerObserver;

// Manages dynamic state of running Chromium extensions. There is one instance
// of this class per Profile. OTR Profiles have a separate instance that keeps
// track of split-mode extensions only.
class ProcessManager : public KeyedService,
                       public ExtensionRegistryObserver,
                       public content::DevToolsAgentHostObserver,
                       public content::RenderProcessHostObserver,
                       public ExtensionHostObserver {
 public:
  using ExtensionHostSet =
      std::set<raw_ptr<extensions::ExtensionHost, SetExperimental>>;

  // A struct representing an active service worker keepalive.
  struct ServiceWorkerKeepaliveData {
    // The worker ID associated with the keepalive.
    WorkerId worker_id;
    // The type of activity for the keepalive.
    Activity::Type activity_type;
    // Any "additional data" for the keepalive; for instance, this could be
    // the API function or event name.
    std::string extra_data;
    // The timeout behavior for the given request.
    content::ServiceWorkerExternalRequestTimeoutType timeout_type;
    // The result of trying to start an external request with the service
    // worker layer.
    content::ServiceWorkerExternalRequestResult start_result;
  };
  using ServiceWorkerKeepaliveDataMap =
      std::map<base::Uuid, ServiceWorkerKeepaliveData>;

  static ProcessManager* Get(content::BrowserContext* context);

  // Creates a new ProcessManager for the given `context`. This is independent
  // from the constructor below as it may construct an incognito version of the
  // ProcessManager.
  // Note: Most callers should use `ProcessManager::Get()` instead to retrieve
  // the ProcessManager for a given context.
  static std::unique_ptr<ProcessManager> Create(
      content::BrowserContext* context);

  ProcessManager(content::BrowserContext* context,
                 ExtensionRegistry* registry);

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

  ~ProcessManager() override;

  // KeyedService support:
  void Shutdown() override;

  void RegisterRenderFrameHost(content::RenderFrameHost* render_frame_host,
                               const Extension* extension);
  void UnregisterRenderFrameHost(content::RenderFrameHost* render_frame_host);

  // Starts tracking or stops tracking (if it's already being tracked) a running
  // worker to this process manager. Note: This does not create any Service
  // Workers.
  void StartTrackingServiceWorkerRunningInstance(const WorkerId& worker_id);
  void StopTrackingServiceWorkerRunningInstance(const WorkerId& worker_id);
  void StopTrackingServiceWorkerRunningInstance(const ExtensionId& extension_id,
                                                int64_t worker_version_id);

  // Returns the SiteInstance that the given URL belongs to.
  // NOTE: Usage of this method is potentially error-prone. An extension can
  // correspond to multiple SiteInstances (e.g. consider a cross origin isolated
  // extension with non-cross-origin-isolated contexts).
  // TODO(aa): This only returns correct results for extensions and packaged
  // apps, not hosted apps.
  // TODO(https://crbug.com/334991035): Remove this method.
  virtual scoped_refptr<content::SiteInstance> GetSiteInstanceForURL(
      const GURL& url);

  using FrameSet = std::set<content::RenderFrameHost*>;
  const FrameSet GetAllFrames() const;

  // Returns all RenderFrameHosts that are registered for the specified
  // extension.
  ProcessManager::FrameSet GetRenderFrameHostsForExtension(
      const ExtensionId& extension_id);

  bool IsRenderFrameHostRegistered(content::RenderFrameHost* render_frame_host);

  void AddObserver(ProcessManagerObserver* observer);
  void RemoveObserver(ProcessManagerObserver* observer);

  // Creates a new UI-less extension instance.  Like CreateViewHost, but not
  // displayed anywhere.  Returns false if no background host can be created,
  // for example for hosted apps and extensions that aren't enabled in
  // Incognito.
  virtual bool CreateBackgroundHost(const Extension* extension,
                                    const GURL& url);

  // Creates background hosts if the embedder is ready and they are not already
  // loaded.
  void MaybeCreateStartupBackgroundHosts();

  // Gets the ExtensionHost for the background page for an extension, or null if
  // the extension isn't running or doesn't have a background page.
  ExtensionHost* GetBackgroundHostForExtension(const ExtensionId& extension_id);

  // Returns the background page ExtensionHost for the given
  // `render_frame_host`, if `render_frame_host` is in primary main frame and
  // within the extension's background.
  ExtensionHost* GetBackgroundHostForRenderFrameHost(
      content::RenderFrameHost* render_frame_host);

  // Returns true if the (lazy) background host for the given extension has
  // already been sent the unload event and is shutting down.
  bool IsBackgroundHostClosing(const ExtensionId& extension_id);

  // Returns the extension associated with the specified RenderFrameHost,
  // or null.
  const Extension* GetExtensionForRenderFrameHost(
      content::RenderFrameHost* render_frame_host);

  // Returns the extension associated with the main frame of the given
  // `web_contents`, or null if there isn't one.
  const Extension* GetExtensionForWebContents(
      content::WebContents* web_contents);

  // Getter and setter for the lazy background page's keepalive count. This is
  // the count of how many outstanding "things" are keeping the page alive.
  // When this reaches 0, we will begin the process of shutting down the page.
  // "Things" include pending events, resource loads, and API calls.
  // Returns -1 if `extension` does not have a lazy background page.
  // The calls to increment and decrement the count also accept a category
  // of activity and an extra string of data. These are kept so there is
  // more information for the counts. See the Activity struct definition
  // for more details regarding the extra data.
  int GetLazyKeepaliveCount(const Extension* extension);
  void IncrementLazyKeepaliveCount(const Extension* extension,
                                   Activity::Type activity_type,
                                   const std::string& extra_data);
  void DecrementLazyKeepaliveCount(const Extension* extension,
                                   Activity::Type activity_type,
                                   const std::string& extra_data);

  // Sends out notification to observers when the extension process is gone.
  void NotifyExtensionProcessTerminated(const Extension* extension);

  // Methods to increment or decrement the ref-count of a specified service
  // worker with id `worker_id`.
  // The increment method returns the guid that needs to be passed to the
  // decrement method.
  // `timeout_type` is the SW's timeout behavior.
  base::Uuid IncrementServiceWorkerKeepaliveCount(
      const WorkerId& worker_id,
      content::ServiceWorkerExternalRequestTimeoutType timeout_type,
      Activity::Type activity_type,
      const std::string& extra_data);
  // Decrements the ref-count of the specified worker with `worker_id` that
  // had its ref-count incremented with `request_uuid`.
  void DecrementServiceWorkerKeepaliveCount(const WorkerId& worker_id,
                                            const base::Uuid& request_uuid,
                                            Activity::Type activity_type,
                                            const std::string& extra_data);

  using ActivitiesMultisetPair = std::pair<Activity::Type, std::string>;
  using ActivitiesMultiset = std::multiset<ActivitiesMultisetPair>;

  // Return the current set of keep-alive activities for the extension.
  ActivitiesMultiset GetLazyKeepaliveActivities(const Extension* extension);

  // Handles a response to the ShouldSuspend message, used for lazy background
  // pages.
  void OnShouldSuspendAck(const ExtensionId& extension_id,
                          uint64_t sequence_id);

  // Tracks network requests for a given RenderFrameHost, used to know
  // when network activity is idle for lazy background pages.
  void NetworkRequestStarted(content::RenderFrameHost* render_frame_host,
                             uint64_t request_id);
  void NetworkRequestDone(content::RenderFrameHost* render_frame_host,
                          uint64_t request_id);

  // Prevents `extension`'s background page from being closed and sends the
  // onSuspendCanceled() event to it.
  void CancelSuspend(const Extension* extension);

  // Called on shutdown to close our extension hosts.
  void CloseBackgroundHosts();

  // Wakes an extension's event page from a suspended state and calls
  // `callback` after it is reactivated.
  //
  // `callback` will be passed true if the extension was reactivated
  // successfully, or false if an error occurred.
  //
  // Returns true if a wake operation was scheduled successfully,
  // or false if the event page was already awake.
  // Callback will be run asynchronously if true, and never run if false.
  bool WakeEventPage(const ExtensionId& extension_id,
                     base::OnceCallback<void(bool)> callback);

  // Sets the time in milliseconds that an extension event page can
  // be idle before it is shut down; must be > 0.
  static void SetEventPageIdleTimeForTesting(unsigned idle_time_msec);

  // Sets the time in milliseconds that an extension event page has
  // between being notified of its impending unload and that unload
  // happening.
  static void SetEventPageSuspendingTimeForTesting(
      unsigned suspending_time_msec);

  content::BrowserContext* browser_context() const { return browser_context_; }

  const ExtensionHostSet& background_hosts() const {
    return background_hosts_;
  }

  // Returns true if this ProcessManager has registered any worker with id
  // `worker_id`.
  bool HasServiceWorker(const WorkerId& worker_id) const;

  // Returns all the Service Worker infos that is active for the extension with
  // `extension_id`.
  std::vector<WorkerId> GetServiceWorkersForExtension(
      const ExtensionId& extension_id) const;

  // Returns the context ID for the given `worker_id`, if `worker_id` is
  // registered in the process manager. Otherwise, returns an empty base::Uuid.
  base::Uuid GetContextIdForWorker(const WorkerId& worker_id) const;

  // Returns the active service worker keepalives for the given `extension_id`.
  // Note: This should be used for debugging and metrics purposes; callers
  // should only interact with the service worker keepalives they themselves
  // created via IncrementServiceWorkerKeepaliveCount().
  std::vector<ServiceWorkerKeepaliveData>
  GetServiceWorkerKeepaliveDataForRecords(
      const ExtensionId& extension_id) const;

  bool startup_background_hosts_created_for_test() const {
    return startup_background_hosts_created_;
  }

  std::vector<WorkerId> GetAllWorkersIdsForTesting();

 protected:
  // Not owned. Also used by IncognitoProcessManager.
  raw_ptr<ExtensionRegistry> extension_registry_;

 private:
  // ExtensionRegistryObserver:
  void OnExtensionLoaded(content::BrowserContext* browser_context,
                         const Extension* extension) override;
  void OnExtensionUnloaded(content::BrowserContext* browser_context,
                           const Extension* extension,
                           UnloadedExtensionReason reason) override;

  // content::RenderProcessHostObserver:
  void RenderProcessExited(
      content::RenderProcessHost* host,
      const content::ChildProcessTerminationInfo& info) override;

  // ExtensionHostObserver:
  void OnExtensionHostDestroyed(ExtensionHost* host) override;

  // Extra information we keep for each extension's background page.
  struct BackgroundPageData;
  struct ExtensionRenderFrameData;
  using BackgroundPageDataMap = std::map<ExtensionId, BackgroundPageData>;
  using ExtensionRenderFrames =
      std::map<content::RenderFrameHost*, ExtensionRenderFrameData>;

  // Load all background pages once the profile data is ready and the pages
  // should be loaded.
  void CreateStartupBackgroundHosts();

  // Called just after `host` is created so it can be registered in our lists.
  void OnBackgroundHostCreated(ExtensionHost* host);

  // Handles a request from a created extension host to close the contents.
  // This happens in cases such as the contents calling `window.close()`.
  void HandleCloseExtensionHost(ExtensionHost* host);

  // Close the given `host` iff it's a background page.
  void CloseBackgroundHost(ExtensionHost* host);

  // If the frame isn't keeping the lazy background page alive, increments the
  // keepalive count to do so.
  void AcquireLazyKeepaliveCountForFrame(
      content::RenderFrameHost* render_frame_host);

  // If the frame is keeping the lazy background page alive, decrements the
  // keepalive count to stop doing it.
  void ReleaseLazyKeepaliveCountForFrame(
      content::RenderFrameHost* render_frame_host);

  // Internal implementation of DecrementLazyKeepaliveCount with an
  // `extension_id` known to have a lazy background page.
  void DecrementLazyKeepaliveCount(const ExtensionId& extension_id);
  void DecrementLazyKeepaliveCount(const ExtensionId& extension_id,
                                   Activity::Type activity_type,
                                   const std::string& extra_data);

  // These are called when the extension transitions between idle and active.
  // They control the process of closing the background page when idle.
  void OnLazyBackgroundPageIdle(const ExtensionId& extension_id,
                                uint64_t sequence_id);
  void OnLazyBackgroundPageActive(const ExtensionId& extension_id);
  void CloseLazyBackgroundPageNow(const ExtensionId& extension_id,
                                  uint64_t sequence_id);

  const Extension* GetExtensionForAgentHost(
      content::DevToolsAgentHost* agent_host);

  // content::DevToolsAgentHostObserver overrides.
  void DevToolsAgentHostAttached(
      content::DevToolsAgentHost* agent_host) override;
  void DevToolsAgentHostDetached(
      content::DevToolsAgentHost* agent_host) override;

  // Unregister RenderFrameHosts and clear background page data for an extension
  // which has been unloaded.
  void UnregisterExtension(const ExtensionId& extension_id);

  // Clears background page data for this extension.
  void ClearBackgroundPageData(const ExtensionId& extension_id);

  // Handles a response to the SuspendExtension Mojo method, used for lazy
  // background pages.
  void OnSuspendAck(const ExtensionId& extension_id);

  // The set of ExtensionHosts running viewless background extensions.
  ExtensionHostSet background_hosts_;

  // A SiteInstance related to the SiteInstance for all extensions in
  // this profile.  We create it in such a way that a new
  // browsing instance is created.  This controls process grouping.
  // TODO(https://crbug.com/334991035): Remove this member. The //content
  // layer will properly isolate new extension processes.
  scoped_refptr<content::SiteInstance> site_instance_;

  // The browser context associated with the ProcessManager.
  raw_ptr<content::BrowserContext> browser_context_;

  // Contains all active extension-related RenderFrameHost instances for all
  // extensions. We also keep a cache of the host's view type, because that
  // information is not accessible at registration/deregistration time.
  ExtensionRenderFrames all_extension_frames_;

  // Contains all active running extension Service Worker information for all
  // extensions.
  WorkerIdSet all_running_extension_workers_;
  // Maps worker IDs to extension context IDs (as used in the runtime API) for
  // running workers.
  std::map<WorkerId, base::Uuid> worker_context_ids_;

  BackgroundPageDataMap background_page_data_;

  // True if we have created the startup set of background hosts.
  bool startup_background_hosts_created_;

  base::ObserverList<ProcessManagerObserver> observer_list_;

  // ID Counter used to set ProcessManager::BackgroundPageData close_sequence_id
  // members. These IDs are tracked per extension in background_page_data_ and
  // are used to verify that nothing has interrupted the process of closing a
  // lazy background process.
  //
  // Any interruption obtains a new ID by incrementing
  // last_background_close_sequence_id_ and storing it in background_page_data_
  // for a particular extension. Callbacks and round-trip IPC messages store the
  // value of the extension's close_sequence_id at the beginning of the process.
  // Thus comparisons can be done to halt when IDs no longer match.
  //
  // This counter provides unique IDs even when BackgroundPageData objects are
  // reset.
  uint64_t last_background_close_sequence_id_;

  // Tracks pending network requests by opaque ID. This is used to ensure proper
  // keepalive counting in response to request status updates; e.g., if an
  // extension URLRequest is constructed and then destroyed without ever
  // starting, we can receive a completion notification without a corresponding
  // start notification. In that case we want to avoid decrementing keepalive.
  std::map<int, raw_ptr<ExtensionHost, CtnExperimental>>
      pending_network_requests_;

  // Observers of Service Worker RPH this ProcessManager manages.
  base::ScopedMultiSourceObservation<content::RenderProcessHost,
                                     content::RenderProcessHostObserver>
      process_observations_{this};
  // Maps render render_process_id -> extension_id for all Service Workers this
  // ProcessManager manages.
  std::map<int, std::set<ExtensionId>> worker_process_to_extension_ids_;

  // A map of the active service worker keepalives.
  ServiceWorkerKeepaliveDataMap service_worker_keepalives_;

  // Must be last member, see doc on WeakPtrFactory.
  base::WeakPtrFactory<ProcessManager> weak_ptr_factory_{this};
};

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_PROCESS_MANAGER_H_