File: extension_host.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 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 (294 lines) | stat: -rw-r--r-- 11,794 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
// 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_EXTENSION_HOST_H_
#define EXTENSIONS_BROWSER_EXTENSION_HOST_H_

#include <stdint.h>

#include <memory>
#include <string>
#include <unordered_map>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/public/browser/media_stream_request.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/deferred_start_render_host.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/mojom/view_type.mojom.h"
#include "extensions/common/stack_frame.h"

namespace base {
class ElapsedTimer;
}  // namespace base

namespace content {
class BrowserContext;
class RenderProcessHost;
class SiteInstance;
}  // namespace content

namespace extensions {
class Extension;
class ExtensionHostDelegate;
class ExtensionHostObserver;
class ExtensionHostQueue;

enum class EventDispatchSource;

// This class is the browser component of an extension component's page.
// It handles setting up the renderer process, if needed, with special
// privileges available to extensions.  It may have a view to be shown in the
// browser UI, or it may be hidden.
//
// If you are adding code that only affects visible extension views (and not
// invisible background pages) you should add it to ExtensionViewHost.
class ExtensionHost : public DeferredStartRenderHost,
                      public content::WebContentsDelegate,
                      public content::WebContentsObserver,
                      public ExtensionFunctionDispatcher::Delegate,
                      public ExtensionRegistryObserver {
 public:
  using CloseHandler = base::OnceCallback<void(ExtensionHost*)>;

  ExtensionHost(const Extension* extension,
                content::SiteInstance* site_instance,
                content::BrowserContext* browser_context,
                const GURL& url,
                mojom::ViewType host_type);

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

  ~ExtensionHost() override;

  // This may be null if the extension has been or is being unloaded.
  const Extension* extension() const { return extension_; }

  const ExtensionId& extension_id() const { return extension_id_; }
  content::WebContents* host_contents() const { return host_contents_.get(); }
  content::RenderFrameHost* main_frame_host() const { return main_frame_host_; }
  content::RenderProcessHost* render_process_host() const;
  bool has_loaded_once() const { return has_loaded_once_; }
  const GURL& initial_url() const { return initial_url_; }
  bool document_element_available() const {
    return document_element_available_;
  }

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

  mojom::ViewType extension_host_type() const { return extension_host_type_; }

  // Sets the callback responsible for closing the ExtensionHost in response to
  // a WebContents::CloseContents() call (which is triggered from e.g.
  // calling `window.close()`). This is done separately from the constructor as
  // some callsites create an ExtensionHost prior to the object that is
  // responsible for later closing it, but must be done before `CloseContents()`
  // can be called.
  void SetCloseHandler(CloseHandler close_handler);

  // Returns the last committed URL of the associated WebContents.
  const GURL& GetLastCommittedURL() const;

  // Returns true if the renderer main frame exists.
  bool IsRendererLive() const;

  // Prepares to initializes our RenderFrameHost by creating the main frame and
  // navigating `host_contents_` to the initial url. This happens delayed to
  // avoid locking the UI.
  void CreateRendererSoon();

  // Closes this host (results in [possibly asynchronous] deletion).
  void Close();

  // Typical observer interface.
  void AddObserver(ExtensionHostObserver* observer);
  void RemoveObserver(ExtensionHostObserver* observer);

  // Called when an event is dispatched to a lazy background page associated
  // with this ExtensionHost.
  void OnBackgroundEventDispatched(const std::string& event_name,
                                   base::TimeTicks dispatch_start_time,
                                   int event_id,
                                   EventDispatchSource dispatch_source,
                                   bool lazy_background_active_on_dispatch);

  // Called by the ProcessManager when a network request is started by the
  // extension corresponding to this ExtensionHost.
  void OnNetworkRequestStarted(uint64_t request_id);

  // Called by the ProcessManager when a previously started network request is
  // finished.
  void OnNetworkRequestDone(uint64_t request_id);

  // Returns true if the ExtensionHost is allowed to be navigated.
  bool ShouldAllowNavigations() const;

  std::size_t GetUnackedMessagesSizeForTesting() const {
    return unacked_messages_.size();
  }

  // content::WebContentsObserver:
  void RenderFrameCreated(content::RenderFrameHost* frame_host) override;
  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
                              content::RenderFrameHost* new_host) override;
  void PrimaryMainFrameRenderProcessGone(
      base::TerminationStatus status) override;
  void PrimaryMainDocumentElementAvailable() override;
  void DidStopLoading() override;

