blob: db8738d5c3307a6b627482567396b70279baa56b [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
21namespace content {
22class WebContents;
23} // namespace content
24
25namespace chromecast {
26
Sean Topping0e8ac572019-01-30 03:05:4327struct RendererFeature {
28 const std::string name;
29 base::Value value;
30};
31
Sean Toppinge91b0972018-10-25 20:59:1232// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2133//
34// Proper usage of content::WebContents relies on understanding the meaning
35// behind various WebContentsObserver methods, and then translating those
36// signals into some concrete state. CastWebContents does *not* own the
37// underlying WebContents (usually whatever class implements
38// content::WebContentsDelegate is the actual owner).
39//
40// =============================================================================
41// Lifetime
42// =============================================================================
43// CastWebContents *must* be created before WebContents begins loading any
44// content. Once content begins loading (via CWC::LoadUrl() or one of the
45// WebContents navigation APIs), CastWebContents will calculate its state based
46// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
47// (e.g. iframes) are ignored, since we expect the web app to take care of
48// sub-frame errors.
49//
50// We consider the CastWebContents to be in a LOADED state when the content of
51// the main frame is fully loaded and running (all resources fetched, JS is
52// running). Iframes might still be loading in this case, but in general we
53// consider the page to be in a presentable state at this stage. It is
54// appropriate to display the WebContents to the user.
55//
56// During or after the page is loaded, there are multiple error conditions that
57// can occur. The following events will cause the page to enter an ERROR state:
58//
59// 1. If the main frame is served an HTTP error page (such as a 404 page), then
60// it means the desired content wasn't loaded.
61//
62// 2. If the main frame fails to load, such as when the browser blocked the URL
63// request, we treat this as an error.
64//
65// 3. The RenderProcess for the main frame could crash, so the page is not in a
66// usable state.
67//
68// The CastWebContents user can respond to these errors in a few ways: The
69// content can be reloaded, or the entire page activity can be cancelled. If we
70// totally cancel the activity, we prefer to notify the user with an error
71// screen or visible/audible error message. Otherwise, a silent retry is
72// preferred.
73//
74// CastWebContents can be used to close the underlying WebContents gracefully
75// via CWC::Close(). This initiates web page tear-down logic so that the web
76// app has a chance to perform its own finalization logic in JS. Next, we call
77// WebContents::ClosePage(), which defers the page closure logic to the
78// content::WebContentsDelegate. Usually, it will run its own finalization
79// logic and then destroy the WebContents. CastWebContents will be notified of
80// the WebContents destruction and enter the DESTROYED state. In the event
81// the page isn't destroyed, the page will enter the CLOSED state automatically
82// after a timeout. CastWebContents users should not try to reload the page, as
83// page closure is intentional.
84//
85// The web app may decide to close itself (such as via "window.close()" in JS).
86// This is similar to initiating the close flow via CWC::Close(), with the end
87// result being the same. We consider this an intentional closure, and should
88// not attempt to reload the page.
89//
90// Once CastWebContents is in the DESTROYED state, it is not really usable
91// anymore; most of the methods will simply no-op, and no more observer signals
92// will be emitted.
93//
94// CastWebContents can be deleted at any time, *except* during Observer
95// notifications. If the owner wants to destroy CastWebContents as a result of
96// an Observer event, it should post a task to destroy CastWebContents.
Sean Toppinge91b0972018-10-25 20:59:1297class CastWebContents {
98 public:
99 class Delegate {
100 public:
Sean Toppingf0a1d572019-06-17 23:03:44101 // Notify that an inner WebContents was created. |inner_contents| is created
102 // in a default-initialized state with no delegate, and can be safely
103 // initialized by the delegate.
104 virtual void InnerContentsCreated(CastWebContents* inner_contents,
105 CastWebContents* outer_contents) {}
106
107 protected:
108 virtual ~Delegate() {}
109 };
110
111 // Observer class. The Observer should *not* destroy CastWebContents during
112 // any of these events, otherwise other observers might try to use a freed
113 // pointer to |cast_web_contents|.
114 class Observer {
115 public:
116 Observer();
117
Sean Toppinge91b0972018-10-25 20:59:12118 // Advertises page state for the CastWebContents.
119 // Use CastWebContents::page_state() to get the new state.
Sean Toppingf0a1d572019-06-17 23:03:44120 virtual void OnPageStateChanged(CastWebContents* cast_web_contents) {}
Sean Toppinge91b0972018-10-25 20:59:12121
122 // Called when the page has stopped. e.g.: A 404 occurred when loading the
123 // page or if the render process for the main frame crashes. |error_code|
124 // will return a net::Error describing the failure, or net::OK if the page
Sean Topping7414eed2019-04-10 23:04:21125 // closed intentionally.
Sean Toppinge91b0972018-10-25 20:59:12126 //
127 // After this method, the page state will be one of the following:
Sean Topping7414eed2019-04-10 23:04:21128 // CLOSED: Page was closed as expected and the WebContents exists. The page
129 // should generally not be reloaded, since the page closure was
130 // triggered intentionally.
131 // ERROR: Page is in an error state. It should be reloaded or deleted.
Sean Toppinge91b0972018-10-25 20:59:12132 // DESTROYED: Page was closed due to deletion of WebContents. The
133 // CastWebContents instance is no longer usable and should be deleted.
Sean Toppinge91b0972018-10-25 20:59:12134 virtual void OnPageStopped(CastWebContents* cast_web_contents,
Sean Toppingf0a1d572019-06-17 23:03:44135 int error_code) {}
Sean Toppinge91b0972018-10-25 20:59:12136
Sean Toppingf0a1d572019-06-17 23:03:44137 // A new RenderFrame was created for the WebContents. |frame_interfaces| are
138 // provided by the new frame.
139 virtual void RenderFrameCreated(
140 int render_process_id,
141 int render_frame_id,
142 service_manager::InterfaceProvider* frame_interfaces) {}
Chad Duffin4aa9c042019-01-11 00:51:55143
Sean Toppingf0a1d572019-06-17 23:03:44144 // These methods are calls forwarded from WebContentsObserver.
145 virtual void MainFrameResized(const gfx::Rect& bounds) {}
146 virtual void UpdateTitle(const base::string16& title) {}
147 virtual void UpdateFaviconURL(GURL icon_url) {}
148 virtual void DidFinishBlockedNavigation(GURL url) {}
149 virtual void DidFirstVisuallyNonEmptyPaint() {}
Chad Duffin4aa9c042019-01-11 00:51:55150
Sean Topping7414eed2019-04-10 23:04:21151 // Notifies that a resource for the main frame failed to load.
152 virtual void ResourceLoadFailed(CastWebContents* cast_web_contents) {}
153
Chad Duffin4aa9c042019-01-11 00:51:55154 // Adds |this| to the ObserverList in the implementation of
155 // |cast_web_contents|.
156 void Observe(CastWebContents* cast_web_contents);
157
158 // Removes |this| from the ObserverList in the implementation of
159 // |cast_web_contents_|. This is only invoked by CastWebContents and is used
160 // to ensure that once the observed CastWebContents object is destructed the
161 // CastWebContents::Observer does not invoke any additional function calls
162 // on it.
163 void ResetCastWebContents();
164
165 protected:
166 virtual ~Observer();
167
168 CastWebContents* cast_web_contents_;
169 };
170
Sean Toppingf0a1d572019-06-17 23:03:44171 enum class BackgroundColor {
172 NONE,
173 WHITE,
174 BLACK,
175 TRANSPARENT,
176 };
177
Sean Topping7414eed2019-04-10 23:04:21178 // Initialization parameters for CastWebContents.
Sean Topping0e8ac572019-01-30 03:05:43179 struct InitParams {
Sean Topping8a343862019-05-09 22:19:14180 // Delegate for CastWebContents. This can be null for an inner WebContents.
181 Delegate* delegate = nullptr;
182 // Enable development mode for this CastWebCastWebContents. Whitelists
183 // certain functionality for the WebContents, like remote debugging and
184 // debugging interfaces.
185 bool enabled_for_dev = false;
Sean Topping7414eed2019-04-10 23:04:21186 // Chooses a media renderer for the WebContents.
Sean Topping8a343862019-05-09 22:19:14187 bool use_cma_renderer = false;
Sean Topping7414eed2019-04-10 23:04:21188 // Whether the WebContents is a root native window, or if it is embedded in
189 // another WebContents (see Delegate::InnerContentsCreated()).
Sean Topping6735aaf2019-03-20 19:20:12190 bool is_root_window = false;
Sean Topping8a343862019-05-09 22:19:14191 // Whether inner WebContents events should be handled. If this is set to
192 // true, then inner WebContents will automatically have a CastWebContents
193 // created and notify the delegate.
194 bool handle_inner_contents = false;
195 // Construct internal media blocker and enable BlockMediaLoading().
196 bool use_media_blocker = false;
Sean Toppingf0a1d572019-06-17 23:03:44197 // Background color for the WebContents view. If not provided, the color
198 // will fall back to the platform default.
199 BackgroundColor background_color = BackgroundColor::NONE;
Sean Topping0e8ac572019-01-30 03:05:43200 };
201
Sean Toppinge91b0972018-10-25 20:59:12202 // Page state for the main frame.
203 enum class PageState {
204 IDLE, // Main frame has not started yet.
205 LOADING, // Main frame is loading resources.
206 LOADED, // Main frame is loaded, but sub-frames may still be loading.
207 CLOSED, // Page is closed and should be cleaned up.
208 DESTROYED, // The WebContents is destroyed and can no longer be used.
209 ERROR, // Main frame is in an error state.
210 };
211
Sean Topping6735aaf2019-03-20 19:20:12212 static std::vector<CastWebContents*>& GetAll();
213
Sean Toppinge91b0972018-10-25 20:59:12214 CastWebContents() = default;
215 virtual ~CastWebContents() = default;
216
Sean Topping6735aaf2019-03-20 19:20:12217 // Tab identifier for the WebContents, mainly used by the tabs extension API.
218 // Tab IDs may be re-used, but no two live CastWebContents should have the
219 // same tab ID at any given time.
220 virtual int tab_id() const = 0;
221
Sean Topping0e8ac572019-01-30 03:05:43222 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12223 virtual content::WebContents* web_contents() const = 0;
224 virtual PageState page_state() const = 0;
225
Sean Topping0e8ac572019-01-30 03:05:43226 // ===========================================================================
227 // Initialization and Setup
228 // ===========================================================================
229
230 // Set the delegate. SetDelegate(nullptr) can be used to stop notifications.
231 virtual void SetDelegate(Delegate* delegate) = 0;
232
233 // Add a set of features for all renderers in the WebContents. Features are
234 // configured when `CastWebContents::RenderFrameCreated` is invoked.
235 virtual void AddRendererFeatures(std::vector<RendererFeature> features) = 0;
236
237 virtual void AllowWebAndMojoWebUiBindings() = 0;
238 virtual void ClearRenderWidgetHostView() = 0;
239
240 // ===========================================================================
241 // Page Lifetime
242 // ===========================================================================
243
Sean Toppinge91b0972018-10-25 20:59:12244 // Navigates the underlying WebContents to |url|. Delegate will be notified of
245 // page progression events via OnPageStateChanged().
246 virtual void LoadUrl(const GURL& url) = 0;
247
248 // Initiate closure of the page. This invokes the appropriate unload handlers.
249 // Eventually the delegate will be notified with OnPageStopped().
250 virtual void ClosePage() = 0;
251
252 // Stop the page immediately. This will automatically invoke
253 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21254 // reload the page without waiting for the WebContents owner to tear down the
255 // page.
Sean Toppinge91b0972018-10-25 20:59:12256 virtual void Stop(int error_code) = 0;
257
Sean Topping8a343862019-05-09 22:19:14258 // ===========================================================================
259 // Media Management
260 // ===========================================================================
261
262 // Block/unblock media from loading in all RenderFrames for the WebContents.
263 virtual void BlockMediaLoading(bool blocked) = 0;
264 virtual void EnableBackgroundVideoPlayback(bool enabled) = 0;
265
266 // ===========================================================================
267 // Utility Methods
268 // ===========================================================================
269
Chad Duffin4aa9c042019-01-11 00:51:55270 // Used to add or remove |observer| to the ObserverList in the implementation.
271 // These functions should only be invoked by CastWebContents::Observer in a
272 // valid sequence, enforced via SequenceChecker.
273 virtual void AddObserver(Observer* observer) = 0;
274 virtual void RemoveObserver(Observer* observer) = 0;
275
Jiawei Li830fcfd2019-02-12 20:12:17276 // Used to expose CastWebContents's |binder_registry_| to Delegate.
277 // Delegate should register its mojo interface binders via this function
278 // when it is ready.
279 virtual service_manager::BinderRegistry* binder_registry() = 0;
280
281 // Used for owner to pass its |InterfaceProviderPtr|s to CastWebContents.
282 // It is owner's respoinsibility to make sure each |InterfaceProviderPtr| has
283 // distinct mojo interface set.
284 using InterfaceSet = base::flat_set<std::string>;
285 virtual void RegisterInterfaceProvider(
286 const InterfaceSet& interface_set,
287 service_manager::InterfaceProvider* interface_provider) = 0;
288
Sean Toppinge91b0972018-10-25 20:59:12289 private:
290 DISALLOW_COPY_AND_ASSIGN(CastWebContents);
291};
292
293std::ostream& operator<<(std::ostream& os, CastWebContents::PageState state);
294
295} // namespace chromecast
296
297#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_