Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chromecast/browser/cast_web_view.cc

Issue 2626863006: [Chromecast] Add CastWebContents (Closed)
Patch Set: Long overdue rebase Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 #include "chromecast/browser/cast_web_view.h"
6
7 #include "base/logging.h"
8 #include "base/threading/thread_task_runner_handle.h"
9 #include "chromecast/base/metrics/cast_metrics_helper.h"
10 #include "content/public/browser/navigation_handle.h"
11 #include "content/public/browser/render_frame_host.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/render_widget_host.h"
14 #include "content/public/browser/render_widget_host_view.h"
15 #include "content/public/common/renderer_preferences.h"
16 #include "ipc/ipc_message.h"
17 #include "net/base/net_errors.h"
18 #include "ui/display/display.h"
19 #include "ui/display/screen.h"
20 #include "url/gurl.h"
21
22 #if defined(OS_ANDROID)
23 #include "chromecast/browser/android/cast_web_contents_activity.h"
24 #endif // defined(OS_ANDROID)
25
26 #if defined(USE_AURA)
27 #include "ui/aura/window.h"
28 #endif
29
30 namespace chromecast {
31
32 namespace {
33 // The time (in milliseconds) we wait for after a page is closed (i.e.
34 // after an app is stopped) before we delete the corresponding WebContents.
35 constexpr int kWebContentsDestructionDelayInMs = 50;
36
37 std::unique_ptr<content::WebContents> CreateWebContents(
38 content::BrowserContext* browser_context,
39 scoped_refptr<content::SiteInstance> site_instance) {
40 CHECK(display::Screen::GetScreen());
41 gfx::Size display_size =
42 display::Screen::GetScreen()->GetPrimaryDisplay().size();
43
44 content::WebContents::CreateParams create_params(browser_context, NULL);
45 create_params.routing_id = MSG_ROUTING_NONE;
46 create_params.initial_size = display_size;
47 create_params.site_instance = site_instance;
48 content::WebContents* web_contents =
49 content::WebContents::Create(create_params);
50
51 #if defined(USE_AURA)
52 // Resize window
53 aura::Window* content_window = web_contents->GetNativeView();
54 content_window->SetBounds(
55 gfx::Rect(display_size.width(), display_size.height()));
56 #endif
57
58 #if defined(OS_ANDROID)
59 content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
60 prefs->use_video_overlay_for_embedded_encrypted_video = true;
61 web_contents->GetRenderViewHost()->SyncRendererPrefs();
62 #endif
63
64 return base::WrapUnique(web_contents);
65 }
66
67 } // namespace
68
69 CastWebView::CastWebView(Delegate* delegate,
70 content::BrowserContext* browser_context,
71 scoped_refptr<content::SiteInstance> site_instance,
72 bool transparent)
73 : delegate_(delegate),
74 browser_context_(browser_context),
75 site_instance_(std::move(site_instance)),
76 transparent_(transparent),
77 window_(shell::CastContentWindow::Create(delegate)),
78 web_contents_(CreateWebContents(browser_context_, site_instance_)),
79 weak_factory_(this) {
80 DCHECK(delegate_);
81 DCHECK(browser_context_);
82 DCHECK(window_);
83 content::WebContentsObserver::Observe(web_contents_.get());
84 web_contents_->SetDelegate(this);
85
86 if (transparent_)
87 window_->SetTransparent();
88 }
89
90 CastWebView::~CastWebView() {}
halliwell 2017/02/20 22:09:11 do we need WebContentsObserver::Observe(nullptr),
derekjchow1 2017/02/22 00:50:41 Looks like it's taken care of in the WebContentsOb
91
92 void CastWebView::LoadUrl(GURL url) {
93 web_contents_->GetController().LoadURL(url, content::Referrer(),
94 ui::PAGE_TRANSITION_TYPED, "");
95 }
96
97 void CastWebView::ClosePage() {
98 content::WebContentsObserver::Observe(nullptr);
99 web_contents_->ClosePage();
100 }
101
102 void CastWebView::CloseContents(content::WebContents* source) {
103 DCHECK_EQ(source, web_contents_.get());
104
105 // We need to delay the deletion of web_contents_ (currently for 50ms) to
halliwell 2017/02/20 22:09:11 nit, delete 'currently for 50ms' ... just risks be
derekjchow1 2017/02/22 00:50:41 Done.
106 // give (and guarantee) the renderer enough time to finish 'onunload'
107 // handler (but we don't want to wait any longer than that to delay the
108 // starting of next app).
109 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
110 FROM_HERE, base::Bind(&CastWebView::DelayedCloseContents,
111 weak_factory_.GetWeakPtr()),
112 base::TimeDelta::FromMilliseconds(kWebContentsDestructionDelayInMs));
113 }
114
115 void CastWebView::DelayedCloseContents() {
116 // Delete the WebContents object here so that the gfx surface will be
117 // deleted as part of destroying RenderWidgetHostViewCast object.
118 // We want to delete the surface before we start the next app because
119 // the next app could be an external one whose Start() function would
120 // destroy the primary gfx plane.
121 web_contents_.reset();
122 delegate_->OnPageStopped(net::OK);
123 }
124
125 void CastWebView::Show(CastWindowManager* window_manager) {
126 DCHECK(window_manager);
127 window_->ShowWebContents(web_contents_.get(), window_manager);
128 web_contents_->Focus();
129 }
130
131 content::WebContents* CastWebView::OpenURLFromTab(
132 content::WebContents* source,
133 const content::OpenURLParams& params) {
134 LOG(INFO) << "Change url: " << params.url;
135 // If source is NULL which means current tab, use web_contents_ of this class.
136 if (!source)
137 source = web_contents_.get();
138 DCHECK_EQ(source, web_contents_.get());
139 // We don't want to create another web_contents. Load url only when source is
140 // specified.
141 if (source) {
halliwell 2017/02/20 22:09:11 in what scenario is source null here?
derekjchow1 2017/02/22 00:50:41 I don't think it's ever null. I don't think web_co
142 source->GetController().LoadURL(params.url, params.referrer,
143 params.transition, params.extra_headers);
144 }
145 return source;
146 }
147
148 void CastWebView::LoadingStateChanged(content::WebContents* source,
149 bool to_different_document) {
150 delegate_->OnLoadingStateChanged(source->IsLoading());
151 }
152
153 void CastWebView::ActivateContents(content::WebContents* contents) {
154 DCHECK_EQ(contents, web_contents_.get());
155 contents->GetRenderViewHost()->GetWidget()->Focus();
156 }
157
158 #if defined(OS_ANDROID)
159 base::android::ScopedJavaLocalRef<jobject>
160 CastWebView::GetContentVideoViewEmbedder() {
161 DCHECK(web_contents_);
162 auto activity = shell::CastWebContentsActivity::Get(web_contents_.get());
163 return activity->GetContentVideoViewEmbedder();
164 }
165 #endif // defined(OS_ANDROID)
166
167 void CastWebView::RenderProcessGone(base::TerminationStatus status) {
168 LOG(INFO) << "APP_ERROR_CHILD_PROCESS_CRASHED";
169 delegate_->OnPageStopped(net::ERR_UNEXPECTED);
170 }
171
172 void CastWebView::RenderViewCreated(content::RenderViewHost* render_view_host) {
173 content::RenderWidgetHostView* view =
174 render_view_host->GetWidget()->GetView();
175 if (view) {
176 view->SetBackgroundColor(transparent_ ? SK_ColorTRANSPARENT
177 : SK_ColorBLACK);
178 }
179 }
180
181 void CastWebView::DidFinishNavigation(
182 content::NavigationHandle* navigation_handle) {
183 // If the navigation was not committed, it means either the page was a
184 // download or error 204/205, or the navigation never left the previous
185 // URL. Ignore these navigations.
186 if (!navigation_handle->HasCommitted()) {
187 LOG(WARNING) << "Navigation did not commit: url="
188 << navigation_handle->GetURL();
189 return;
190 }
191
192 net::Error error_code = navigation_handle->GetNetErrorCode();
193 if (!navigation_handle->IsErrorPage())
194 return;
195
196 // If we abort errors in an iframe, it can create a really confusing
197 // and fragile user experience. Rather than create a list of errors
198 // that are most likely to occur, we ignore all of them for now.
199 if (!navigation_handle->IsInMainFrame()) {
200 LOG(ERROR) << "Got error on sub-iframe: url=" << navigation_handle->GetURL()
201 << ", error=" << error_code
202 << ", description=" << net::ErrorToShortString(error_code);
203 return;
204 }
205
206 LOG(ERROR) << "Got error on navigation: url=" << navigation_handle->GetURL()
207 << ", error_code=" << error_code
208 << ", description= " << net::ErrorToShortString(error_code);
209 delegate_->OnPageStopped(error_code);
210 }
211
212 void CastWebView::DidFailLoad(content::RenderFrameHost* render_frame_host,
213 const GURL& validated_url,
214 int error_code,
215 const base::string16& error_description,
216 bool was_ignored_by_handler) {
217 // Only report an error if we are the main frame. See b/8433611.
218 if (render_frame_host->GetParent()) {
219 LOG(ERROR) << "Got error on sub-iframe: url=" << validated_url.spec()
220 << ", error=" << error_code;
221 } else if (error_code == net::ERR_ABORTED) {
222 // ERR_ABORTED means download was aborted by the app, typically this happens
223 // when flinging URL for direct playback, the initial URLRequest gets
224 // cancelled/aborted and then the same URL is requested via the buffered
225 // data source for media::Pipeline playback.
226 LOG(INFO) << "Load canceled: url=" << validated_url.spec();
227 } else {
228 LOG(ERROR) << "Got error on load: url=" << validated_url.spec()
229 << ", error_code=" << error_code;
230 delegate_->OnPageStopped(error_code);
231 }
232 }
233
234 void CastWebView::DidFirstVisuallyNonEmptyPaint() {
235 metrics::CastMetricsHelper::GetInstance()->LogTimeToFirstPaint();
236 }
237
238 void CastWebView::DidStartNavigation(
239 content::NavigationHandle* navigation_handle) {
240 #if defined(USE_AURA)
241 // Resize window
242 gfx::Size display_size =
243 display::Screen::GetScreen()->GetPrimaryDisplay().size();
244 aura::Window* content_window = web_contents()->GetNativeView();
245 content_window->SetBounds(
246 gfx::Rect(display_size.width(), display_size.height()));
247 #endif
248 }
249
250 void CastWebView::MediaStartedPlaying(const MediaPlayerInfo& media_info,
251 const MediaPlayerId& id) {
252 metrics::CastMetricsHelper::GetInstance()->LogMediaPlay();
253 }
254
255 void CastWebView::MediaStoppedPlaying(const MediaPlayerInfo& media_info,
256 const MediaPlayerId& id) {
257 metrics::CastMetricsHelper::GetInstance()->LogMediaPause();
258 }
259
260 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698