blob: 44753ccc46ba739e1ced91887d5a840c5ca1dd57 [file] [log] [blame]
Avi Drissmand878a5012022-09-12 19:13:301// Copyright 2018 The Chromium Authors
Sean Toppinge91b0972018-10-25 20:59:122// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_
6#define CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_
7
Helmut Januschka430ce472024-01-31 22:31:408#include <optional>
Chad Duffin4aa9c042019-01-11 00:51:559#include <string>
Helmut Januschka430ce472024-01-31 22:31:4010#include <string_view>
Chad Duffin4aa9c042019-01-11 00:51:5511#include <vector>
12
Jiawei Li830fcfd2019-02-12 20:12:1713#include "base/containers/flat_set.h"
Avi Drissman710fdab2023-01-11 04:37:3614#include "base/functional/callback_forward.h"
Chad Duffin4aa9c042019-01-11 00:51:5515#include "base/observer_list.h"
Sean Topping6c9e3932021-08-23 21:25:3316#include "base/observer_list_types.h"
Zhaoxin2fe094a2020-02-11 23:35:4517#include "base/process/process.h"
Jiawei Li3446cb72021-06-07 14:11:5618#include "chromecast/bindings/public/mojom/api_bindings.mojom.h"
Sean Topping6c9e3932021-08-23 21:25:3319#include "chromecast/browser/cast_web_contents_observer.h"
Sean Topping92d0465b2021-07-16 01:11:3320#include "chromecast/browser/mojom/cast_web_contents.mojom.h"
21#include "chromecast/browser/web_types.h"
Chad Duffin4aa9c042019-01-11 00:51:5522#include "chromecast/common/mojom/feature_manager.mojom.h"
Sean Topping0436b462021-10-12 21:38:5623#include "chromecast/mojo/interface_bundle.h"
Chih-Hsuan Kuo7b4fb102020-03-04 08:21:4924#include "content/public/common/media_playback_renderer_type.mojom.h"
Ken Rockot48c7b502020-11-20 23:33:5925#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
Sean Topping92d0465b2021-07-16 01:11:3326#include "mojo/public/cpp/bindings/pending_receiver.h"
Sean Topping077ba6d82021-11-02 22:48:4227#include "mojo/public/cpp/bindings/receiver.h"
Sean Toppinge0c5a95c2021-11-12 23:13:4928#include "mojo/public/cpp/bindings/receiver_set.h"
Sean Topping92d0465b2021-07-16 01:11:3329#include "mojo/public/cpp/bindings/remote_set.h"
Jiawei Li830fcfd2019-02-12 20:12:1730#include "services/service_manager/public/cpp/interface_provider.h"
Chris Hamilton825f2ed2020-01-30 21:46:4131#include "third_party/blink/public/common/messaging/web_message_port.h"
Sean Toppingf0a1d572019-06-17 23:03:4432#include "ui/gfx/geometry/rect.h"
Sean Toppinge91b0972018-10-25 20:59:1233#include "url/gurl.h"
34
35namespace content {
Ryan Keane0d0493d2021-05-25 16:59:5536class NavigationHandle;
Sean Toppinge91b0972018-10-25 20:59:1237class WebContents;
38} // namespace content
39
Simeon Anfinrudc337a1522023-01-23 22:15:1640namespace media_control {
41class MediaBlocker;
42} // namespace media_control
43
Junbo Ke7f8623a2022-01-21 17:57:0544namespace url_rewrite {
45class UrlRequestRewriteRulesManager;
46} // namespace url_rewrite
47
Sean Toppinge91b0972018-10-25 20:59:1248namespace chromecast {
49
Sean Topping0e8ac572019-01-30 03:05:4350struct RendererFeature {
51 const std::string name;
52 base::Value value;
53};
54
Sean Toppinge91b0972018-10-25 20:59:1255// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2156//
57// Proper usage of content::WebContents relies on understanding the meaning
58// behind various WebContentsObserver methods, and then translating those
59// signals into some concrete state. CastWebContents does *not* own the
60// underlying WebContents (usually whatever class implements
61// content::WebContentsDelegate is the actual owner).
62//
63// =============================================================================
64// Lifetime
65// =============================================================================
66// CastWebContents *must* be created before WebContents begins loading any
67// content. Once content begins loading (via CWC::LoadUrl() or one of the
68// WebContents navigation APIs), CastWebContents will calculate its state based
69// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
70// (e.g. iframes) are ignored, since we expect the web app to take care of
71// sub-frame errors.
72//
73// We consider the CastWebContents to be in a LOADED state when the content of
Jiawei Li042aaca2021-03-30 00:15:5374// the main frame is fully loaded and running (all resources fetched,
75// redirection finished, JS is running). Iframes might still be loading in this
76// case, but in general we consider the page to be in a presentable state at
77// this stage, so it is appropriate to display the WebContents to the user.
Sean Topping7414eed2019-04-10 23:04:2178//
79// During or after the page is loaded, there are multiple error conditions that
80// can occur. The following events will cause the page to enter an ERROR state:
81//
82// 1. If the main frame is served an HTTP error page (such as a 404 page), then
83// it means the desired content wasn't loaded.
84//
85// 2. If the main frame fails to load, such as when the browser blocked the URL
86// request, we treat this as an error.
87//
88// 3. The RenderProcess for the main frame could crash, so the page is not in a
89// usable state.
90//
91// The CastWebContents user can respond to these errors in a few ways: The
92// content can be reloaded, or the entire page activity can be cancelled. If we
93// totally cancel the activity, we prefer to notify the user with an error
94// screen or visible/audible error message. Otherwise, a silent retry is
95// preferred.
96//
97// CastWebContents can be used to close the underlying WebContents gracefully
98// via CWC::Close(). This initiates web page tear-down logic so that the web
99// app has a chance to perform its own finalization logic in JS. Next, we call
100// WebContents::ClosePage(), which defers the page closure logic to the
101// content::WebContentsDelegate. Usually, it will run its own finalization
102// logic and then destroy the WebContents. CastWebContents will be notified of
103// the WebContents destruction and enter the DESTROYED state. In the event
104// the page isn't destroyed, the page will enter the CLOSED state automatically
105// after a timeout. CastWebContents users should not try to reload the page, as
106// page closure is intentional.
107//
108// The web app may decide to close itself (such as via "window.close()" in JS).
109// This is similar to initiating the close flow via CWC::Close(), with the end
110// result being the same. We consider this an intentional closure, and should
111// not attempt to reload the page.
112//
113// Once CastWebContents is in the DESTROYED state, it is not really usable
114// anymore; most of the methods will simply no-op, and no more observer signals
115// will be emitted.
116//
117// CastWebContents can be deleted at any time, *except* during Observer
118// notifications. If the owner wants to destroy CastWebContents as a result of
119// an Observer event, it should post a task to destroy CastWebContents.
Sean Topping92d0465b2021-07-16 01:11:33120class CastWebContents : public mojom::CastWebContents {
Sean Toppinge91b0972018-10-25 20:59:12121 public:
Sean Topping6c9e3932021-08-23 21:25:33122 // Synchronous in-process observer for CastWebContents. Observers must not
123 // destroy CastWebContents in any of the methods below.
124 class Observer : public base::CheckedObserver {
Sean Toppingf0a1d572019-06-17 23:03:44125 public:
126 Observer();
127
Sean Topping92d0465b2021-07-16 01:11:33128 // Adds |this| to the CastWebContents observer list. Observe(nullptr) will
129 // remove |this| from the observer list of the current CastWebContents being
130 // observed.
131 void Observe(CastWebContents* cast_web_contents);
132
Ryan Keane0d0493d2021-05-25 16:59:55133 // Called when the navigation is ready to be committed in the WebContents'
134 // main frame.
135 virtual void MainFrameReadyToCommitNavigation(
136 content::NavigationHandle* navigation_handle) {}
137
Vigen Issahhanjan77d798c22021-11-30 23:36:11138 // Notify that an inner WebContents was created. |inner_contents| is created
139 // in a default-initialized state with no delegate, and can be safely
140 // initialized by the delegate.
141 virtual void InnerContentsCreated(CastWebContents* inner_contents,
142 CastWebContents* outer_contents) {}
143
Vigen Issahhanjanc2911072022-06-06 18:20:45144 // Notify the page state changed.
145 virtual void PageStateChanged(PageState page_state) {}
146
147 // Notify the page stopped.
148 virtual void PageStopped(PageState page_state, int32_t error_code) {}
149
Vigen Issahhanjan89fc4f3c2022-08-05 02:14:38150 // Notify media playback state changes for the underlying WebContents.
151 virtual void MediaPlaybackChanged(bool media_playing) {}
152
Sean Topping6c9e3932021-08-23 21:25:33153 // Sets |cast_web_contents_| to |nullptr| but does not remove the Observer
154 // from the ObserverList. Called for each Observer during CastWebContents
155 // destruction; we don't use Observe(nullptr) since it would mutate the
156 // ObserverList during iteration.
Chad Duffin4aa9c042019-01-11 00:51:55157 void ResetCastWebContents();
158
159 protected:
Sean Topping92d0465b2021-07-16 01:11:33160 ~Observer() override;
Chad Duffin4aa9c042019-01-11 00:51:55161
162 CastWebContents* cast_web_contents_;
Sean Toppinge91b0972018-10-25 20:59:12163 };
164
Sean Topping6735aaf2019-03-20 19:20:12165 static std::vector<CastWebContents*>& GetAll();
166
Jiawei Lia64a082b2019-12-06 21:17:26167 // Returns the CastWebContents that wraps the content::WebContents, or nullptr
168 // if the CastWebContents does not exist.
169 static CastWebContents* FromWebContents(content::WebContents* web_contents);
170
Sean Topping92d0465b2021-07-16 01:11:33171 CastWebContents();
Peter Boströmae0ffa02021-10-05 17:08:33172
173 CastWebContents(const CastWebContents&) = delete;
174 CastWebContents& operator=(const CastWebContents&) = delete;
175
Sean Topping92d0465b2021-07-16 01:11:33176 ~CastWebContents() override;
Sean Toppinge91b0972018-10-25 20:59:12177
Sean Topping6735aaf2019-03-20 19:20:12178 // Tab identifier for the WebContents, mainly used by the tabs extension API.
179 // Tab IDs may be re-used, but no two live CastWebContents should have the
180 // same tab ID at any given time.
181 virtual int tab_id() const = 0;
182
Randy Rossic6bb3ab2020-08-11 18:02:52183 // An identifier for the WebContents, mainly used by platform views service.
184 // IDs may be re-used but are unique among all live CastWebContents.
185 virtual int id() const = 0;
186
Sean Topping0e8ac572019-01-30 03:05:43187 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12188 virtual content::WebContents* web_contents() const = 0;
189 virtual PageState page_state() const = 0;
Junbo Ked10a1eb2022-01-25 02:28:35190 virtual url_rewrite::UrlRequestRewriteRulesManager*
191 url_rewrite_rules_manager() = 0;
Simeon Anfinrudc337a1522023-01-23 22:15:16192 virtual const media_control::MediaBlocker* media_blocker() const = 0;
Sean Toppinge91b0972018-10-25 20:59:12193
Sean Topping92d0465b2021-07-16 01:11:33194 // mojom::CastWebContents implementation:
Sean Topping6c9e3932021-08-23 21:25:33195 void SetAppProperties(const std::string& app_id,
196 const std::string& session_id,
197 bool is_audio_app,
Guohui Dengedbf8032021-09-29 21:34:19198 const GURL& app_web_url,
199 bool enforce_feature_permissions,
200 const std::vector<int32_t>& feature_permissions,
201 const std::vector<std::string>&
202 additional_feature_permission_origins) override = 0;
Sean Topping077ba6d82021-11-02 22:48:42203 void SetGroupInfo(const std::string& session_id,
204 bool is_multizone_launch) override = 0;
Lukasz Anforowicz46cda462023-02-07 18:54:38205 void AddRendererFeatures(base::Value::Dict features) override = 0;
Sean Topping6c9e3932021-08-23 21:25:33206 void SetInterfacesForRenderer(mojo::PendingRemote<mojom::RemoteInterfaces>
207 remote_interfaces) override = 0;
Junbo Ke7f8623a2022-01-21 17:57:05208 void SetUrlRewriteRules(
209 url_rewrite::mojom::UrlRequestRewriteRulesPtr rules) override = 0;
Sean Topping92d0465b2021-07-16 01:11:33210 void LoadUrl(const GURL& url) override = 0;
211 void ClosePage() override = 0;
212 void SetWebVisibilityAndPaint(bool visible) override = 0;
213 void BlockMediaLoading(bool blocked) override = 0;
214 void BlockMediaStarting(bool blocked) override = 0;
215 void EnableBackgroundVideoPlayback(bool enabled) override = 0;
Sean Topping6c9e3932021-08-23 21:25:33216 void ConnectToBindingsService(
217 mojo::PendingRemote<mojom::ApiBindings> api_bindings_remote) override = 0;
Sean Topping92d0465b2021-07-16 01:11:33218 void SetEnabledForRemoteDebugging(bool enabled) override = 0;
219 void AddObserver(
220 mojo::PendingRemote<mojom::CastWebContentsObserver> observer) override;
Sean Topping6c9e3932021-08-23 21:25:33221 void GetMainFramePid(GetMainFramePidCallback cb) override = 0;
Sean Topping92d0465b2021-07-16 01:11:33222
Sean Topping0e8ac572019-01-30 03:05:43223 // ===========================================================================
Sean Topping0e8ac572019-01-30 03:05:43224 // Page Lifetime
225 // ===========================================================================
226
Sean Toppinge91b0972018-10-25 20:59:12227 // Stop the page immediately. This will automatically invoke
228 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21229 // reload the page without waiting for the WebContents owner to tear down the
230 // page.
Sean Toppinge91b0972018-10-25 20:59:12231 virtual void Stop(int error_code) = 0;
232
Sean Topping8a343862019-05-09 22:19:14233 // ===========================================================================
Jiawei Lidf9ad18a2019-07-07 05:31:02234 // Page Communication
235 // ===========================================================================
236
Jiawei Li3446cb72021-06-07 14:11:56237 // Executes a UTF-8 encoded |script| for every subsequent page load where
238 // the frame's URL has an origin reflected in |origins|. The script is
239 // executed early, prior to the execution of the document's scripts.
240 //
241 // Scripts are identified by a client-managed |id|. Any
242 // script previously injected using the same |id| will be replaced.
243 //
244 // The order in which multiple bindings are executed is the same as the
245 // order in which the bindings were added. If a script is added which
246 // clobbers an existing script of the same |id|, the previous script's
247 // precedence in the injection order will be preserved.
248 // |script| and |id| must be non-empty string.
249 virtual void AddBeforeLoadJavaScript(uint64_t id,
Helmut Januschka430ce472024-01-31 22:31:40250 std::string_view script) = 0;
Jiawei Li3446cb72021-06-07 14:11:56251
Jiawei Libba76072019-07-29 23:00:25252 // Posts a message to the frame's onMessage handler.
253 //
254 // `target_origin` restricts message delivery to the specified origin.
255 // If `target_origin` is "*", then the message will be sent to the
256 // document regardless of its origin.
257 // See html.spec.whatwg.org/multipage/web-messaging.html sect. 9.4.3
258 // for more details on how the target origin policy is applied.
259 // Should be called on UI thread.
Chris Hamilton825f2ed2020-01-30 21:46:41260 virtual void PostMessageToMainFrame(
261 const std::string& target_origin,
262 const std::string& data,
263 std::vector<blink::WebMessagePort> ports) = 0;
Jiawei Libba76072019-07-29 23:00:25264
Jiawei Li5283ad42020-03-27 21:26:05265 // Executes a string of JavaScript in the main frame's context.
266 // This is no-op if the main frame is not available.
267 // Pass in a callback to receive a result when it is available.
268 // If there is no need to receive the result, pass in a
269 // default-constructed callback. If provided, the callback
270 // will be invoked on the UI thread.
271 virtual void ExecuteJavaScript(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58272 const std::u16string& javascript,
Jiawei Li5283ad42020-03-27 21:26:05273 base::OnceCallback<void(base::Value)> callback) = 0;
274
Jiawei Lidf9ad18a2019-07-07 05:31:02275 // ===========================================================================
Sean Topping8a343862019-05-09 22:19:14276 // Utility Methods
277 // ===========================================================================
278
Ken Rockot48c7b502020-11-20 23:33:59279 // Asks the CastWebContents to bind an interface receiver using either its
280 // registry or any registered InterfaceProvider.
281 virtual bool TryBindReceiver(mojo::GenericPendingReceiver& receiver) = 0;
282
Sean Topping0436b462021-10-12 21:38:56283 // Locally-registered interfaces which are exposed to render frames.
284 virtual InterfaceBundle* local_interfaces() = 0;
285
Jiawei Lia64a082b2019-12-06 21:17:26286 // Returns true if WebSQL database is configured enabled for this
287 // CastWebContents.
288 virtual bool is_websql_enabled() = 0;
289
290 // Returns true if mixer audio is enabled.
291 virtual bool is_mixer_audio_enabled() = 0;
292
Sean Toppinge0c5a95c2021-11-12 23:13:49293 // Binds an owning receiver for remote control of CastWebContents. When the
294 // CastWebContents is managed by CastWebService, its lifetime is scoped to the
295 // duration of the connection. Only one owner can be bound at a time.
296 void BindOwnerReceiver(
297 mojo::PendingReceiver<mojom::CastWebContents> receiver);
298
299 // Binds a non-owning receiver for CastWebContents. This can be called by
300 // multiple clients.
301 void BindSharedReceiver(
302 mojo::PendingReceiver<mojom::CastWebContents> receiver);
Sean Topping92d0465b2021-07-16 01:11:33303
Sean Topping077ba6d82021-11-02 22:48:42304 // |cb| is called when |receiver_| is disconnected. This allows the web
305 // service to destroy CastWebContents which are owned via a remote handle.
306 void SetDisconnectCallback(base::OnceClosure cb);
307
Sean Topping92d0465b2021-07-16 01:11:33308 protected:
Sean Toppinge0c5a95c2021-11-12 23:13:49309 mojo::Receiver<mojom::CastWebContents> owner_receiver_{this};
310 mojo::ReceiverSet<mojom::CastWebContents> shared_receivers_;
Sean Topping92d0465b2021-07-16 01:11:33311 mojo::RemoteSet<mojom::CastWebContentsObserver> observers_;
Sean Topping6c9e3932021-08-23 21:25:33312 base::ObserverList<Observer> sync_observers_;
Sean Topping92d0465b2021-07-16 01:11:33313
Sean Toppinge91b0972018-10-25 20:59:12314 private:
Sean Topping92d0465b2021-07-16 01:11:33315 friend class Observer;
316
317 // These functions should only be invoked by CastWebContents::Observer in a
318 // valid sequence, enforced via SequenceChecker.
Sean Topping6c9e3932021-08-23 21:25:33319 void AddObserver(Observer* observer);
320 void RemoveObserver(Observer* observer);
Sean Topping077ba6d82021-11-02 22:48:42321
322 void OnDisconnect();
323
324 base::OnceClosure disconnect_cb_;
Sean Toppinge91b0972018-10-25 20:59:12325};
326
Sean Toppinge91b0972018-10-25 20:59:12327} // namespace chromecast
328
329#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_