blob: c11d4654b7a7d1b509d95888f4b44f28f9c59384 [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"
Sean Toppingf0a1d572019-06-17 23:03:4415#include "base/strings/string16.h"
Jiawei Lidf9ad18a2019-07-07 05:31:0216#include "base/strings/string_piece_forward.h"
Chad Duffin4aa9c042019-01-11 00:51:5517#include "chromecast/common/mojom/feature_manager.mojom.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"
Sean Toppingf0a1d572019-06-17 23:03:4420#include "ui/gfx/geometry/rect.h"
Sean Toppinge91b0972018-10-25 20:59:1221#include "url/gurl.h"
22
Sean Topping2d4e54e2019-06-25 00:04:0423namespace blink {
24class AssociatedInterfaceProvider;
25} // namespace blink
26
Sean Toppinge91b0972018-10-25 20:59:1227namespace content {
28class WebContents;
29} // namespace content
30
31namespace chromecast {
32
Sean Topping0e8ac572019-01-30 03:05:4333struct RendererFeature {
34 const std::string name;
35 base::Value value;
36};
37
Sean Toppinge91b0972018-10-25 20:59:1238// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2139//
40// Proper usage of content::WebContents relies on understanding the meaning
41// behind various WebContentsObserver methods, and then translating those
42// signals into some concrete state. CastWebContents does *not* own the
43// underlying WebContents (usually whatever class implements
44// content::WebContentsDelegate is the actual owner).
45//
46// =============================================================================
47// Lifetime
48// =============================================================================
49// CastWebContents *must* be created before WebContents begins loading any
50// content. Once content begins loading (via CWC::LoadUrl() or one of the
51// WebContents navigation APIs), CastWebContents will calculate its state based
52// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
53// (e.g. iframes) are ignored, since we expect the web app to take care of
54// sub-frame errors.
55//
56// We consider the CastWebContents to be in a LOADED state when the content of
57// the main frame is fully loaded and running (all resources fetched, JS is
58// running). Iframes might still be loading in this case, but in general we
Sean Toppingeda675e2019-11-07 22:29:0459// consider the page to be in a presentable state at this stage, so it is
Sean Topping7414eed2019-04-10 23:04:2160// appropriate to display the WebContents to the user.
61//
62// During or after the page is loaded, there are multiple error conditions that
63// can occur. The following events will cause the page to enter an ERROR state:
64//
65// 1. If the main frame is served an HTTP error page (such as a 404 page), then
66// it means the desired content wasn't loaded.
67//
68// 2. If the main frame fails to load, such as when the browser blocked the URL
69// request, we treat this as an error.
70//
71// 3. The RenderProcess for the main frame could crash, so the page is not in a
72// usable state.
73//
74// The CastWebContents user can respond to these errors in a few ways: The
75// content can be reloaded, or the entire page activity can be cancelled. If we
76// totally cancel the activity, we prefer to notify the user with an error
77// screen or visible/audible error message. Otherwise, a silent retry is
78// preferred.
79//
80// CastWebContents can be used to close the underlying WebContents gracefully
81// via CWC::Close(). This initiates web page tear-down logic so that the web
82// app has a chance to perform its own finalization logic in JS. Next, we call
83// WebContents::ClosePage(), which defers the page closure logic to the
84// content::WebContentsDelegate. Usually, it will run its own finalization
85// logic and then destroy the WebContents. CastWebContents will be notified of
86// the WebContents destruction and enter the DESTROYED state. In the event
87// the page isn't destroyed, the page will enter the CLOSED state automatically
88// after a timeout. CastWebContents users should not try to reload the page, as
89// page closure is intentional.
90//
91// The web app may decide to close itself (such as via "window.close()" in JS).
92// This is similar to initiating the close flow via CWC::Close(), with the end
93// result being the same. We consider this an intentional closure, and should
94// not attempt to reload the page.
95//
96// Once CastWebContents is in the DESTROYED state, it is not really usable
97// anymore; most of the methods will simply no-op, and no more observer signals
98// will be emitted.
99//
100// CastWebContents can be deleted at any time, *except* during Observer
101// notifications. If the owner wants to destroy CastWebContents as a result of
102// an Observer event, it should post a task to destroy CastWebContents.
Sean Toppinge91b0972018-10-25 20:59:12103class CastWebContents {
104 public:
105 class Delegate {
106 public:
Sean Toppingf0a1d572019-06-17 23:03:44107 // Notify that an inner WebContents was created. |inner_contents| is created
108 // in a default-initialized state with no delegate, and can be safely
109 // initialized by the delegate.
110 virtual void InnerContentsCreated(CastWebContents* inner_contents,
111 CastWebContents* outer_contents) {}
112
113 protected:
114 virtual ~Delegate() {}
115 };
116
117 // Observer class. The Observer should *not* destroy CastWebContents during
118 // any of these events, otherwise other observers might try to use a freed
119 // pointer to |cast_web_contents|.
120 class Observer {
121 public:
122 Observer();
123
Sean Toppinge91b0972018-10-25 20:59:12124 // Advertises page state for the CastWebContents.
125 // Use CastWebContents::page_state() to get the new state.
Sean Toppingf0a1d572019-06-17 23:03:44126 virtual void OnPageStateChanged(CastWebContents* cast_web_contents) {}
Sean Toppinge91b0972018-10-25 20:59:12127
128 // Called when the page has stopped. e.g.: A 404 occurred when loading the
129 // page or if the render process for the main frame crashes. |error_code|
130 // will return a net::Error describing the failure, or net::OK if the page
Sean Topping7414eed2019-04-10 23:04:21131 // closed intentionally.
Sean Toppinge91b0972018-10-25 20:59:12132 //
133 // After this method, the page state will be one of the following:
Sean Topping7414eed2019-04-10 23:04:21134 // CLOSED: Page was closed as expected and the WebContents exists. The page
135 // should generally not be reloaded, since the page closure was
136 // triggered intentionally.
137 // ERROR: Page is in an error state. It should be reloaded or deleted.
Sean Toppinge91b0972018-10-25 20:59:12138 // DESTROYED: Page was closed due to deletion of WebContents. The
139 // CastWebContents instance is no longer usable and should be deleted.
Sean Toppinge91b0972018-10-25 20:59:12140 virtual void OnPageStopped(CastWebContents* cast_web_contents,
Sean Toppingf0a1d572019-06-17 23:03:44141 int error_code) {}
Sean Toppinge91b0972018-10-25 20:59:12142
Sean Toppingf0a1d572019-06-17 23:03:44143 // A new RenderFrame was created for the WebContents. |frame_interfaces| are
144 // provided by the new frame.
145 virtual void RenderFrameCreated(
146 int render_process_id,
147 int render_frame_id,
Sean Topping2d4e54e2019-06-25 00:04:04148 service_manager::InterfaceProvider* frame_interfaces,
149 blink::AssociatedInterfaceProvider* frame_associated_interfaces) {}
Chad Duffin4aa9c042019-01-11 00:51:55150
Sean Toppingf0a1d572019-06-17 23:03:44151 // These methods are calls forwarded from WebContentsObserver.
152 virtual void MainFrameResized(const gfx::Rect& bounds) {}
153 virtual void UpdateTitle(const base::string16& title) {}
154 virtual void UpdateFaviconURL(GURL icon_url) {}
155 virtual void DidFinishBlockedNavigation(GURL url) {}
156 virtual void DidFirstVisuallyNonEmptyPaint() {}
Chad Duffin4aa9c042019-01-11 00:51:55157
Sean Topping7414eed2019-04-10 23:04:21158 // Notifies that a resource for the main frame failed to load.
159 virtual void ResourceLoadFailed(CastWebContents* cast_web_contents) {}
160
Chad Duffin4aa9c042019-01-11 00:51:55161 // Adds |this| to the ObserverList in the implementation of
162 // |cast_web_contents|.
163 void Observe(CastWebContents* cast_web_contents);
164
165 // Removes |this| from the ObserverList in the implementation of
166 // |cast_web_contents_|. This is only invoked by CastWebContents and is used
167 // to ensure that once the observed CastWebContents object is destructed the
168 // CastWebContents::Observer does not invoke any additional function calls
169 // on it.
170 void ResetCastWebContents();
171
172 protected:
173 virtual ~Observer();
174
175 CastWebContents* cast_web_contents_;
176 };
177
Sean Toppingf0a1d572019-06-17 23:03:44178 enum class BackgroundColor {
179 NONE,
180 WHITE,
181 BLACK,
182 TRANSPARENT,
183 };
184
Sean Topping7414eed2019-04-10 23:04:21185 // Initialization parameters for CastWebContents.
Sean Topping0e8ac572019-01-30 03:05:43186 struct InitParams {
Sean Toppingeda675e2019-11-07 22:29:04187 // The delegate for the CastWebContents. Must be non-null. If the delegate
188 // is destroyed before CastWebContents, the WeakPtr will be invalidated on
189 // the main UI thread.
190 base::WeakPtr<Delegate> delegate = nullptr;
Jiawei Lia64a082b2019-12-06 21:17:26191 // Enable development mode for this CastWebContents. Whitelists
Sean Topping8a343862019-05-09 22:19:14192 // certain functionality for the WebContents, like remote debugging and
193 // debugging interfaces.
194 bool enabled_for_dev = false;
Sean Topping7414eed2019-04-10 23:04:21195 // Chooses a media renderer for the WebContents.
Sean Topping8a343862019-05-09 22:19:14196 bool use_cma_renderer = false;
Sean Topping7414eed2019-04-10 23:04:21197 // Whether the WebContents is a root native window, or if it is embedded in
198 // another WebContents (see Delegate::InnerContentsCreated()).
Sean Topping6735aaf2019-03-20 19:20:12199 bool is_root_window = false;
Sean Topping8a343862019-05-09 22:19:14200 // Whether inner WebContents events should be handled. If this is set to
201 // true, then inner WebContents will automatically have a CastWebContents
202 // created and notify the delegate.
203 bool handle_inner_contents = false;
204 // Construct internal media blocker and enable BlockMediaLoading().
205 bool use_media_blocker = false;
Sean Toppingf0a1d572019-06-17 23:03:44206 // Background color for the WebContents view. If not provided, the color
207 // will fall back to the platform default.
208 BackgroundColor background_color = BackgroundColor::NONE;
Jiawei Lia64a082b2019-12-06 21:17:26209 // Enable WebSQL database for this CastWebContents.
210 bool enable_websql = false;
211 // Enable mixer audio support for this CastWebContents.
212 bool enable_mixer_audio = false;
Sean Toppingeda675e2019-11-07 22:29:04213
214 InitParams();
215 InitParams(const InitParams& other);
216 ~InitParams();
Sean Topping0e8ac572019-01-30 03:05:43217 };
218
Sean Toppinge91b0972018-10-25 20:59:12219 // Page state for the main frame.
220 enum class PageState {
221 IDLE, // Main frame has not started yet.
222 LOADING, // Main frame is loading resources.
223 LOADED, // Main frame is loaded, but sub-frames may still be loading.
224 CLOSED, // Page is closed and should be cleaned up.
225 DESTROYED, // The WebContents is destroyed and can no longer be used.
226 ERROR, // Main frame is in an error state.
227 };
228
Sean Topping6735aaf2019-03-20 19:20:12229 static std::vector<CastWebContents*>& GetAll();
230
Jiawei Lia64a082b2019-12-06 21:17:26231 // Returns the CastWebContents that wraps the content::WebContents, or nullptr
232 // if the CastWebContents does not exist.
233 static CastWebContents* FromWebContents(content::WebContents* web_contents);
234
Sean Toppinge91b0972018-10-25 20:59:12235 CastWebContents() = default;
236 virtual ~CastWebContents() = default;
237
Sean Topping6735aaf2019-03-20 19:20:12238 // Tab identifier for the WebContents, mainly used by the tabs extension API.
239 // Tab IDs may be re-used, but no two live CastWebContents should have the
240 // same tab ID at any given time.
241 virtual int tab_id() const = 0;
242
Sean Topping0e8ac572019-01-30 03:05:43243 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12244 virtual content::WebContents* web_contents() const = 0;
245 virtual PageState page_state() const = 0;
246
Sean Topping0e8ac572019-01-30 03:05:43247 // ===========================================================================
248 // Initialization and Setup
249 // ===========================================================================
250
Sean Topping0e8ac572019-01-30 03:05:43251 // Add a set of features for all renderers in the WebContents. Features are
252 // configured when `CastWebContents::RenderFrameCreated` is invoked.
253 virtual void AddRendererFeatures(std::vector<RendererFeature> features) = 0;
254
255 virtual void AllowWebAndMojoWebUiBindings() = 0;
256 virtual void ClearRenderWidgetHostView() = 0;
257
258 // ===========================================================================
259 // Page Lifetime
260 // ===========================================================================
261
Sean Toppinge91b0972018-10-25 20:59:12262 // Navigates the underlying WebContents to |url|. Delegate will be notified of
263 // page progression events via OnPageStateChanged().
264 virtual void LoadUrl(const GURL& url) = 0;
265
266 // Initiate closure of the page. This invokes the appropriate unload handlers.
267 // Eventually the delegate will be notified with OnPageStopped().
268 virtual void ClosePage() = 0;
269
270 // Stop the page immediately. This will automatically invoke
271 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21272 // reload the page without waiting for the WebContents owner to tear down the
273 // page.
Sean Toppinge91b0972018-10-25 20:59:12274 virtual void Stop(int error_code) = 0;
275
Sean Topping8a343862019-05-09 22:19:14276 // ===========================================================================
277 // Media Management
278 // ===========================================================================
279
280 // Block/unblock media from loading in all RenderFrames for the WebContents.
281 virtual void BlockMediaLoading(bool blocked) = 0;
Andres Medinaa65ad1b2019-06-26 22:18:19282 // Block/unblock media from starting in all RenderFrames for the WebContents.
283 // As opposed to |BlockMediaLoading|, |BlockMediaStarting| allows media to
284 // load while in blocking state.
285 virtual void BlockMediaStarting(bool blocked) = 0;
Sean Topping8a343862019-05-09 22:19:14286 virtual void EnableBackgroundVideoPlayback(bool enabled) = 0;
287
288 // ===========================================================================
Jiawei Lidf9ad18a2019-07-07 05:31:02289 // Page Communication
290 // ===========================================================================
291
292 // Executes a UTF-8 encoded |script| for every subsequent page load where
293 // the frame's URL has an origin reflected in |origins|. The script is
294 // executed early, prior to the execution of the document's scripts.
295 //
296 // Scripts are identified by a string-based client-managed |id|. Any
297 // script previously injected using the same |id| will be replaced.
298 //
299 // The order in which multiple bindings are executed is the same as the
300 // order in which the bindings were Added. If a script is added which
301 // clobbers an existing script of the same |id|, the previous script's
302 // precedence in the injection order will be preserved.
303 // |script| and |id| must be non-empty string.
304 //
305 // At least one |origins| entry must be specified.
306 // If a wildcard "*" is specified in |origins|, then the script will be
307 // evaluated for all documents.
308 virtual void AddBeforeLoadJavaScript(base::StringPiece id,
309 const std::vector<std::string>& origins,
310 base::StringPiece script) = 0;
311
312 // Removes a previously added JavaScript snippet identified by |id|.
313 // This is a no-op if there is no JavaScript snippet identified by |id|.
314 virtual void RemoveBeforeLoadJavaScript(base::StringPiece id) = 0;
315
Jiawei Libba76072019-07-29 23:00:25316 // Posts a message to the frame's onMessage handler.
317 //
318 // `target_origin` restricts message delivery to the specified origin.
319 // If `target_origin` is "*", then the message will be sent to the
320 // document regardless of its origin.
321 // See html.spec.whatwg.org/multipage/web-messaging.html sect. 9.4.3
322 // for more details on how the target origin policy is applied.
323 // Should be called on UI thread.
324 virtual void PostMessageToMainFrame(
325 const std::string& target_origin,
326 const std::string& data,
327 std::vector<mojo::ScopedMessagePipeHandle> channels) = 0;
328
Jiawei Lidf9ad18a2019-07-07 05:31:02329 // ===========================================================================
Sean Topping8a343862019-05-09 22:19:14330 // Utility Methods
331 // ===========================================================================
332
Chad Duffin4aa9c042019-01-11 00:51:55333 // Used to add or remove |observer| to the ObserverList in the implementation.
334 // These functions should only be invoked by CastWebContents::Observer in a
335 // valid sequence, enforced via SequenceChecker.
336 virtual void AddObserver(Observer* observer) = 0;
337 virtual void RemoveObserver(Observer* observer) = 0;
338
Jiawei Li830fcfd2019-02-12 20:12:17339 // Used to expose CastWebContents's |binder_registry_| to Delegate.
340 // Delegate should register its mojo interface binders via this function
341 // when it is ready.
342 virtual service_manager::BinderRegistry* binder_registry() = 0;
343
Julie Jeongeun Kim641f4752019-12-04 01:53:22344 // Used for owner to pass its |InterfaceProvider| pointers to CastWebContents.
345 // It is owner's responsibility to make sure each |InterfaceProvider| pointer
346 // has distinct mojo interface set.
Jiawei Li830fcfd2019-02-12 20:12:17347 using InterfaceSet = base::flat_set<std::string>;
348 virtual void RegisterInterfaceProvider(
349 const InterfaceSet& interface_set,
350 service_manager::InterfaceProvider* interface_provider) = 0;
351
Jiawei Lia64a082b2019-12-06 21:17:26352 // Returns true if WebSQL database is configured enabled for this
353 // CastWebContents.
354 virtual bool is_websql_enabled() = 0;
355
356 // Returns true if mixer audio is enabled.
357 virtual bool is_mixer_audio_enabled() = 0;
358
Sean Toppinge91b0972018-10-25 20:59:12359 private:
360 DISALLOW_COPY_AND_ASSIGN(CastWebContents);
361};
362
363std::ostream& operator<<(std::ostream& os, CastWebContents::PageState state);
364
365} // namespace chromecast
366
367#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_