blob: 5724ada93e36f376ac8fc04292589d572ab311a7 [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"
Sean Topping0e8ac572019-01-30 03:05:4314#include "base/optional.h"
Zhaoxin2fe094a2020-02-11 23:35:4515#include "base/process/process.h"
Sean Toppingf0a1d572019-06-17 23:03:4416#include "base/strings/string16.h"
Jiawei Lidf9ad18a2019-07-07 05:31:0217#include "base/strings/string_piece_forward.h"
Chad Duffin4aa9c042019-01-11 00:51:5518#include "chromecast/common/mojom/feature_manager.mojom.h"
Chih-Hsuan Kuo7b4fb102020-03-04 08:21:4919#include "content/public/common/media_playback_renderer_type.mojom.h"
Jiawei Li830fcfd2019-02-12 20:12:1720#include "services/service_manager/public/cpp/binder_registry.h"
21#include "services/service_manager/public/cpp/interface_provider.h"
Chris Hamilton825f2ed2020-01-30 21:46:4122#include "third_party/blink/public/common/messaging/web_message_port.h"
Sean Toppingf0a1d572019-06-17 23:03:4423#include "ui/gfx/geometry/rect.h"
Sean Toppinge91b0972018-10-25 20:59:1224#include "url/gurl.h"
25
Sean Topping2d4e54e2019-06-25 00:04:0426namespace blink {
27class AssociatedInterfaceProvider;
28} // namespace blink
29
Kevin Marshall6f8f04b2020-08-05 18:48:1430namespace on_load_script_injector {
31class OnLoadScriptInjectorHost;
32} // namespace on_load_script_injector
33
Sean Toppinge91b0972018-10-25 20:59:1234namespace content {
35class WebContents;
36} // namespace content
37
38namespace chromecast {
39
Jiawei Li0565a2f2019-12-07 01:26:0140class QueryableDataHost;
41
Sean Topping0e8ac572019-01-30 03:05:4342struct RendererFeature {
43 const std::string name;
44 base::Value value;
45};
46
Sean Toppinge91b0972018-10-25 20:59:1247// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2148//
49// Proper usage of content::WebContents relies on understanding the meaning
50// behind various WebContentsObserver methods, and then translating those
51// signals into some concrete state. CastWebContents does *not* own the
52// underlying WebContents (usually whatever class implements
53// content::WebContentsDelegate is the actual owner).
54//
55// =============================================================================
56// Lifetime
57// =============================================================================
58// CastWebContents *must* be created before WebContents begins loading any
59// content. Once content begins loading (via CWC::LoadUrl() or one of the
60// WebContents navigation APIs), CastWebContents will calculate its state based
61// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
62// (e.g. iframes) are ignored, since we expect the web app to take care of
63// sub-frame errors.
64//
65// We consider the CastWebContents to be in a LOADED state when the content of
66// the main frame is fully loaded and running (all resources fetched, JS is
67// running). Iframes might still be loading in this case, but in general we
Sean Toppingeda675e2019-11-07 22:29:0468// consider the page to be in a presentable state at this stage, so it is
Sean Topping7414eed2019-04-10 23:04:2169// appropriate to display the WebContents to the user.
70//
71// During or after the page is loaded, there are multiple error conditions that
72// can occur. The following events will cause the page to enter an ERROR state:
73//
74// 1. If the main frame is served an HTTP error page (such as a 404 page), then
75// it means the desired content wasn't loaded.
76//
77// 2. If the main frame fails to load, such as when the browser blocked the URL
78// request, we treat this as an error.
79//
80// 3. The RenderProcess for the main frame could crash, so the page is not in a
81// usable state.
82//
83// The CastWebContents user can respond to these errors in a few ways: The
84// content can be reloaded, or the entire page activity can be cancelled. If we
85// totally cancel the activity, we prefer to notify the user with an error
86// screen or visible/audible error message. Otherwise, a silent retry is
87// preferred.
88//
89// CastWebContents can be used to close the underlying WebContents gracefully
90// via CWC::Close(). This initiates web page tear-down logic so that the web
91// app has a chance to perform its own finalization logic in JS. Next, we call
92// WebContents::ClosePage(), which defers the page closure logic to the
93// content::WebContentsDelegate. Usually, it will run its own finalization
94// logic and then destroy the WebContents. CastWebContents will be notified of
95// the WebContents destruction and enter the DESTROYED state. In the event
96// the page isn't destroyed, the page will enter the CLOSED state automatically
97// after a timeout. CastWebContents users should not try to reload the page, as
98// page closure is intentional.
99//
100// The web app may decide to close itself (such as via "window.close()" in JS).
101// This is similar to initiating the close flow via CWC::Close(), with the end
102// result being the same. We consider this an intentional closure, and should
103// not attempt to reload the page.
104//
105// Once CastWebContents is in the DESTROYED state, it is not really usable
106// anymore; most of the methods will simply no-op, and no more observer signals
107// will be emitted.
108//
109// CastWebContents can be deleted at any time, *except* during Observer
110// notifications. If the owner wants to destroy CastWebContents as a result of
111// an Observer event, it should post a task to destroy CastWebContents.
Sean Toppinge91b0972018-10-25 20:59:12112class CastWebContents {
113 public:
114 class Delegate {
115 public:
Sean Toppingf0a1d572019-06-17 23:03:44116 // Notify that an inner WebContents was created. |inner_contents| is created
117 // in a default-initialized state with no delegate, and can be safely
118 // initialized by the delegate.
119 virtual void InnerContentsCreated(CastWebContents* inner_contents,
120 CastWebContents* outer_contents) {}
121
122 protected:
123 virtual ~Delegate() {}
124 };
125
126 // Observer class. The Observer should *not* destroy CastWebContents during
127 // any of these events, otherwise other observers might try to use a freed
128 // pointer to |cast_web_contents|.
129 class Observer {
130 public:
131 Observer();
132
Sean Toppinge91b0972018-10-25 20:59:12133 // Advertises page state for the CastWebContents.
134 // Use CastWebContents::page_state() to get the new state.
Sean Toppingf0a1d572019-06-17 23:03:44135 virtual void OnPageStateChanged(CastWebContents* cast_web_contents) {}
Sean Toppinge91b0972018-10-25 20:59:12136
137 // Called when the page has stopped. e.g.: A 404 occurred when loading the
138 // page or if the render process for the main frame crashes. |error_code|
139 // will return a net::Error describing the failure, or net::OK if the page
Sean Topping7414eed2019-04-10 23:04:21140 // closed intentionally.
Sean Toppinge91b0972018-10-25 20:59:12141 //
142 // After this method, the page state will be one of the following:
Sean Topping7414eed2019-04-10 23:04:21143 // CLOSED: Page was closed as expected and the WebContents exists. The page
144 // should generally not be reloaded, since the page closure was
145 // triggered intentionally.
146 // ERROR: Page is in an error state. It should be reloaded or deleted.
Sean Toppinge91b0972018-10-25 20:59:12147 // DESTROYED: Page was closed due to deletion of WebContents. The
148 // CastWebContents instance is no longer usable and should be deleted.
Sean Toppinge91b0972018-10-25 20:59:12149 virtual void OnPageStopped(CastWebContents* cast_web_contents,
Sean Toppingf0a1d572019-06-17 23:03:44150 int error_code) {}
Sean Toppinge91b0972018-10-25 20:59:12151
Sean Toppingf0a1d572019-06-17 23:03:44152 // A new RenderFrame was created for the WebContents. |frame_interfaces| are
153 // provided by the new frame.
154 virtual void RenderFrameCreated(
155 int render_process_id,
156 int render_frame_id,
Sean Topping2d4e54e2019-06-25 00:04:04157 service_manager::InterfaceProvider* frame_interfaces,
158 blink::AssociatedInterfaceProvider* frame_associated_interfaces) {}
Chad Duffin4aa9c042019-01-11 00:51:55159
Jiawei Lic3354ee2019-12-13 23:48:35160 // A navigation has finished in the WebContents' main frame.
161 virtual void MainFrameFinishedNavigation() {}
162
Sean Toppingf0a1d572019-06-17 23:03:44163 // These methods are calls forwarded from WebContentsObserver.
164 virtual void MainFrameResized(const gfx::Rect& bounds) {}
165 virtual void UpdateTitle(const base::string16& title) {}
166 virtual void UpdateFaviconURL(GURL icon_url) {}
167 virtual void DidFinishBlockedNavigation(GURL url) {}
168 virtual void DidFirstVisuallyNonEmptyPaint() {}
Chad Duffin4aa9c042019-01-11 00:51:55169
Sean Topping7414eed2019-04-10 23:04:21170 // Notifies that a resource for the main frame failed to load.
171 virtual void ResourceLoadFailed(CastWebContents* cast_web_contents) {}
172
Zhaoxin2fe094a2020-02-11 23:35:45173 // Propagates the process information via observer, in particular to
174 // the underlying OnRendererProcessStarted() method.
175 virtual void OnRenderProcessReady(const base::Process& process) {}
176
Sean Toppinge8648a22020-04-29 18:41:00177 // Notify media playback state changes for the underlying WebContents.
178 virtual void MediaPlaybackChanged(bool media_playing) {}
179
Chad Duffin4aa9c042019-01-11 00:51:55180 // Adds |this| to the ObserverList in the implementation of
181 // |cast_web_contents|.
182 void Observe(CastWebContents* cast_web_contents);
183
184 // Removes |this| from the ObserverList in the implementation of
185 // |cast_web_contents_|. This is only invoked by CastWebContents and is used
186 // to ensure that once the observed CastWebContents object is destructed the
187 // CastWebContents::Observer does not invoke any additional function calls
188 // on it.
189 void ResetCastWebContents();
190
191 protected:
192 virtual ~Observer();
193
194 CastWebContents* cast_web_contents_;
195 };
196
Sean Toppingf0a1d572019-06-17 23:03:44197 enum class BackgroundColor {
198 NONE,
199 WHITE,
200 BLACK,
201 TRANSPARENT,
202 };
203
Sean Topping7414eed2019-04-10 23:04:21204 // Initialization parameters for CastWebContents.
Sean Topping0e8ac572019-01-30 03:05:43205 struct InitParams {
Sean Toppingeda675e2019-11-07 22:29:04206 // The delegate for the CastWebContents. Must be non-null. If the delegate
207 // is destroyed before CastWebContents, the WeakPtr will be invalidated on
208 // the main UI thread.
209 base::WeakPtr<Delegate> delegate = nullptr;
Jiawei Lia64a082b2019-12-06 21:17:26210 // Enable development mode for this CastWebContents. Whitelists
Sean Topping8a343862019-05-09 22:19:14211 // certain functionality for the WebContents, like remote debugging and
212 // debugging interfaces.
213 bool enabled_for_dev = false;
Sean Topping7414eed2019-04-10 23:04:21214 // Chooses a media renderer for the WebContents.
Chih-Hsuan Kuo7b4fb102020-03-04 08:21:49215 content::mojom::RendererType renderer_type =
216 content::mojom::RendererType::DEFAULT_RENDERER;
Sean Topping7414eed2019-04-10 23:04:21217 // Whether the WebContents is a root native window, or if it is embedded in
218 // another WebContents (see Delegate::InnerContentsCreated()).
Sean Topping6735aaf2019-03-20 19:20:12219 bool is_root_window = false;
Sean Topping8a343862019-05-09 22:19:14220 // Whether inner WebContents events should be handled. If this is set to
221 // true, then inner WebContents will automatically have a CastWebContents
222 // created and notify the delegate.
223 bool handle_inner_contents = false;
224 // Construct internal media blocker and enable BlockMediaLoading().
225 bool use_media_blocker = false;
Sean Toppingf0a1d572019-06-17 23:03:44226 // Background color for the WebContents view. If not provided, the color
227 // will fall back to the platform default.
228 BackgroundColor background_color = BackgroundColor::NONE;
Jiawei Lia64a082b2019-12-06 21:17:26229 // Enable WebSQL database for this CastWebContents.
230 bool enable_websql = false;
231 // Enable mixer audio support for this CastWebContents.
232 bool enable_mixer_audio = false;
Jiawei Li0565a2f2019-12-07 01:26:01233 // Whether to provide a QueryableDataHost for this CastWebContents.
234 // Clients can use it to send queryable values to the render frames.
235 // queryable_data_host() will return a nullptr if this is false.
236 bool enable_queryable_data_host = false;
Jiaqi Han9ea54f92020-02-20 23:44:59237 // Whether to provide a URL filter applied to network requests for the
238 // activity hosted by this CastWebContents.
239 // No filters implies no restrictions.
240 base::Optional<std::vector<std::string>> url_filters = base::nullopt;
Sean Toppingeda675e2019-11-07 22:29:04241
242 InitParams();
243 InitParams(const InitParams& other);
244 ~InitParams();
Sean Topping0e8ac572019-01-30 03:05:43245 };
246
Sean Toppinge91b0972018-10-25 20:59:12247 // Page state for the main frame.
248 enum class PageState {
249 IDLE, // Main frame has not started yet.
250 LOADING, // Main frame is loading resources.
251 LOADED, // Main frame is loaded, but sub-frames may still be loading.
252 CLOSED, // Page is closed and should be cleaned up.
253 DESTROYED, // The WebContents is destroyed and can no longer be used.
254 ERROR, // Main frame is in an error state.
255 };
256
Sean Topping6735aaf2019-03-20 19:20:12257 static std::vector<CastWebContents*>& GetAll();
258
Jiawei Lia64a082b2019-12-06 21:17:26259 // Returns the CastWebContents that wraps the content::WebContents, or nullptr
260 // if the CastWebContents does not exist.
261 static CastWebContents* FromWebContents(content::WebContents* web_contents);
262
Sean Toppinge91b0972018-10-25 20:59:12263 CastWebContents() = default;
264 virtual ~CastWebContents() = default;
265
Sean Topping6735aaf2019-03-20 19:20:12266 // Tab identifier for the WebContents, mainly used by the tabs extension API.
267 // Tab IDs may be re-used, but no two live CastWebContents should have the
268 // same tab ID at any given time.
269 virtual int tab_id() const = 0;
270
Sean Topping0e8ac572019-01-30 03:05:43271 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12272 virtual content::WebContents* web_contents() const = 0;
273 virtual PageState page_state() const = 0;
274
Jiawei Li0565a2f2019-12-07 01:26:01275 // Returns QueryableDataHost that is used to push values to the renderer.
276 // Returns nullptr if the new queryable data bindings is enabled.
277 virtual QueryableDataHost* queryable_data_host() const = 0;
278
Jiawei Lic3354ee2019-12-13 23:48:35279 // Returns the PID of the main frame process if valid.
280 virtual base::Optional<pid_t> GetMainFrameRenderProcessPid() const = 0;
281
Sean Topping0e8ac572019-01-30 03:05:43282 // ===========================================================================
283 // Initialization and Setup
284 // ===========================================================================
285
Sean Topping0e8ac572019-01-30 03:05:43286 // Add a set of features for all renderers in the WebContents. Features are
287 // configured when `CastWebContents::RenderFrameCreated` is invoked.
288 virtual void AddRendererFeatures(std::vector<RendererFeature> features) = 0;
289
290 virtual void AllowWebAndMojoWebUiBindings() = 0;
291 virtual void ClearRenderWidgetHostView() = 0;
292
293 // ===========================================================================
294 // Page Lifetime
295 // ===========================================================================
296
Sean Toppinge91b0972018-10-25 20:59:12297 // Navigates the underlying WebContents to |url|. Delegate will be notified of
298 // page progression events via OnPageStateChanged().
299 virtual void LoadUrl(const GURL& url) = 0;
300
301 // Initiate closure of the page. This invokes the appropriate unload handlers.
302 // Eventually the delegate will be notified with OnPageStopped().
303 virtual void ClosePage() = 0;
304
305 // Stop the page immediately. This will automatically invoke
306 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21307 // reload the page without waiting for the WebContents owner to tear down the
308 // page.
Sean Toppinge91b0972018-10-25 20:59:12309 virtual void Stop(int error_code) = 0;
310
Sean Topping8a343862019-05-09 22:19:14311 // ===========================================================================
Sean Toppinga0a0f5e2020-03-19 00:22:30312 // Visibility
313 // ===========================================================================
314
315 // Specify if the WebContents should be treated as visible. This triggers a
316 // document "visibilitychange" change event, and will paint the WebContents
317 // quad if |visible| is true (otherwise it will be blank). Note that this does
318 // *not* guarantee the page is visible on the screen, as that depends on if
319 // the WebContents quad is present in the screen layout and isn't obscured by
320 // another window.
321 virtual void SetWebVisibilityAndPaint(bool visible) = 0;
322
323 // ===========================================================================
Sean Topping8a343862019-05-09 22:19:14324 // Media Management
325 // ===========================================================================
326
327 // Block/unblock media from loading in all RenderFrames for the WebContents.
328 virtual void BlockMediaLoading(bool blocked) = 0;
Andres Medinaa65ad1b2019-06-26 22:18:19329 // Block/unblock media from starting in all RenderFrames for the WebContents.
330 // As opposed to |BlockMediaLoading|, |BlockMediaStarting| allows media to
331 // load while in blocking state.
332 virtual void BlockMediaStarting(bool blocked) = 0;
Sean Topping8a343862019-05-09 22:19:14333 virtual void EnableBackgroundVideoPlayback(bool enabled) = 0;
334
335 // ===========================================================================
Jiawei Lidf9ad18a2019-07-07 05:31:02336 // Page Communication
337 // ===========================================================================
338
Kevin Marshall6f8f04b2020-08-05 18:48:14339 // Returns the script injector instance, which injects scripts at page load
340 // time.
341 virtual on_load_script_injector::OnLoadScriptInjectorHost*
342 script_injector() = 0;
Jiawei Lidf9ad18a2019-07-07 05:31:02343
Kevin Marshall6f8f04b2020-08-05 18:48:14344 // Injects on-load scripts into the WebContents' main frame.
345 virtual void InjectScriptsIntoMainFrame() = 0;
Jiawei Lidf9ad18a2019-07-07 05:31:02346
Jiawei Libba76072019-07-29 23:00:25347 // Posts a message to the frame's onMessage handler.
348 //
349 // `target_origin` restricts message delivery to the specified origin.
350 // If `target_origin` is "*", then the message will be sent to the
351 // document regardless of its origin.
352 // See html.spec.whatwg.org/multipage/web-messaging.html sect. 9.4.3
353 // for more details on how the target origin policy is applied.
354 // Should be called on UI thread.
Chris Hamilton825f2ed2020-01-30 21:46:41355 virtual void PostMessageToMainFrame(
356 const std::string& target_origin,
357 const std::string& data,
358 std::vector<blink::WebMessagePort> ports) = 0;
Jiawei Libba76072019-07-29 23:00:25359
Jiawei Li5283ad42020-03-27 21:26:05360 // Executes a string of JavaScript in the main frame's context.
361 // This is no-op if the main frame is not available.
362 // Pass in a callback to receive a result when it is available.
363 // If there is no need to receive the result, pass in a
364 // default-constructed callback. If provided, the callback
365 // will be invoked on the UI thread.
366 virtual void ExecuteJavaScript(
367 const base::string16& javascript,
368 base::OnceCallback<void(base::Value)> callback) = 0;
369
Jiawei Lidf9ad18a2019-07-07 05:31:02370 // ===========================================================================
Sean Topping8a343862019-05-09 22:19:14371 // Utility Methods
372 // ===========================================================================
373
Chad Duffin4aa9c042019-01-11 00:51:55374 // Used to add or remove |observer| to the ObserverList in the implementation.
375 // These functions should only be invoked by CastWebContents::Observer in a
376 // valid sequence, enforced via SequenceChecker.
377 virtual void AddObserver(Observer* observer) = 0;
378 virtual void RemoveObserver(Observer* observer) = 0;
379
Ryan Daum52c9f7132020-04-06 21:23:34380 // Enable or disable devtools remote debugging for this WebContents and any
381 // inner WebContents that are spawned from it.
382 virtual void SetEnabledForRemoteDebugging(bool enabled) = 0;
383
Jiawei Li830fcfd2019-02-12 20:12:17384 // Used to expose CastWebContents's |binder_registry_| to Delegate.
385 // Delegate should register its mojo interface binders via this function
386 // when it is ready.
387 virtual service_manager::BinderRegistry* binder_registry() = 0;
388
Julie Jeongeun Kim641f4752019-12-04 01:53:22389 // Used for owner to pass its |InterfaceProvider| pointers to CastWebContents.
390 // It is owner's responsibility to make sure each |InterfaceProvider| pointer
391 // has distinct mojo interface set.
Jiawei Li830fcfd2019-02-12 20:12:17392 using InterfaceSet = base::flat_set<std::string>;
393 virtual void RegisterInterfaceProvider(
394 const InterfaceSet& interface_set,
395 service_manager::InterfaceProvider* interface_provider) = 0;
396
Jiawei Lia64a082b2019-12-06 21:17:26397 // Returns true if WebSQL database is configured enabled for this
398 // CastWebContents.
399 virtual bool is_websql_enabled() = 0;
400
401 // Returns true if mixer audio is enabled.
402 virtual bool is_mixer_audio_enabled() = 0;
403
Sean Toppingabf3be592020-03-11 23:20:35404 // Returns whether or not CastWebContents binder_registry() is valid for
405 // binding interfaces.
406 virtual bool can_bind_interfaces() = 0;
407
Sean Toppinge91b0972018-10-25 20:59:12408 private:
409 DISALLOW_COPY_AND_ASSIGN(CastWebContents);
410};
411
412std::ostream& operator<<(std::ostream& os, CastWebContents::PageState state);
413
414} // namespace chromecast
415
416#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_