blob: 320b7431c8a7b7bb5227dc4b48de7cb023572f1b [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 Li830fcfd2019-02-12 20:12:1711#include "base/containers/flat_set.h"
Chad Duffin4aa9c042019-01-11 00:51:5512#include "base/observer_list.h"
Sean Topping0e8ac572019-01-30 03:05:4313#include "base/optional.h"
Sean Toppingf0a1d572019-06-17 23:03:4414#include "base/strings/string16.h"
Chad Duffin4aa9c042019-01-11 00:51:5515#include "chromecast/common/mojom/feature_manager.mojom.h"
Jiawei Li830fcfd2019-02-12 20:12:1716#include "services/service_manager/public/cpp/binder_registry.h"
17#include "services/service_manager/public/cpp/interface_provider.h"
Sean Toppingf0a1d572019-06-17 23:03:4418#include "ui/gfx/geometry/rect.h"
Sean Toppinge91b0972018-10-25 20:59:1219#include "url/gurl.h"
20
Sean Topping2d4e54e2019-06-25 00:04:0421namespace blink {
22class AssociatedInterfaceProvider;
23} // namespace blink
24
Sean Toppinge91b0972018-10-25 20:59:1225namespace content {
26class WebContents;
27} // namespace content
28
29namespace chromecast {
30
Sean Topping0e8ac572019-01-30 03:05:4331struct RendererFeature {
32 const std::string name;
33 base::Value value;
34};
35
Sean Toppinge91b0972018-10-25 20:59:1236// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2137//
38// Proper usage of content::WebContents relies on understanding the meaning
39// behind various WebContentsObserver methods, and then translating those
40// signals into some concrete state. CastWebContents does *not* own the
41// underlying WebContents (usually whatever class implements
42// content::WebContentsDelegate is the actual owner).
43//
44// =============================================================================
45// Lifetime
46// =============================================================================
47// CastWebContents *must* be created before WebContents begins loading any
48// content. Once content begins loading (via CWC::LoadUrl() or one of the
49// WebContents navigation APIs), CastWebContents will calculate its state based
50// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
51// (e.g. iframes) are ignored, since we expect the web app to take care of
52// sub-frame errors.
53//
54// We consider the CastWebContents to be in a LOADED state when the content of
55// the main frame is fully loaded and running (all resources fetched, JS is
56// running). Iframes might still be loading in this case, but in general we
57// consider the page to be in a presentable state at this stage. It is
58// appropriate to display the WebContents to the user.
59//
60// During or after the page is loaded, there are multiple error conditions that
61// can occur. The following events will cause the page to enter an ERROR state:
62//
63// 1. If the main frame is served an HTTP error page (such as a 404 page), then
64// it means the desired content wasn't loaded.
65//
66// 2. If the main frame fails to load, such as when the browser blocked the URL
67// request, we treat this as an error.
68//
69// 3. The RenderProcess for the main frame could crash, so the page is not in a
70// usable state.
71//
72// The CastWebContents user can respond to these errors in a few ways: The
73// content can be reloaded, or the entire page activity can be cancelled. If we
74// totally cancel the activity, we prefer to notify the user with an error
75// screen or visible/audible error message. Otherwise, a silent retry is
76// preferred.
77//
78// CastWebContents can be used to close the underlying WebContents gracefully
79// via CWC::Close(). This initiates web page tear-down logic so that the web
80// app has a chance to perform its own finalization logic in JS. Next, we call
81// WebContents::ClosePage(), which defers the page closure logic to the
82// content::WebContentsDelegate. Usually, it will run its own finalization
83// logic and then destroy the WebContents. CastWebContents will be notified of
84// the WebContents destruction and enter the DESTROYED state. In the event
85// the page isn't destroyed, the page will enter the CLOSED state automatically
86// after a timeout. CastWebContents users should not try to reload the page, as
87// page closure is intentional.
88//
89// The web app may decide to close itself (such as via "window.close()" in JS).
90// This is similar to initiating the close flow via CWC::Close(), with the end
91// result being the same. We consider this an intentional closure, and should
92// not attempt to reload the page.
93//
94// Once CastWebContents is in the DESTROYED state, it is not really usable
95// anymore; most of the methods will simply no-op, and no more observer signals
96// will be emitted.
97//
98// CastWebContents can be deleted at any time, *except* during Observer
99// notifications. If the owner wants to destroy CastWebContents as a result of
100// an Observer event, it should post a task to destroy CastWebContents.
Sean Toppinge91b0972018-10-25 20:59:12101class CastWebContents {
102 public:
103 class Delegate {
104 public:
Sean Toppingf0a1d572019-06-17 23:03:44105 // Notify that an inner WebContents was created. |inner_contents| is created
106 // in a default-initialized state with no delegate, and can be safely
107 // initialized by the delegate.
108 virtual void InnerContentsCreated(CastWebContents* inner_contents,
109 CastWebContents* outer_contents) {}
110
111 protected:
112 virtual ~Delegate() {}
113 };
114
115 // Observer class. The Observer should *not* destroy CastWebContents during
116 // any of these events, otherwise other observers might try to use a freed
117 // pointer to |cast_web_contents|.
118 class Observer {
119 public:
120 Observer();
121
Sean Toppinge91b0972018-10-25 20:59:12122 // Advertises page state for the CastWebContents.
123 // Use CastWebContents::page_state() to get the new state.
Sean Toppingf0a1d572019-06-17 23:03:44124 virtual void OnPageStateChanged(CastWebContents* cast_web_contents) {}
Sean Toppinge91b0972018-10-25 20:59:12125
126 // Called when the page has stopped. e.g.: A 404 occurred when loading the
127 // page or if the render process for the main frame crashes. |error_code|
128 // will return a net::Error describing the failure, or net::OK if the page
Sean Topping7414eed2019-04-10 23:04:21129 // closed intentionally.
Sean Toppinge91b0972018-10-25 20:59:12130 //
131 // After this method, the page state will be one of the following:
Sean Topping7414eed2019-04-10 23:04:21132 // CLOSED: Page was closed as expected and the WebContents exists. The page
133 // should generally not be reloaded, since the page closure was
134 // triggered intentionally.
135 // ERROR: Page is in an error state. It should be reloaded or deleted.
Sean Toppinge91b0972018-10-25 20:59:12136 // DESTROYED: Page was closed due to deletion of WebContents. The
137 // CastWebContents instance is no longer usable and should be deleted.
Sean Toppinge91b0972018-10-25 20:59:12138 virtual void OnPageStopped(CastWebContents* cast_web_contents,
Sean Toppingf0a1d572019-06-17 23:03:44139 int error_code) {}
Sean Toppinge91b0972018-10-25 20:59:12140
Sean Toppingf0a1d572019-06-17 23:03:44141 // A new RenderFrame was created for the WebContents. |frame_interfaces| are
142 // provided by the new frame.
143 virtual void RenderFrameCreated(
144 int render_process_id,
145 int render_frame_id,
Sean Topping2d4e54e2019-06-25 00:04:04146 service_manager::InterfaceProvider* frame_interfaces,
147 blink::AssociatedInterfaceProvider* frame_associated_interfaces) {}
Chad Duffin4aa9c042019-01-11 00:51:55148
Sean Toppingf0a1d572019-06-17 23:03:44149 // These methods are calls forwarded from WebContentsObserver.
150 virtual void MainFrameResized(const gfx::Rect& bounds) {}
151 virtual void UpdateTitle(const base::string16& title) {}
152 virtual void UpdateFaviconURL(GURL icon_url) {}
153 virtual void DidFinishBlockedNavigation(GURL url) {}
154 virtual void DidFirstVisuallyNonEmptyPaint() {}
Chad Duffin4aa9c042019-01-11 00:51:55155
Sean Topping7414eed2019-04-10 23:04:21156 // Notifies that a resource for the main frame failed to load.
157 virtual void ResourceLoadFailed(CastWebContents* cast_web_contents) {}
158
Chad Duffin4aa9c042019-01-11 00:51:55159 // Adds |this| to the ObserverList in the implementation of
160 // |cast_web_contents|.
161 void Observe(CastWebContents* cast_web_contents);
162
163 // Removes |this| from the ObserverList in the implementation of
164 // |cast_web_contents_|. This is only invoked by CastWebContents and is used
165 // to ensure that once the observed CastWebContents object is destructed the
166 // CastWebContents::Observer does not invoke any additional function calls
167 // on it.
168 void ResetCastWebContents();
169
170 protected:
171 virtual ~Observer();
172
173 CastWebContents* cast_web_contents_;
174 };
175
Sean Toppingf0a1d572019-06-17 23:03:44176 enum class BackgroundColor {
177 NONE,
178 WHITE,
179 BLACK,
180 TRANSPARENT,
181 };
182
Sean Topping7414eed2019-04-10 23:04:21183 // Initialization parameters for CastWebContents.
Sean Topping0e8ac572019-01-30 03:05:43184 struct InitParams {
Sean Topping8a343862019-05-09 22:19:14185 // Delegate for CastWebContents. This can be null for an inner WebContents.
186 Delegate* delegate = nullptr;
187 // Enable development mode for this CastWebCastWebContents. Whitelists
188 // certain functionality for the WebContents, like remote debugging and
189 // debugging interfaces.
190 bool enabled_for_dev = false;
Sean Topping7414eed2019-04-10 23:04:21191 // Chooses a media renderer for the WebContents.
Sean Topping8a343862019-05-09 22:19:14192 bool use_cma_renderer = false;
Sean Topping7414eed2019-04-10 23:04:21193 // Whether the WebContents is a root native window, or if it is embedded in
194 // another WebContents (see Delegate::InnerContentsCreated()).
Sean Topping6735aaf2019-03-20 19:20:12195 bool is_root_window = false;
Sean Topping8a343862019-05-09 22:19:14196 // Whether inner WebContents events should be handled. If this is set to
197 // true, then inner WebContents will automatically have a CastWebContents
198 // created and notify the delegate.
199 bool handle_inner_contents = false;
200 // Construct internal media blocker and enable BlockMediaLoading().
201 bool use_media_blocker = false;
Sean Toppingf0a1d572019-06-17 23:03:44202 // Background color for the WebContents view. If not provided, the color
203 // will fall back to the platform default.
204 BackgroundColor background_color = BackgroundColor::NONE;
Sean Topping0e8ac572019-01-30 03:05:43205 };
206
Sean Toppinge91b0972018-10-25 20:59:12207 // Page state for the main frame.
208 enum class PageState {
209 IDLE, // Main frame has not started yet.
210 LOADING, // Main frame is loading resources.
211 LOADED, // Main frame is loaded, but sub-frames may still be loading.
212 CLOSED, // Page is closed and should be cleaned up.
213 DESTROYED, // The WebContents is destroyed and can no longer be used.
214 ERROR, // Main frame is in an error state.
215 };
216
Sean Topping6735aaf2019-03-20 19:20:12217 static std::vector<CastWebContents*>& GetAll();
218
Sean Toppinge91b0972018-10-25 20:59:12219 CastWebContents() = default;
220 virtual ~CastWebContents() = default;
221
Sean Topping6735aaf2019-03-20 19:20:12222 // Tab identifier for the WebContents, mainly used by the tabs extension API.
223 // Tab IDs may be re-used, but no two live CastWebContents should have the
224 // same tab ID at any given time.
225 virtual int tab_id() const = 0;
226
Sean Topping0e8ac572019-01-30 03:05:43227 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12228 virtual content::WebContents* web_contents() const = 0;
229 virtual PageState page_state() const = 0;
230
Sean Topping0e8ac572019-01-30 03:05:43231 // ===========================================================================
232 // Initialization and Setup
233 // ===========================================================================
234
235 // Set the delegate. SetDelegate(nullptr) can be used to stop notifications.
236 virtual void SetDelegate(Delegate* delegate) = 0;
237
238 // Add a set of features for all renderers in the WebContents. Features are
239 // configured when `CastWebContents::RenderFrameCreated` is invoked.
240 virtual void AddRendererFeatures(std::vector<RendererFeature> features) = 0;
241
242 virtual void AllowWebAndMojoWebUiBindings() = 0;
243 virtual void ClearRenderWidgetHostView() = 0;
244
245 // ===========================================================================
246 // Page Lifetime
247 // ===========================================================================
248
Sean Toppinge91b0972018-10-25 20:59:12249 // Navigates the underlying WebContents to |url|. Delegate will be notified of
250 // page progression events via OnPageStateChanged().
251 virtual void LoadUrl(const GURL& url) = 0;
252
253 // Initiate closure of the page. This invokes the appropriate unload handlers.
254 // Eventually the delegate will be notified with OnPageStopped().
255 virtual void ClosePage() = 0;
256
257 // Stop the page immediately. This will automatically invoke
258 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21259 // reload the page without waiting for the WebContents owner to tear down the
260 // page.
Sean Toppinge91b0972018-10-25 20:59:12261 virtual void Stop(int error_code) = 0;
262
Sean Topping8a343862019-05-09 22:19:14263 // ===========================================================================
264 // Media Management
265 // ===========================================================================
266
267 // Block/unblock media from loading in all RenderFrames for the WebContents.
268 virtual void BlockMediaLoading(bool blocked) = 0;
Andres Medinaa65ad1b2019-06-26 22:18:19269 // Block/unblock media from starting in all RenderFrames for the WebContents.
270 // As opposed to |BlockMediaLoading|, |BlockMediaStarting| allows media to
271 // load while in blocking state.
272 virtual void BlockMediaStarting(bool blocked) = 0;
Sean Topping8a343862019-05-09 22:19:14273 virtual void EnableBackgroundVideoPlayback(bool enabled) = 0;
274
275 // ===========================================================================
276 // Utility Methods
277 // ===========================================================================
278
Chad Duffin4aa9c042019-01-11 00:51:55279 // Used to add or remove |observer| to the ObserverList in the implementation.
280 // These functions should only be invoked by CastWebContents::Observer in a
281 // valid sequence, enforced via SequenceChecker.
282 virtual void AddObserver(Observer* observer) = 0;
283 virtual void RemoveObserver(Observer* observer) = 0;
284
Jiawei Li830fcfd2019-02-12 20:12:17285 // Used to expose CastWebContents's |binder_registry_| to Delegate.
286 // Delegate should register its mojo interface binders via this function
287 // when it is ready.
288 virtual service_manager::BinderRegistry* binder_registry() = 0;
289
290 // Used for owner to pass its |InterfaceProviderPtr|s to CastWebContents.
291 // It is owner's respoinsibility to make sure each |InterfaceProviderPtr| has
292 // distinct mojo interface set.
293 using InterfaceSet = base::flat_set<std::string>;
294 virtual void RegisterInterfaceProvider(
295 const InterfaceSet& interface_set,
296 service_manager::InterfaceProvider* interface_provider) = 0;
297
Sean Toppinge91b0972018-10-25 20:59:12298 private:
299 DISALLOW_COPY_AND_ASSIGN(CastWebContents);
300};
301
302std::ostream& operator<<(std::ostream& os, CastWebContents::PageState state);
303
304} // namespace chromecast
305
306#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_