15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromecast/shell/browser/android/cast_window_android.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromecast/shell/browser/android/cast_window_manager.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/devtools_agent_host.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h" 128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/navigation_entry.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/renderer_preferences.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "jni/CastWindowAndroid_jni.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromecast { 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace shell { 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// The time (in milliseconds) we wait for after a page is closed (i.e. 238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// after an app is stopped) before we delete the corresponding WebContents. 248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const int kWebContentsDestructionDelayInMs = 50; 258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CastWindowAndroid::RegisterJni(JNIEnv* env) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RegisterNativesImpl(env); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CastWindowAndroid::CastWindowAndroid(content::WebContents* web_contents) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : content::WebContentsObserver(web_contents), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_(this) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CastWindowAndroid::~CastWindowAndroid() { 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CastWindowAndroid* CastWindowAndroid::CreateNewWindow( 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::BrowserContext* browser_context, 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& url) { 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::WebContents::CreateParams create_params(browser_context); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_params.routing_id = MSG_ROUTING_NONE; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents = 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents::Create(create_params); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CastWindowAndroid* shell = CreateCastWindowAndroid( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_params.initial_size); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_empty()) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shell->LoadURL(url); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shell; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CastWindowAndroid* CastWindowAndroid::CreateCastWindowAndroid( 598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) content::WebContents* web_contents, 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const gfx::Size& initial_size) { 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CastWindowAndroid* shell = new CastWindowAndroid(web_contents); 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::android::ScopedJavaLocalRef<jobject> shell_android( 658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CreateCastWindowView(shell)); 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) shell->java_object_.Reset(env, shell_android.Release()); 688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) shell->web_contents_.reset(web_contents); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->SetDelegate(shell); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Java_CastWindowAndroid_initFromNativeWebContents( 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env, shell->java_object_.obj(), reinterpret_cast<jint>(web_contents)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enabling hole-punching also requires runtime renderer preference 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetMutableRendererPrefs()-> 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_video_overlay_for_embedded_encrypted_video = true; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetRenderViewHost()->SyncRendererPrefs(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shell; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CastWindowAndroid::Close() { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close page first, which fires the window.unload event. The WebContents 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // itself will be destroyed after browser-process has received renderer 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notification that the page is closed. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_->GetRenderViewHost()->ClosePage(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CastWindowAndroid::Destroy() { 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note: if multiple windows becomes supported, this may close other devtools 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // sessions. 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::DevToolsAgentHost::DetachAllClients(); 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CloseCastWindowView(java_object_.obj()); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete this; 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CastWindowAndroid::LoadURL(const GURL& url) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NavigationController::LoadURLParams params(url); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.transition_type = ui::PageTransitionFromInt( 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::PAGE_TRANSITION_TYPED | 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents_->GetController().LoadURLWithParams(params); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents_->Focus(); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CastWindowAndroid::AddNewContents(content::WebContents* source, 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::WebContents* new_contents, 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WindowOpenDisposition disposition, 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const gfx::Rect& initial_pos, 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool user_gesture, 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool* was_blocked) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (was_blocked) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *was_blocked = true; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CastWindowAndroid::CloseContents(content::WebContents* source) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(source, web_contents_.get()); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We need to delay the deletion of web_contents_ (currently for 50ms) to 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // give (and guarantee) the renderer enough time to finish 'onunload' 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // handler (but we don't want to wait any longer than that to delay the 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // starting of next app). 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) { 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // When shutting down in a test context, the last remaining WebContents 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is torn down at browser-thread shutdown time. Call Destroy directly to 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // avoid losing the last posted task to delete this object. 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(gunsch): This could probably be avoided by using a 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // CompletionCallback in StopCurrentApp to wait until the app is completely 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // stopped. This might require a separate message loop and might only be 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // appropriate for test contexts or during shutdown, since it triggers a 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // wait on the main thread. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MessageLoopProxy::current()->PostDelayedTask( 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CastWindowAndroid::Destroy, weak_factory_.GetWeakPtr()), 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kWebContentsDestructionDelayInMs)); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CastWindowAndroid::CanOverscrollContent() const { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CastWindowAndroid::AddMessageToConsole(content::WebContents* source, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 level, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::string16& message, 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 line_no, 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::string16& source_id) { 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CastWindowAndroid::ActivateContents(content::WebContents* contents) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(contents, web_contents_.get()); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->GetRenderViewHost()->Focus(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CastWindowAndroid::DeactivateContents(content::WebContents* contents) { 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(contents, web_contents_.get()); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->GetRenderViewHost()->Blur(); 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CastWindowAndroid::RenderProcessGone(base::TerminationStatus status) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Render process gone: status=" << status; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace shell 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chromecast 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)