blob: 96d1774ab4c7273ad736fee64c9a13bb9d8977b6 [file] [log] [blame]
Sean Toppinge91b0972018-10-25 20:59:121// Copyright 2018 The Chromium Authors. All rights reserved.
2// 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
Chad Duffin4aa9c042019-01-11 00:51:558#include <string>
9#include <vector>
10
Jiawei Lidf9ad18a2019-07-07 05:31:0211#include "base/callback.h"
Jiawei Li830fcfd2019-02-12 20:12:1712#include "base/containers/flat_set.h"
Chad Duffin4aa9c042019-01-11 00:51:5513#include "base/observer_list.h"
Zhaoxin2fe094a2020-02-11 23:35:4514#include "base/process/process.h"
Chad Duffin4aa9c042019-01-11 00:51:5515#include "chromecast/common/mojom/feature_manager.mojom.h"
Chih-Hsuan Kuo7b4fb102020-03-04 08:21:4916#include "content/public/common/media_playback_renderer_type.mojom.h"
Ken Rockot48c7b502020-11-20 23:33:5917#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
Jiawei Li830fcfd2019-02-12 20:12:1718#include "services/service_manager/public/cpp/binder_registry.h"
19#include "services/service_manager/public/cpp/interface_provider.h"
Anton Bikineev3f85f032021-05-15 17:58:2420#include "third_party/abseil-cpp/absl/types/optional.h"
Chris Hamilton825f2ed2020-01-30 21:46:4121#include "third_party/blink/public/common/messaging/web_message_port.h"
Sean Toppingf0a1d572019-06-17 23:03:4422#include "ui/gfx/geometry/rect.h"
Sean Toppinge91b0972018-10-25 20:59:1223#include "url/gurl.h"
24
Sean Topping2d4e54e2019-06-25 00:04:0425namespace blink {
26class AssociatedInterfaceProvider;
27} // namespace blink
28
Sean Toppinge91b0972018-10-25 20:59:1229namespace content {
Ryan Keane0d0493d2021-05-25 16:59:5530class NavigationHandle;
Sean Toppinge91b0972018-10-25 20:59:1231class WebContents;
32} // namespace content
33
Kevin Marshall3f693812020-08-07 17:45:3634namespace on_load_script_injector {
35template <typename>
36class OnLoadScriptInjectorHost;
37} // namespace on_load_script_injector
38
Sean Toppinge91b0972018-10-25 20:59:1239namespace chromecast {
40
Sean Topping0e8ac572019-01-30 03:05:4341struct RendererFeature {
42 const std::string name;
43 base::Value value;
44};
45
Sean Toppinge91b0972018-10-25 20:59:1246// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2147//
48// Proper usage of content::WebContents relies on understanding the meaning
49// behind various WebContentsObserver methods, and then translating those
50// signals into some concrete state. CastWebContents does *not* own the
51// underlying WebContents (usually whatever class implements
52// content::WebContentsDelegate is the actual owner).
53//
54// =============================================================================
55// Lifetime
56// =============================================================================
57// CastWebContents *must* be created before WebContents begins loading any
58// content. Once content begins loading (via CWC::LoadUrl() or one of the
59// WebContents navigation APIs), CastWebContents will calculate its state based
60// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
61// (e.g. iframes) are ignored, since we expect the web app to take care of
62// sub-frame errors.
63//
64// We consider the CastWebContents to be in a LOADED state when the content of
Jiawei Li042aaca2021-03-30 00:15:5365// the main frame is fully loaded and running (all resources fetched,
66// redirection finished, JS is running). Iframes might still be loading in this
67// case, but in general we consider the page to be in a presentable state at
68// this stage, so it is appropriate to display the WebContents to the user.
Sean Topping7414eed2019-04-10 23:04:2169//
70// During or after the page is loaded, there are multiple error conditions that
71// can occur. The following events will cause the page to enter an ERROR state:
72//
73// 1. If the main frame is served an HTTP error page (such as a 404 page), then
74// it means the desired content wasn't loaded.
75//
76// 2. If the main frame fails to load, such as when the browser blocked the URL
77// request, we treat this as an error.
78//
79// 3. The RenderProcess for the main frame could crash, so the page is not in a
80// usable state.
81//
82// The CastWebContents user can respond to these errors in a few ways: The
83// content can be reloaded, or the entire page activity can be cancelled. If we
84// totally cancel the activity, we prefer to notify the user with an error
85// screen or visible/audible error message. Otherwise, a silent retry is
86// preferred.
87//
88// CastWebContents can be used to close the underlying WebContents gracefully
89// via CWC::Close(). This initiates web page tear-down logic so that the web
90// app has a chance to perform its own finalization logic in JS. Next, we call
91// WebContents::ClosePage(), which defers the page closure logic to the
92// content::WebContentsDelegate. Usually, it will run its own finalization
93// logic and then destroy the WebContents. CastWebContents will be notified of
94// the WebContents destruction and enter the DESTROYED state. In the event
95// the page isn't destroyed, the page will enter the CLOSED state automatically
96// after a timeout. CastWebContents users should not try to reload the page, as
97// page closure is intentional.
98//
99// The web app may decide to close itself (such as via "window.close()" in JS).
100// This is similar to initiating the close flow via CWC::Close(), with the end
101// result being the same. We consider this an intentional closure, and should
102// not attempt to reload the page.
103//
104// Once CastWebContents is in the DESTROYED state, it is not really usable
105// anymore; most of the methods will simply no-op, and no more observer signals
106// will be emitted.
107//
108// CastWebContents can be deleted at any time, *except* during Observer
109// notifications. If the owner wants to destroy CastWebContents as a result of
110// an Observer event, it should post a task to destroy CastWebContents.
Sean Toppinge91b0972018-10-25 20:59:12111class CastWebContents {
112 public:
113 class Delegate {
114 public:
Sean Toppingf0a1d572019-06-17 23:03:44115 // Notify that an inner WebContents was created. |inner_contents| is created
116 // in a default-initialized state with no delegate, and can be safely
117 // initialized by the delegate.
118 virtual void InnerContentsCreated(CastWebContents* inner_contents,
119 CastWebContents* outer_contents) {}
120
121 protected:
122 virtual ~Delegate() {}
123 };
124
125 // Observer class. The Observer should *not* destroy CastWebContents during
126 // any of these events, otherwise other observers might try to use a freed
127 // pointer to |cast_web_contents|.
128 class Observer {
129 public:
130 Observer();
131
Sean Toppinge91b0972018-10-25 20:59:12132 // Advertises page state for the CastWebContents.
133 // Use CastWebContents::page_state() to get the new state.
Sean Toppingf0a1d572019-06-17 23:03:44134 virtual void OnPageStateChanged(CastWebContents* cast_web_contents) {}
Sean Toppinge91b0972018-10-25 20:59:12135
136 // Called when the page has stopped. e.g.: A 404 occurred when loading the
137 // page or if the render process for the main frame crashes. |error_code|
138 // will return a net::Error describing the failure, or net::OK if the page
Sean Topping7414eed2019-04-10 23:04:21139 // closed intentionally.
Sean Toppinge91b0972018-10-25 20:59:12140 //
141 // After this method, the page state will be one of the following:
Sean Topping7414eed2019-04-10 23:04:21142 // CLOSED: Page was closed as expected and the WebContents exists. The page
143 // should generally not be reloaded, since the page closure was
144 // triggered intentionally.
145 // ERROR: Page is in an error state. It should be reloaded or deleted.
Sean Toppinge91b0972018-10-25 20:59:12146 // DESTROYED: Page was closed due to deletion of WebContents. The
147 // CastWebContents instance is no longer usable and should be deleted.
Sean Toppinge91b0972018-10-25 20:59:12148 virtual void OnPageStopped(CastWebContents* cast_web_contents,
Sean Toppingf0a1d572019-06-17 23:03:44149 int error_code) {}
Sean Toppinge91b0972018-10-25 20:59:12150
Sean Toppingf0a1d572019-06-17 23:03:44151 // A new RenderFrame was created for the WebContents. |frame_interfaces| are
152 // provided by the new frame.
153 virtual void RenderFrameCreated(
154 int render_process_id,
155 int render_frame_id,
Sean Topping2d4e54e2019-06-25 00:04:04156 service_manager::InterfaceProvider* frame_interfaces,
157 blink::AssociatedInterfaceProvider* frame_associated_interfaces) {}
Chad Duffin4aa9c042019-01-11 00:51:55158
Ryan Keane0d0493d2021-05-25 16:59:55159 // Called when the navigation is ready to be committed in the WebContents'
160 // main frame.
161 virtual void MainFrameReadyToCommitNavigation(
162 content::NavigationHandle* navigation_handle) {}
163
Jiawei Lic3354ee2019-12-13 23:48:35164 // A navigation has finished in the WebContents' main frame.
165 virtual void MainFrameFinishedNavigation() {}
166
Sean Toppingf0a1d572019-06-17 23:03:44167 // These methods are calls forwarded from WebContentsObserver.
168 virtual void MainFrameResized(const gfx::Rect& bounds) {}
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58169 virtual void UpdateTitle(const std::u16string& title) {}
Sean Toppingf0a1d572019-06-17 23:03:44170 virtual void UpdateFaviconURL(GURL icon_url) {}
Sean Toppingf0a1d572019-06-17 23:03:44171 virtual void DidFirstVisuallyNonEmptyPaint() {}
Chad Duffin4aa9c042019-01-11 00:51:55172
Sean Topping7414eed2019-04-10 23:04:21173 // Notifies that a resource for the main frame failed to load.
174 virtual void ResourceLoadFailed(CastWebContents* cast_web_contents) {}
175
Zhaoxin2fe094a2020-02-11 23:35:45176 // Propagates the process information via observer, in particular to
177 // the underlying OnRendererProcessStarted() method.
178 virtual void OnRenderProcessReady(const base::Process& process) {}
179
Sean Toppinge8648a22020-04-29 18:41:00180 // Notify media playback state changes for the underlying WebContents.
181 virtual void MediaPlaybackChanged(bool media_playing) {}
182
Chad Duffin4aa9c042019-01-11 00:51:55183 // Adds |this| to the ObserverList in the implementation of
184 // |cast_web_contents|.
185 void Observe(CastWebContents* cast_web_contents);
186
187 // Removes |this| from the ObserverList in the implementation of
188 // |cast_web_contents_|. This is only invoked by CastWebContents and is used
189 // to ensure that once the observed CastWebContents object is destructed the
190 // CastWebContents::Observer does not invoke any additional function calls
191 // on it.
192 void ResetCastWebContents();
193
194 protected:
195 virtual ~Observer();
196
197 CastWebContents* cast_web_contents_;
198 };
199
Sean Toppingf0a1d572019-06-17 23:03:44200 enum class BackgroundColor {
201 NONE,
202 WHITE,
203 BLACK,
204 TRANSPARENT,
205 };
206
Sean Topping7414eed2019-04-10 23:04:21207 // Initialization parameters for CastWebContents.
Sean Topping0e8ac572019-01-30 03:05:43208 struct InitParams {
Sean Toppingeda675e2019-11-07 22:29:04209 // The delegate for the CastWebContents. Must be non-null. If the delegate
210 // is destroyed before CastWebContents, the WeakPtr will be invalidated on
211 // the main UI thread.
212 base::WeakPtr<Delegate> delegate = nullptr;
Jiawei Lia64a082b2019-12-06 21:17:26213 // Enable development mode for this CastWebContents. Whitelists
Sean Topping8a343862019-05-09 22:19:14214 // certain functionality for the WebContents, like remote debugging and
215 // debugging interfaces.
216 bool enabled_for_dev = false;
Sean Topping7414eed2019-04-10 23:04:21217 // Chooses a media renderer for the WebContents.
Chih-Hsuan Kuo7b4fb102020-03-04 08:21:49218 content::mojom::RendererType renderer_type =
219 content::mojom::RendererType::DEFAULT_RENDERER;
Sean Topping7414eed2019-04-10 23:04:21220 // Whether the WebContents is a root native window, or if it is embedded in
221 // another WebContents (see Delegate::InnerContentsCreated()).
Sean Topping6735aaf2019-03-20 19:20:12222 bool is_root_window = false;
Sean Topping8a343862019-05-09 22:19:14223 // Whether inner WebContents events should be handled. If this is set to
224 // true, then inner WebContents will automatically have a CastWebContents
225 // created and notify the delegate.
226 bool handle_inner_contents = false;
227 // Construct internal media blocker and enable BlockMediaLoading().
228 bool use_media_blocker = false;
Sean Toppingf0a1d572019-06-17 23:03:44229 // Background color for the WebContents view. If not provided, the color
230 // will fall back to the platform default.
231 BackgroundColor background_color = BackgroundColor::NONE;
Jiawei Lia64a082b2019-12-06 21:17:26232 // Enable WebSQL database for this CastWebContents.
233 bool enable_websql = false;
234 // Enable mixer audio support for this CastWebContents.
235 bool enable_mixer_audio = false;
Jiaqi Han9ea54f92020-02-20 23:44:59236 // Whether to provide a URL filter applied to network requests for the
237 // activity hosted by this CastWebContents.
238 // No filters implies no restrictions.
Anton Bikineev3f85f032021-05-15 17:58:24239 absl::optional<std::vector<std::string>> url_filters = absl::nullopt;
Peter Qiu90dfc9a2021-02-10 18:39:23240 // Whether WebRTC peer connections are allowed to use legacy versions of the
241 // TLS/DTLS protocols.
242 bool webrtc_allow_legacy_tls_protocols = false;
Sean Toppingeda675e2019-11-07 22:29:04243
244 InitParams();
245 InitParams(const InitParams& other);
246 ~InitParams();
Sean Topping0e8ac572019-01-30 03:05:43247 };
248
Sean Toppinge91b0972018-10-25 20:59:12249 // Page state for the main frame.
250 enum class PageState {
251 IDLE, // Main frame has not started yet.
252 LOADING, // Main frame is loading resources.
253 LOADED, // Main frame is loaded, but sub-frames may still be loading.
254 CLOSED, // Page is closed and should be cleaned up.
255 DESTROYED, // The WebContents is destroyed and can no longer be used.
256 ERROR, // Main frame is in an error state.
257 };
258
Sean Topping6735aaf2019-03-20 19:20:12259 static std::vector<CastWebContents*>& GetAll();
260
Jiawei Lia64a082b2019-12-06 21:17:26261 // Returns the CastWebContents that wraps the content::WebContents, or nullptr
262 // if the CastWebContents does not exist.
263 static CastWebContents* FromWebContents(content::WebContents* web_contents);
264
Sean Toppinge91b0972018-10-25 20:59:12265 CastWebContents() = default;
266 virtual ~CastWebContents() = default;
267
Sean Topping6735aaf2019-03-20 19:20:12268 // Tab identifier for the WebContents, mainly used by the tabs extension API.
269 // Tab IDs may be re-used, but no two live CastWebContents should have the
270 // same tab ID at any given time.
271 virtual int tab_id() const = 0;
272
Randy Rossic6bb3ab2020-08-11 18:02:52273 // An identifier for the WebContents, mainly used by platform views service.
274 // IDs may be re-used but are unique among all live CastWebContents.
275 virtual int id() const = 0;
276
Sean Topping0e8ac572019-01-30 03:05:43277 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12278 virtual content::WebContents* web_contents() const = 0;
279 virtual PageState page_state() const = 0;
280
Jiawei Lic3354ee2019-12-13 23:48:35281 // Returns the PID of the main frame process if valid.
Anton Bikineev3f85f032021-05-15 17:58:24282 virtual absl::optional<pid_t> GetMainFrameRenderProcessPid() const = 0;
Jiawei Lic3354ee2019-12-13 23:48:35283
Sean Topping0e8ac572019-01-30 03:05:43284 // ===========================================================================
285 // Initialization and Setup
286 // ===========================================================================
287
Sean Topping0e8ac572019-01-30 03:05:43288 // Add a set of features for all renderers in the WebContents. Features are
289 // configured when `CastWebContents::RenderFrameCreated` is invoked.
290 virtual void AddRendererFeatures(std::vector<RendererFeature> features) = 0;
291
292 virtual void AllowWebAndMojoWebUiBindings() = 0;
293 virtual void ClearRenderWidgetHostView() = 0;
294
Sean Topping805f50e2021-05-21 00:55:47295 // Associates transparent app properties to a given session ID. This data is
296 // used elsewhere in the browser to gate output stream selection. We expose
297 // this API on CastWebContents for the sake of convenience.
298 virtual void SetAppProperties(const std::string& session_id,
299 bool is_audio_app) = 0;
300
Sean Topping0e8ac572019-01-30 03:05:43301 // ===========================================================================
302 // Page Lifetime
303 // ===========================================================================
304
Sean Toppinge91b0972018-10-25 20:59:12305 // Navigates the underlying WebContents to |url|. Delegate will be notified of
306 // page progression events via OnPageStateChanged().
307 virtual void LoadUrl(const GURL& url) = 0;
308
309 // Initiate closure of the page. This invokes the appropriate unload handlers.
310 // Eventually the delegate will be notified with OnPageStopped().
311 virtual void ClosePage() = 0;
312
313 // Stop the page immediately. This will automatically invoke
314 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21315 // reload the page without waiting for the WebContents owner to tear down the
316 // page.
Sean Toppinge91b0972018-10-25 20:59:12317 virtual void Stop(int error_code) = 0;
318
Sean Topping8a343862019-05-09 22:19:14319 // ===========================================================================
Sean Toppinga0a0f5e2020-03-19 00:22:30320 // Visibility
321 // ===========================================================================
322
323 // Specify if the WebContents should be treated as visible. This triggers a
324 // document "visibilitychange" change event, and will paint the WebContents
325 // quad if |visible| is true (otherwise it will be blank). Note that this does
326 // *not* guarantee the page is visible on the screen, as that depends on if
327 // the WebContents quad is present in the screen layout and isn't obscured by
328 // another window.
329 virtual void SetWebVisibilityAndPaint(bool visible) = 0;
330
331 // ===========================================================================
Sean Topping8a343862019-05-09 22:19:14332 // Media Management
333 // ===========================================================================
334
335 // Block/unblock media from loading in all RenderFrames for the WebContents.
336 virtual void BlockMediaLoading(bool blocked) = 0;
Andres Medinaa65ad1b2019-06-26 22:18:19337 // Block/unblock media from starting in all RenderFrames for the WebContents.
338 // As opposed to |BlockMediaLoading|, |BlockMediaStarting| allows media to
339 // load while in blocking state.
340 virtual void BlockMediaStarting(bool blocked) = 0;
Sean Topping8a343862019-05-09 22:19:14341 virtual void EnableBackgroundVideoPlayback(bool enabled) = 0;
342
343 // ===========================================================================
Jiawei Lidf9ad18a2019-07-07 05:31:02344 // Page Communication
345 // ===========================================================================
346
Kevin Marshall6f8f04b2020-08-05 18:48:14347 // Returns the script injector instance, which injects scripts at page load
348 // time.
Jiawei Li0b1efea2020-08-12 03:30:57349 virtual on_load_script_injector::OnLoadScriptInjectorHost<std::string>*
Kevin Marshall6f8f04b2020-08-05 18:48:14350 script_injector() = 0;
Jiawei Lidf9ad18a2019-07-07 05:31:02351
Jiawei Libba76072019-07-29 23:00:25352 // Posts a message to the frame's onMessage handler.
353 //
354 // `target_origin` restricts message delivery to the specified origin.
355 // If `target_origin` is "*", then the message will be sent to the
356 // document regardless of its origin.
357 // See html.spec.whatwg.org/multipage/web-messaging.html sect. 9.4.3
358 // for more details on how the target origin policy is applied.
359 // Should be called on UI thread.
Chris Hamilton825f2ed2020-01-30 21:46:41360 virtual void PostMessageToMainFrame(
361 const std::string& target_origin,
362 const std::string& data,
363 std::vector<blink::WebMessagePort> ports) = 0;
Jiawei Libba76072019-07-29 23:00:25364
Jiawei Li5283ad42020-03-27 21:26:05365 // Executes a string of JavaScript in the main frame's context.
366 // This is no-op if the main frame is not available.
367 // Pass in a callback to receive a result when it is available.
368 // If there is no need to receive the result, pass in a
369 // default-constructed callback. If provided, the callback
370 // will be invoked on the UI thread.
371 virtual void ExecuteJavaScript(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58372 const std::u16string& javascript,
Jiawei Li5283ad42020-03-27 21:26:05373 base::OnceCallback<void(base::Value)> callback) = 0;
374
Jiawei Lidf9ad18a2019-07-07 05:31:02375 // ===========================================================================
Sean Topping8a343862019-05-09 22:19:14376 // Utility Methods
377 // ===========================================================================
378
Chad Duffin4aa9c042019-01-11 00:51:55379 // Used to add or remove |observer| to the ObserverList in the implementation.
380 // These functions should only be invoked by CastWebContents::Observer in a
381 // valid sequence, enforced via SequenceChecker.
382 virtual void AddObserver(Observer* observer) = 0;
383 virtual void RemoveObserver(Observer* observer) = 0;
384
Ryan Daum52c9f7132020-04-06 21:23:34385 // Enable or disable devtools remote debugging for this WebContents and any
386 // inner WebContents that are spawned from it.
387 virtual void SetEnabledForRemoteDebugging(bool enabled) = 0;
388
Jiawei Li830fcfd2019-02-12 20:12:17389 // Used to expose CastWebContents's |binder_registry_| to Delegate.
390 // Delegate should register its mojo interface binders via this function
391 // when it is ready.
392 virtual service_manager::BinderRegistry* binder_registry() = 0;
393
Ken Rockot48c7b502020-11-20 23:33:59394 // Asks the CastWebContents to bind an interface receiver using either its
395 // registry or any registered InterfaceProvider.
396 virtual bool TryBindReceiver(mojo::GenericPendingReceiver& receiver) = 0;
397
Julie Jeongeun Kim641f4752019-12-04 01:53:22398 // Used for owner to pass its |InterfaceProvider| pointers to CastWebContents.
399 // It is owner's responsibility to make sure each |InterfaceProvider| pointer
400 // has distinct mojo interface set.
Jiawei Li830fcfd2019-02-12 20:12:17401 using InterfaceSet = base::flat_set<std::string>;
402 virtual void RegisterInterfaceProvider(
403 const InterfaceSet& interface_set,
404 service_manager::InterfaceProvider* interface_provider) = 0;
405
Jiawei Lia64a082b2019-12-06 21:17:26406 // Returns true if WebSQL database is configured enabled for this
407 // CastWebContents.
408 virtual bool is_websql_enabled() = 0;
409
410 // Returns true if mixer audio is enabled.
411 virtual bool is_mixer_audio_enabled() = 0;
412
Sean Toppingabf3be592020-03-11 23:20:35413 // Returns whether or not CastWebContents binder_registry() is valid for
414 // binding interfaces.
415 virtual bool can_bind_interfaces() = 0;
416
Sean Toppinge91b0972018-10-25 20:59:12417 private:
418 DISALLOW_COPY_AND_ASSIGN(CastWebContents);
419};
420
421std::ostream& operator<<(std::ostream& os, CastWebContents::PageState state);
422
423} // namespace chromecast
424
425#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_