  // content::WebContentsDelegate:
  content::JavaScriptDialogManager* GetJavaScriptDialogManager(
      content::WebContents* source) override;
  content::WebContents* AddNewContents(
      content::WebContents* source,
      std::unique_ptr<content::WebContents> new_contents,
      const GURL& target_url,
      WindowOpenDisposition disposition,
      const blink::mojom::WindowFeatures& window_features,
      bool user_gesture,
      bool* was_blocked) override;
  void CloseContents(content::WebContents* contents) override;
  void RequestMediaAccessPermission(
      content::WebContents* web_contents,
      const content::MediaStreamRequest& request,
      content::MediaResponseCallback callback) override;
  bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host,
                                  const url::Origin& security_origin,
                                  blink::mojom::MediaStreamType type) override;
  content::PictureInPictureResult EnterPictureInPicture(
      content::WebContents* web_contents) override;
  void ExitPictureInPicture() override;
  std::string GetTitleForMediaControls(
      content::WebContents* web_contents) override;

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

  // Notifies observers when an event has been acknowledged from the renderer to
  // the browser. `event_has_listener_in_background_context` being set to true
  // emits histograms for some events that (when dispatched) should have ran in
  // the extension's background page. Of note:
  // `event_has_listener_in_background_context` is provided by the renderer when
  // the event is dispatched and is therefore not a reliable confirmation that
  // an event ran in the background page, but instead that it should have run in
  // the background page and is good enough for metrics purposes.
  void OnEventAck(int event_id, bool event_has_listener_in_background_context);

 protected:
  // Called each time this ExtensionHost completes a load finishes loading,
  // before any stop-loading notifications or observer methods are called.
  virtual void OnDidStopFirstLoad();

  // Navigates to the initial page.
  virtual void LoadInitialURL();

  // Returns true if we're hosting a background page.
  virtual bool IsBackgroundPage() const;

 private:
  struct UnackedEventData {
    // The event to dispatch.
    std::string event_name;

    // When the event router received the event to be dispatched to the
    // extension. Used in UMA histograms.
    base::TimeTicks dispatch_start_time;

    // The event dispatching processing flow that was followed for this event.
    EventDispatchSource dispatch_source;

    // `true` if the event was dispatched to a active/running lazy background.
    // Used in UMA histograms.
    bool lazy_background_active_on_dispatch;
  };

  // Emits a stale event ack metric if an event with `event_id` is not present
  // in `unacked_messages_`. Meaning that the event was not yet acked by the
  // renderer to the browser.
  void EmitLateAckedEventTask(int event_id);

  // DeferredStartRenderHost:
  void CreateRendererNow() override;

  void MaybeNotifyRenderProcessReady();
  void NotifyRenderProcessReady();

  // Records UMA for load events.
  void RecordStopLoadingUMA();

  // Delegate for functionality that cannot exist in the extensions module.
  std::unique_ptr<ExtensionHostDelegate> delegate_;

  // The extension that we're hosting in this view.
  raw_ptr<const Extension> extension_;

  // Id of extension that we're hosting in this view.
  const ExtensionId extension_id_;

  // The browser context that this host is tied to.
  raw_ptr<content::BrowserContext> browser_context_;

  // The host for our HTML content.
  std::unique_ptr<content::WebContents> host_contents_;

  // A pointer to the current or speculative main frame in `host_contents_`. We
  // can't access this frame through the `host_contents_` directly as it does
  // not expose the speculative main frame. While navigating to a still-loading
  // speculative main frame, we want to send messages to it rather than the
  // current frame.
  raw_ptr<content::RenderFrameHost> main_frame_host_;

  // Whether CreateRendererNow was called before the extension was ready.
  bool is_renderer_creation_pending_ = false;

  // Whether ExtensionHostCreated() event has been fired, since
  // RenderFrameCreated is triggered by every main frame that is created,
  // including during a cross-site navigation which uses a new main frame.
  bool has_creation_notification_already_fired_ = false;

  // Whether the ExtensionHost has finished loading some content at least once.
  // There may be subsequent loads - such as reloads and navigations - and this
  // will not affect its value (it will remain true).
  bool has_loaded_once_ = false;

  // True if the main frame has finished parsing.
  bool document_element_available_ = false;

  // The original URL of the page being hosted.
  GURL initial_url_;

  // Messages sent out to the renderer that have not been acknowledged yet.
  // Maps event ID to unacknowledged event information.
  std::map<int, UnackedEventData> unacked_messages_;

  // The type of view being hosted.
  mojom::ViewType extension_host_type_;

  // Measures how long since the initial URL started loading. This timer is
  // started only once the ExtensionHost has exited the ExtensionHostQueue.
  std::unique_ptr<base::ElapsedTimer> load_start_;

  CloseHandler close_handler_;
  // Whether the close handler has been previously invoked.
  bool called_close_handler_ = false;

  base::ObserverList<ExtensionHostObserver>::Unchecked observer_list_;

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

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_EXTENSION_HOST_H_