blob: 4c64868d19c28c5f2ef77ebc8f0b7ae420c88268 [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"
Chad Duffin4aa9c042019-01-11 00:51:5514#include "chromecast/common/mojom/feature_manager.mojom.h"
Jiawei Li830fcfd2019-02-12 20:12:1715#include "services/service_manager/public/cpp/binder_registry.h"
16#include "services/service_manager/public/cpp/interface_provider.h"
Sean Toppinge91b0972018-10-25 20:59:1217#include "url/gurl.h"
18
19namespace content {
20class WebContents;
21} // namespace content
22
23namespace chromecast {
24
Sean Topping0e8ac572019-01-30 03:05:4325struct RendererFeature {
26 const std::string name;
27 base::Value value;
28};
29
Sean Toppinge91b0972018-10-25 20:59:1230// Simplified WebContents wrapper class for Cast platforms.
Sean Topping7414eed2019-04-10 23:04:2131//
32// Proper usage of content::WebContents relies on understanding the meaning
33// behind various WebContentsObserver methods, and then translating those
34// signals into some concrete state. CastWebContents does *not* own the
35// underlying WebContents (usually whatever class implements
36// content::WebContentsDelegate is the actual owner).
37//
38// =============================================================================
39// Lifetime
40// =============================================================================
41// CastWebContents *must* be created before WebContents begins loading any
42// content. Once content begins loading (via CWC::LoadUrl() or one of the
43// WebContents navigation APIs), CastWebContents will calculate its state based
44// on the status of the WebContents' *main* RenderFrame. Events from sub-frames
45// (e.g. iframes) are ignored, since we expect the web app to take care of
46// sub-frame errors.
47//
48// We consider the CastWebContents to be in a LOADED state when the content of
49// the main frame is fully loaded and running (all resources fetched, JS is
50// running). Iframes might still be loading in this case, but in general we
51// consider the page to be in a presentable state at this stage. It is
52// appropriate to display the WebContents to the user.
53//
54// During or after the page is loaded, there are multiple error conditions that
55// can occur. The following events will cause the page to enter an ERROR state:
56//
57// 1. If the main frame is served an HTTP error page (such as a 404 page), then
58// it means the desired content wasn't loaded.
59//
60// 2. If the main frame fails to load, such as when the browser blocked the URL
61// request, we treat this as an error.
62//
63// 3. The RenderProcess for the main frame could crash, so the page is not in a
64// usable state.
65//
66// The CastWebContents user can respond to these errors in a few ways: The
67// content can be reloaded, or the entire page activity can be cancelled. If we
68// totally cancel the activity, we prefer to notify the user with an error
69// screen or visible/audible error message. Otherwise, a silent retry is
70// preferred.
71//
72// CastWebContents can be used to close the underlying WebContents gracefully
73// via CWC::Close(). This initiates web page tear-down logic so that the web
74// app has a chance to perform its own finalization logic in JS. Next, we call
75// WebContents::ClosePage(), which defers the page closure logic to the
76// content::WebContentsDelegate. Usually, it will run its own finalization
77// logic and then destroy the WebContents. CastWebContents will be notified of
78// the WebContents destruction and enter the DESTROYED state. In the event
79// the page isn't destroyed, the page will enter the CLOSED state automatically
80// after a timeout. CastWebContents users should not try to reload the page, as
81// page closure is intentional.
82//
83// The web app may decide to close itself (such as via "window.close()" in JS).
84// This is similar to initiating the close flow via CWC::Close(), with the end
85// result being the same. We consider this an intentional closure, and should
86// not attempt to reload the page.
87//
88// Once CastWebContents is in the DESTROYED state, it is not really usable
89// anymore; most of the methods will simply no-op, and no more observer signals
90// will be emitted.
91//
92// CastWebContents can be deleted at any time, *except* during Observer
93// notifications. If the owner wants to destroy CastWebContents as a result of
94// an Observer event, it should post a task to destroy CastWebContents.
Sean Toppinge91b0972018-10-25 20:59:1295class CastWebContents {
96 public:
97 class Delegate {
98 public:
99 // Advertises page state for the CastWebContents.
100 // Use CastWebContents::page_state() to get the new state.
101 virtual void OnPageStateChanged(CastWebContents* cast_web_contents) = 0;
102
103 // Called when the page has stopped. e.g.: A 404 occurred when loading the
104 // page or if the render process for the main frame crashes. |error_code|
105 // will return a net::Error describing the failure, or net::OK if the page
Sean Topping7414eed2019-04-10 23:04:21106 // closed intentionally.
Sean Toppinge91b0972018-10-25 20:59:12107 //
108 // After this method, the page state will be one of the following:
Sean Topping7414eed2019-04-10 23:04:21109 // CLOSED: Page was closed as expected and the WebContents exists. The page
110 // should generally not be reloaded, since the page closure was
111 // triggered intentionally.
112 // ERROR: Page is in an error state. It should be reloaded or deleted.
Sean Toppinge91b0972018-10-25 20:59:12113 // DESTROYED: Page was closed due to deletion of WebContents. The
114 // CastWebContents instance is no longer usable and should be deleted.
Sean Toppinge91b0972018-10-25 20:59:12115 virtual void OnPageStopped(CastWebContents* cast_web_contents,
116 int error_code) = 0;
117
Sean Topping7414eed2019-04-10 23:04:21118 // Notify that an inner WebContents was created. |inner_contents| is created
Sean Topping0e8ac572019-01-30 03:05:43119 // in a default-initialized state with no delegate, and can be safely
120 // initialized by the delegate.
121 virtual void InnerContentsCreated(CastWebContents* inner_contents,
122 CastWebContents* outer_contents) {}
Chad Duffin4aa9c042019-01-11 00:51:55123
Sean Toppinge91b0972018-10-25 20:59:12124 protected:
125 virtual ~Delegate() {}
126 };
127
Chad Duffin4aa9c042019-01-11 00:51:55128 class Observer {
129 public:
130 Observer();
131
132 virtual void RenderFrameCreated(int render_process_id,
133 int render_frame_id) {}
Chad Duffin4aa9c042019-01-11 00:51:55134
Sean Topping7414eed2019-04-10 23:04:21135 // Notifies that a resource for the main frame failed to load.
136 virtual void ResourceLoadFailed(CastWebContents* cast_web_contents) {}
137
Chad Duffin4aa9c042019-01-11 00:51:55138 // Adds |this| to the ObserverList in the implementation of
139 // |cast_web_contents|.
140 void Observe(CastWebContents* cast_web_contents);
141
142 // Removes |this| from the ObserverList in the implementation of
143 // |cast_web_contents_|. This is only invoked by CastWebContents and is used
144 // to ensure that once the observed CastWebContents object is destructed the
145 // CastWebContents::Observer does not invoke any additional function calls
146 // on it.
147 void ResetCastWebContents();
148
149 protected:
150 virtual ~Observer();
151
152 CastWebContents* cast_web_contents_;
153 };
154
Sean Topping7414eed2019-04-10 23:04:21155 // Initialization parameters for CastWebContents.
Sean Topping0e8ac572019-01-30 03:05:43156 struct InitParams {
157 Delegate* delegate;
Sean Topping7414eed2019-04-10 23:04:21158 // Whether the underlying WebContents is exposed to the remote debugger.
Sean Topping0e8ac572019-01-30 03:05:43159 bool enabled_for_dev;
Sean Topping7414eed2019-04-10 23:04:21160 // Chooses a media renderer for the WebContents.
Yuchen Liuea568d22019-03-05 21:54:01161 bool use_cma_renderer;
Sean Topping7414eed2019-04-10 23:04:21162 // Whether the WebContents is a root native window, or if it is embedded in
163 // another WebContents (see Delegate::InnerContentsCreated()).
Sean Topping6735aaf2019-03-20 19:20:12164 bool is_root_window = false;
Sean Topping0e8ac572019-01-30 03:05:43165 };
166
Sean Toppinge91b0972018-10-25 20:59:12167 // Page state for the main frame.
168 enum class PageState {
169 IDLE, // Main frame has not started yet.
170 LOADING, // Main frame is loading resources.
171 LOADED, // Main frame is loaded, but sub-frames may still be loading.
172 CLOSED, // Page is closed and should be cleaned up.
173 DESTROYED, // The WebContents is destroyed and can no longer be used.
174 ERROR, // Main frame is in an error state.
175 };
176
Sean Topping6735aaf2019-03-20 19:20:12177 static std::vector<CastWebContents*>& GetAll();
178
Sean Toppinge91b0972018-10-25 20:59:12179 CastWebContents() = default;
180 virtual ~CastWebContents() = default;
181
Sean Topping6735aaf2019-03-20 19:20:12182 // Tab identifier for the WebContents, mainly used by the tabs extension API.
183 // Tab IDs may be re-used, but no two live CastWebContents should have the
184 // same tab ID at any given time.
185 virtual int tab_id() const = 0;
186
Sean Topping0e8ac572019-01-30 03:05:43187 // TODO(seantopping): Hide this, clients shouldn't use WebContents directly.
Sean Toppinge91b0972018-10-25 20:59:12188 virtual content::WebContents* web_contents() const = 0;
189 virtual PageState page_state() const = 0;
190
Sean Topping0e8ac572019-01-30 03:05:43191 // ===========================================================================
192 // Initialization and Setup
193 // ===========================================================================
194
195 // Set the delegate. SetDelegate(nullptr) can be used to stop notifications.
196 virtual void SetDelegate(Delegate* delegate) = 0;
197
198 // Add a set of features for all renderers in the WebContents. Features are
199 // configured when `CastWebContents::RenderFrameCreated` is invoked.
200 virtual void AddRendererFeatures(std::vector<RendererFeature> features) = 0;
201
202 virtual void AllowWebAndMojoWebUiBindings() = 0;
203 virtual void ClearRenderWidgetHostView() = 0;
204
205 // ===========================================================================
206 // Page Lifetime
207 // ===========================================================================
208
Sean Toppinge91b0972018-10-25 20:59:12209 // Navigates the underlying WebContents to |url|. Delegate will be notified of
210 // page progression events via OnPageStateChanged().
211 virtual void LoadUrl(const GURL& url) = 0;
212
213 // Initiate closure of the page. This invokes the appropriate unload handlers.
214 // Eventually the delegate will be notified with OnPageStopped().
215 virtual void ClosePage() = 0;
216
217 // Stop the page immediately. This will automatically invoke
218 // Delegate::OnPageStopped(error_code), allowing the delegate to delete or
Sean Topping7414eed2019-04-10 23:04:21219 // reload the page without waiting for the WebContents owner to tear down the
220 // page.
Sean Toppinge91b0972018-10-25 20:59:12221 virtual void Stop(int error_code) = 0;
222
Chad Duffin4aa9c042019-01-11 00:51:55223 // Used to add or remove |observer| to the ObserverList in the implementation.
224 // These functions should only be invoked by CastWebContents::Observer in a
225 // valid sequence, enforced via SequenceChecker.
226 virtual void AddObserver(Observer* observer) = 0;
227 virtual void RemoveObserver(Observer* observer) = 0;
228
Jiawei Li830fcfd2019-02-12 20:12:17229 // Used to expose CastWebContents's |binder_registry_| to Delegate.
230 // Delegate should register its mojo interface binders via this function
231 // when it is ready.
232 virtual service_manager::BinderRegistry* binder_registry() = 0;
233
234 // Used for owner to pass its |InterfaceProviderPtr|s to CastWebContents.
235 // It is owner's respoinsibility to make sure each |InterfaceProviderPtr| has
236 // distinct mojo interface set.
237 using InterfaceSet = base::flat_set<std::string>;
238 virtual void RegisterInterfaceProvider(
239 const InterfaceSet& interface_set,
240 service_manager::InterfaceProvider* interface_provider) = 0;
241
Sean Toppinge91b0972018-10-25 20:59:12242 private:
243 DISALLOW_COPY_AND_ASSIGN(CastWebContents);
244};
245
246std::ostream& operator<<(std::ostream& os, CastWebContents::PageState state);
247
248} // namespace chromecast
249
250#endif // CHROMECAST_BROWSER_CAST_WEB_CONTENTS_H_