1 // Copyright 2014 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.
5 #include "chromecast/browser/android/cast_window_android.h"
7 #include "base/message_loop/message_loop_proxy.h"
8 #include "chromecast/browser/android/cast_window_manager.h"
9 #include "content/public/browser/devtools_agent_host.h"
10 #include "content/public/browser/navigation_controller.h"
11 #include "content/public/browser/navigation_entry.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/browser/render_view_host.h"
14 #include "content/public/common/renderer_preferences.h"
15 #include "jni/CastWindowAndroid_jni.h"
17 namespace chromecast
{
22 // The time (in milliseconds) we wait for after a page is closed (i.e.
23 // after an app is stopped) before we delete the corresponding WebContents.
24 const int kWebContentsDestructionDelayInMs
= 50;
29 bool CastWindowAndroid::RegisterJni(JNIEnv
* env
) {
30 return RegisterNativesImpl(env
);
33 CastWindowAndroid::CastWindowAndroid(content::WebContents
* web_contents
)
34 : content::WebContentsObserver(web_contents
),
38 CastWindowAndroid::~CastWindowAndroid() {
42 CastWindowAndroid
* CastWindowAndroid::CreateNewWindow(
43 content::BrowserContext
* browser_context
,
45 content::WebContents::CreateParams
create_params(browser_context
);
46 create_params
.routing_id
= MSG_ROUTING_NONE
;
47 content::WebContents
* web_contents
=
48 content::WebContents::Create(create_params
);
49 CastWindowAndroid
* shell
= CreateCastWindowAndroid(
51 create_params
.initial_size
);
58 CastWindowAndroid
* CastWindowAndroid::CreateCastWindowAndroid(
59 content::WebContents
* web_contents
,
60 const gfx::Size
& initial_size
) {
61 CastWindowAndroid
* shell
= new CastWindowAndroid(web_contents
);
63 JNIEnv
* env
= base::android::AttachCurrentThread();
64 base::android::ScopedJavaLocalRef
<jobject
> shell_android(
65 CreateCastWindowView(shell
));
67 shell
->java_object_
.Reset(env
, shell_android
.Release());
68 shell
->web_contents_
.reset(web_contents
);
69 web_contents
->SetDelegate(shell
);
71 Java_CastWindowAndroid_initFromNativeWebContents(
72 env
, shell
->java_object_
.obj(), reinterpret_cast<jint
>(web_contents
),
73 web_contents
->GetRenderProcessHost()->GetID());
75 // Enabling hole-punching also requires runtime renderer preference
76 web_contents
->GetMutableRendererPrefs()->
77 use_video_overlay_for_embedded_encrypted_video
= true;
78 web_contents
->GetRenderViewHost()->SyncRendererPrefs();
83 void CastWindowAndroid::Close() {
84 // Close page first, which fires the window.unload event. The WebContents
85 // itself will be destroyed after browser-process has received renderer
86 // notification that the page is closed.
87 web_contents_
->GetRenderViewHost()->ClosePage();
90 void CastWindowAndroid::Destroy() {
91 // Note: if multiple windows becomes supported, this may close other devtools
93 content::DevToolsAgentHost::DetachAllClients();
94 CloseCastWindowView(java_object_
.obj());
98 void CastWindowAndroid::LoadURL(const GURL
& url
) {
99 content::NavigationController::LoadURLParams
params(url
);
100 params
.transition_type
= ui::PageTransitionFromInt(
101 ui::PAGE_TRANSITION_TYPED
|
102 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
);
103 web_contents_
->GetController().LoadURLWithParams(params
);
104 web_contents_
->Focus();
107 void CastWindowAndroid::AddNewContents(content::WebContents
* source
,
108 content::WebContents
* new_contents
,
109 WindowOpenDisposition disposition
,
110 const gfx::Rect
& initial_pos
,
119 void CastWindowAndroid::CloseContents(content::WebContents
* source
) {
120 DCHECK_EQ(source
, web_contents_
.get());
122 // We need to delay the deletion of web_contents_ (currently for 50ms) to
123 // give (and guarantee) the renderer enough time to finish 'onunload'
124 // handler (but we don't want to wait any longer than that to delay the
125 // starting of next app).
127 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType
)) {
128 // When shutting down in a test context, the last remaining WebContents
129 // is torn down at browser-thread shutdown time. Call Destroy directly to
130 // avoid losing the last posted task to delete this object.
131 // TODO(gunsch): This could probably be avoided by using a
132 // CompletionCallback in StopCurrentApp to wait until the app is completely
133 // stopped. This might require a separate message loop and might only be
134 // appropriate for test contexts or during shutdown, since it triggers a
135 // wait on the main thread.
140 base::MessageLoopProxy::current()->PostDelayedTask(
142 base::Bind(&CastWindowAndroid::Destroy
, weak_factory_
.GetWeakPtr()),
143 base::TimeDelta::FromMilliseconds(kWebContentsDestructionDelayInMs
));
146 bool CastWindowAndroid::CanOverscrollContent() const {
150 bool CastWindowAndroid::AddMessageToConsole(content::WebContents
* source
,
152 const base::string16
& message
,
154 const base::string16
& source_id
) {
158 void CastWindowAndroid::ActivateContents(content::WebContents
* contents
) {
159 DCHECK_EQ(contents
, web_contents_
.get());
160 contents
->GetRenderViewHost()->Focus();
163 void CastWindowAndroid::DeactivateContents(content::WebContents
* contents
) {
164 DCHECK_EQ(contents
, web_contents_
.get());
165 contents
->GetRenderViewHost()->Blur();
168 void CastWindowAndroid::RenderProcessGone(base::TerminationStatus status
) {
169 LOG(ERROR
) << "Render process gone: status=" << status
;
174 } // namespace chromecast