Commit 504caf2a authored by derekjchow's avatar derekjchow Committed by Commit bot

[Chromecast] Turn CastContentWindow into an abstract interface.

CastContentWindowImpl is the implementation of CastContentWindow
now. Add a CastContentWindowAndroid specific for Android platform.

BUG=NONE
TEST=cast_shell_apk

Change-Id: I6092f733b54638256bd3028ac3d889f6b52a02fe
Review-Url: https://codereview.chromium.org/2570623003
Cr-Commit-Position: refs/heads/master@{#443358}
parent ea4f0f86
......@@ -21,8 +21,6 @@ shared_library("libcast_shell_android") {
"//chromecast/app/android/cast_jni_loader.cc",
"cast_jni_registrar.cc",
"cast_jni_registrar.h",
"cast_metrics_helper_android.cc",
"cast_metrics_helper_android.h",
]
deps = [
......@@ -36,7 +34,6 @@ shared_library("libcast_shell_android") {
"//chromecast/base:jni_headers",
"//chromecast/base/metrics",
"//chromecast/browser",
"//chromecast/browser:jni_headers",
"//content/public/app:both",
"//content/public/browser",
"//skia",
......
include_rules = [
"+jni",
# TODO(sanfin): Remove cyclic dependency between content and android.
"!chromecast/browser/android",
]
......@@ -7,10 +7,8 @@
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/macros.h"
#include "chromecast/android/cast_metrics_helper_android.h"
#include "chromecast/base/android/system_time_change_notifier_android.h"
#include "chromecast/base/chromecast_config_android.h"
#include "chromecast/browser/android/cast_window_manager.h"
namespace chromecast {
namespace android {
......@@ -18,11 +16,9 @@ namespace android {
namespace {
static base::android::RegistrationMethod kMethods[] = {
{ "CastMetricsHelperAndroid", CastMetricsHelperAndroid::RegisterJni },
{ "CastWindowManager", shell::RegisterCastWindowManager },
{ "ChromecastConfigAndroid", ChromecastConfigAndroid::RegisterJni },
{ "SystemTimeChangeNotifierAndroid",
SystemTimeChangeNotifierAndroid::RegisterJni },
{"ChromecastConfigAndroid", ChromecastConfigAndroid::RegisterJni},
{"SystemTimeChangeNotifierAndroid",
SystemTimeChangeNotifierAndroid::RegisterJni},
};
} // namespace
......
include_rules = [
"+breakpad",
"+chromecast/android",
"+chromecast/browser/android",
"+jni",
]
......@@ -7,6 +7,7 @@
#include "chromecast/android/cast_jni_registrar.h"
#include "chromecast/android/platform_jni_loader.h"
#include "chromecast/app/cast_main_delegate.h"
#include "chromecast/browser/android/jni_registrar.h"
#include "content/public/app/content_jni_onload.h"
#include "content/public/app/content_main.h"
#include "content/public/browser/android/compositor.h"
......@@ -18,6 +19,8 @@ bool RegisterJNI(JNIEnv* env) {
// a separate thread, this should be moved elsewhere.
if (!chromecast::android::RegisterJni(env))
return false;
if (!chromecast::shell::RegisterJni(env))
return false;
// Allow platform-specific implementations to perform more JNI registration.
if (!chromecast::android::PlatformRegisterJni(env))
return false;
......
......@@ -14,10 +14,6 @@ if (is_android) {
source_set("browser") {
sources = [
"android/cast_window_android.cc",
"android/cast_window_android.h",
"android/cast_window_manager.cc",
"android/cast_window_manager.h",
"cast_browser_context.cc",
"cast_browser_context.h",
"cast_browser_main_parts.cc",
......@@ -26,7 +22,6 @@ source_set("browser") {
"cast_browser_process.h",
"cast_content_browser_client.cc",
"cast_content_browser_client.h",
"cast_content_window.cc",
"cast_content_window.h",
"cast_download_manager_delegate.cc",
"cast_download_manager_delegate.h",
......@@ -124,6 +119,8 @@ source_set("browser") {
if (is_linux) {
sources += [
"cast_content_window_linux.cc",
"cast_content_window_linux.h",
"cast_memory_pressure_monitor.cc",
"cast_memory_pressure_monitor.h",
"metrics/external_metrics.cc",
......@@ -136,6 +133,17 @@ source_set("browser") {
"//ui/aura",
]
} else if (is_android) {
sources += [
"android/cast_content_window_android.cc",
"android/cast_content_window_android.h",
"android/cast_metrics_helper_android.cc",
"android/cast_metrics_helper_android.h",
"android/cast_web_contents_activity.cc",
"android/cast_web_contents_activity.h",
"android/jni_registrar.cc",
"android/jni_registrar.h",
]
deps += [ ":jni_headers" ]
}
......@@ -265,11 +273,11 @@ source_set("unittests") {
if (is_android) {
generate_jni("jni_headers") {
sources = [
"android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java",
"android/apk/src/org/chromium/chromecast/shell/CastCrashHandler.java",
"android/apk/src/org/chromium/chromecast/shell/CastMetricsHelper.java",
"android/apk/src/org/chromium/chromecast/shell/CastSysInfoAndroid.java",
"android/apk/src/org/chromium/chromecast/shell/CastWindowAndroid.java",
"android/apk/src/org/chromium/chromecast/shell/CastWindowManager.java",
"android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java",
]
jni_package = "chromecast"
......
......@@ -8,6 +8,7 @@ include_rules = [
"+components/crash",
"+components/network_hints/browser",
"+components/prefs",
"+content/public/android",
"+content/public/browser",
"+content/public/common",
"+content/public/test",
......@@ -25,6 +26,7 @@ include_rules = [
"+ui/aura",
"+ui/base",
"+ui/compositor",
"+ui/events",
"+ui/gfx",
"+ui/gl",
"+ui/display",
......
......@@ -26,13 +26,12 @@ android_library("cast_shell_java") {
"$java_src_dir/org/chromium/chromecast/shell/CastApplication.java",
"$java_src_dir/org/chromium/chromecast/shell/CastAudioManager.java",
"$java_src_dir/org/chromium/chromecast/shell/CastBrowserHelper.java",
"$java_src_dir/org/chromium/chromecast/shell/CastContentWindowAndroid.java",
"$java_src_dir/org/chromium/chromecast/shell/CastCrashHandler.java",
"$java_src_dir/org/chromium/chromecast/shell/CastCrashUploader.java",
"$java_src_dir/org/chromium/chromecast/shell/CastMetricsHelper.java",
"$java_src_dir/org/chromium/chromecast/shell/CastShellActivity.java",
"$java_src_dir/org/chromium/chromecast/shell/CastSysInfoAndroid.java",
"$java_src_dir/org/chromium/chromecast/shell/CastWindowAndroid.java",
"$java_src_dir/org/chromium/chromecast/shell/CastWindowManager.java",
"$java_src_dir/org/chromium/chromecast/shell/CastWebContentsActivity.java",
]
android_manifest = cast_shell_android_manifest
......
......@@ -18,11 +18,12 @@
<application android:name="org.chromium.chromecast.shell.CastApplication"
android:icon="@mipmap/app_icon"
android:label="@string/app_name">
<activity android:name="org.chromium.chromecast.shell.CastShellActivity"
<activity android:name="org.chromium.chromecast.shell.CastWebContentsActivity"
android:theme="@style/CastShellTheme"
android:exported="true"
android:hardwareAccelerated="true"
android:taskAffinity=".CastShellActivity"
android:launchMode="standard"
android:taskAffinity=".CastWebContentsActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
android:excludeFromRecents="true"
android:noHistory="true">
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2014 The Chromium Authors. All rights reserved.
<!-- Copyright 2016 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<org.chromium.chromecast.shell.CastWindowManager
android:id="@+id/shell_container"
<FrameLayout android:id="@+id/web_contents_container"
android:background="#000000"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:layout_weight="1">
</FrameLayout>
</merge>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<org.chromium.chromecast.shell.CastWindowAndroid
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout android:id="@+id/contentview_holder"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</org.chromium.chromecast.shell.CastWindowAndroid>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chromecast.shell;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.PatternMatcher;
import android.support.v4.content.LocalBroadcastManager;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content_public.browser.WebContents;
/**
* The Java component of CastContentWindowAndroid. This class is responsible for
* starting, stopping and monitoring CastWebContentsActivity.
*
* See chromecast/browser/cast_content_window_android.* for the native half.
*/
@JNINamespace("chromecast::shell")
public class CastContentWindowAndroid {
private static final String TAG = "cr_CastContentWindowAndroid";
private static final boolean DEBUG = true;
// Note: CastContentWindowAndroid may outlive the native object. The native
// ref should be checked that it is not zero before it is used.
private long mNativeCastContentWindowAndroid;
private Context mContext;
private IntentFilter mActivityClosedIntentFilter;
private BroadcastReceiver mActivityClosedBroadcastReceiver;
private String mInstanceId;
private static int sInstanceId = 1;
@SuppressWarnings("unused")
@CalledByNative
private static CastContentWindowAndroid create(long nativeCastContentWindowAndroid) {
return new CastContentWindowAndroid(
nativeCastContentWindowAndroid, ContextUtils.getApplicationContext());
}
private CastContentWindowAndroid(long nativeCastContentWindowAndroid, Context context) {
mNativeCastContentWindowAndroid = nativeCastContentWindowAndroid;
mContext = context;
mInstanceId = Integer.toString(sInstanceId++);
}
private Uri getInstanceUri() {
Uri instanceUri = new Uri.Builder()
.scheme(CastWebContentsActivity.ACTION_DATA_SCHEME)
.authority(CastWebContentsActivity.ACTION_DATA_AUTHORITY)
.path(mInstanceId)
.build();
return instanceUri;
}
@SuppressWarnings("unused")
@CalledByNative
private void showWebContents(WebContents webContents) {
if (DEBUG) Log.d(TAG, "showWebContents");
Intent intent = new Intent(
Intent.ACTION_VIEW, getInstanceUri(), mContext, CastWebContentsActivity.class);
mActivityClosedBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == CastWebContentsActivity.ACTION_ACTIVITY_STOPPED) {
onActivityStopped();
} else if (intent.getAction() == CastWebContentsActivity.ACTION_KEY_EVENT) {
int keyCode =
intent.getIntExtra(CastWebContentsActivity.ACTION_EXTRA_KEY_CODE, 0);
onKeyDown(keyCode);
}
}
};
mActivityClosedIntentFilter = new IntentFilter();
mActivityClosedIntentFilter.addDataScheme(intent.getData().getScheme());
mActivityClosedIntentFilter.addDataAuthority(intent.getData().getAuthority(), null);
mActivityClosedIntentFilter.addDataPath(
intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
mActivityClosedIntentFilter.addAction(CastWebContentsActivity.ACTION_ACTIVITY_STOPPED);
mActivityClosedIntentFilter.addAction(CastWebContentsActivity.ACTION_KEY_EVENT);
LocalBroadcastManager.getInstance(mContext).registerReceiver(
mActivityClosedBroadcastReceiver, mActivityClosedIntentFilter);
intent.putExtra(CastWebContentsActivity.ACTION_EXTRA_WEB_CONTENTS, webContents);
// FLAG_ACTIVITY_SINGLE_TOP will try to reuse existing activity.
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
mContext.startActivity(intent);
}
@SuppressWarnings("unused")
@CalledByNative
private void onNativeDestroyed() {
assert mNativeCastContentWindowAndroid != 0;
mNativeCastContentWindowAndroid = 0;
// Note: there is a potential race condition when this function is called after
// showWebContents. If the stop intent is received after the start intent but before
// onCreate, the activity won't shutdown.
// TODO(derekjchow): Add a unittest to check this behaviour. Also consider using
// Instrumentation.startActivitySync to guarentee onCreate is run.
if (DEBUG) Log.d(TAG, "onNativeDestroyed");
Intent intent = new Intent(CastWebContentsActivity.ACTION_STOP_ACTIVITY, getInstanceUri());
LocalBroadcastManager.getInstance(mContext).sendBroadcastSync(intent);
}
private void onActivityStopped() {
if (DEBUG) Log.d(TAG, "onActivityStopped");
if (mNativeCastContentWindowAndroid != 0) {
nativeOnActivityStopped(mNativeCastContentWindowAndroid);
}
}
private void onKeyDown(int keyCode) {
if (DEBUG) Log.d(TAG, "onKeyDown");
if (mNativeCastContentWindowAndroid != 0) {
nativeOnKeyDown(mNativeCastContentWindowAndroid, keyCode);
}
}
private native void nativeOnActivityStopped(long nativeCastContentWindowAndroid);
private native void nativeOnKeyDown(long nativeCastContentWindowAndroid, int keyCode);
}
......@@ -9,9 +9,8 @@ import org.chromium.base.annotations.JNINamespace;
/**
* Wrapper of native CastMetricsHelper.
*/
@JNINamespace("chromecast")
@JNINamespace("chromecast::shell")
public final class CastMetricsHelper {
public static void logMediaPlay() {
nativeLogMediaPlay();
}
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chromecast.shell;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content.browser.ActivityContentVideoViewEmbedder;
import org.chromium.content.browser.ContentVideoViewEmbedder;
import org.chromium.content.browser.ContentView;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.ContentViewRenderView;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.WindowAndroid;
/**
* Container for the various UI components that make up a shell window.
*/
@JNINamespace("chromecast::shell")
public class CastWindowAndroid extends LinearLayout {
public static final String TAG = "CastWindowAndroid";
public static final String ACTION_PAGE_LOADED = "castPageLoaded";
public static final String ACTION_ENABLE_DEV_TOOLS = "castEnableDevTools";
public static final String ACTION_DISABLE_DEV_TOOLS = "castDisableDevTools";
private ContentViewCore mContentViewCore;
private ContentViewRenderView mContentViewRenderView;
private NavigationController mNavigationController;
private int mRenderProcessId;
private WebContents mWebContents;
private WebContentsObserver mWebContentsObserver;
private WindowAndroid mWindow;
/**
* Constructor for inflating via XML.
*/
public CastWindowAndroid(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Set the SurfaceView being renderered to as soon as it is available.
*/
public void setContentViewRenderView(ContentViewRenderView contentViewRenderView) {
FrameLayout contentViewHolder = (FrameLayout) findViewById(R.id.contentview_holder);
if (contentViewRenderView == null) {
if (mContentViewRenderView != null) {
contentViewHolder.removeView(mContentViewRenderView);
}
} else {
contentViewHolder.addView(contentViewRenderView,
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT));
}
mContentViewRenderView = contentViewRenderView;
}
/**
* @param window The owning window for this shell.
*/
public void setWindow(WindowAndroid window) {
mWindow = window;
}
/**
* Loads an URL. This will perform minimal amounts of sanitizing of the URL to attempt to
* make it valid.
*
* @param url The URL to be loaded by the shell.
*/
public void loadUrl(String url) {
if (url == null) return;
if (TextUtils.equals(url, mWebContents.getUrl())) {
mNavigationController.reload(true);
} else {
mNavigationController.loadUrl(new LoadUrlParams(normalizeUrl(url)));
}
// TODO(aurimas): Remove this when crbug.com/174541 is fixed.
mContentViewCore.getContainerView().clearFocus();
mContentViewCore.getContainerView().requestFocus();
}
/**
* Returns the render_process_id for the associated web contents
*/
public int getRenderProcessId() {
return mRenderProcessId;
}
/**
* Given a URI String, performs minimal normalization to attempt to build a usable URL from it.
* @param uriString The passed-in path to be normalized.
* @return The normalized URL, as a string.
*/
private static String normalizeUrl(String uriString) {
if (uriString == null) return uriString;
Uri uri = Uri.parse(uriString);
if (uri.getScheme() == null) {
uri = Uri.parse("http://" + uriString);
}
return uri.toString();
}
/**
* Initializes the ContentView based on the native tab contents pointer passed in.
* @param nativeWebContents The pointer to the native tab contents object.
* @param renderProcessId ID of the corresponding render process host.
* @param productVersion String containing version description.
*/
@SuppressWarnings("unused")
@CalledByNative
private void initFromNativeWebContents(WebContents webContents, int renderProcessId,
String productVersion) {
Context context = getContext();
mContentViewCore = new ContentViewCore(context, productVersion);
ContentView view = ContentView.createContentView(context, mContentViewCore);
mContentViewCore.initialize(ViewAndroidDelegate.createBasicDelegate(view), view,
webContents, mWindow);
mWebContents = mContentViewCore.getWebContents();
mNavigationController = mWebContents.getNavigationController();
mRenderProcessId = renderProcessId;
if (getParent() != null) mContentViewCore.onShow();
((FrameLayout) findViewById(R.id.contentview_holder)).addView(view,
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT));
view.requestFocus();
mContentViewRenderView.setCurrentContentViewCore(mContentViewCore);
mWebContentsObserver = new WebContentsObserver(mWebContents) {
@Override
public void didStopLoading(String url) {
Uri intentUri = Uri.parse(mNavigationController
.getOriginalUrlForVisibleNavigationEntry());
Log.v(TAG, "Broadcast ACTION_PAGE_LOADED: scheme=" + intentUri.getScheme()
+ ", host=" + intentUri.getHost());
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(
new Intent(ACTION_PAGE_LOADED, intentUri));
}
};
}
@CalledByNative
private ContentVideoViewEmbedder getContentVideoViewEmbedder() {
return new ActivityContentVideoViewEmbedder((Activity) getContext());
}
/**
* @return The {@link ViewGroup} currently shown by this Shell.
*/
public ViewGroup getContentView() {
return mContentViewCore.getContainerView();
}
/**
* @return The {@link ContentViewCore} currently managing the view shown by this Shell.
*/
public ContentViewCore getContentViewCore() {
return mContentViewCore;
}
/**
* @return The {@link WebContents} managed by this class.
*/
public WebContents getWebContents() {
return mWebContents;
}
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chromecast.shell;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.ContentViewRenderView;
import org.chromium.ui.base.WindowAndroid;
/**
* Container and generator of CastWindow instances.
*/
@JNINamespace("chromecast::shell")
public class CastWindowManager extends FrameLayout {
private static final String TAG = "CastWindowManager";
private WindowAndroid mWindow;
private CastWindowAndroid mActiveCastWindow;
// The target for all content rendering.
private ContentViewRenderView mContentViewRenderView;
/**
* Delegate to deliver events from the native window.
*/
public interface Delegate {
public void onCreated();
public void onClosed();
}
private Delegate mDelegate;
/**
* Constructor for inflating via XML.
*/
public CastWindowManager(Context context, AttributeSet attrs) {
super(context, attrs);
nativeInit(this);
}
/**
* @param delegate Delegate to handle events.
*/
public void setDelegate(Delegate delegate) {
mDelegate = delegate;
}
/**
* @param window Represents the activity window.
*/
public void setWindow(WindowAndroid window) {
assert window != null;
mWindow = window;
mContentViewRenderView = new ContentViewRenderView(getContext()) {
@Override
protected void onReadyToRender() {
setOverlayVideoMode(true);
}
};
mContentViewRenderView.onNativeLibraryLoaded(window);
// Setting the background color to black avoids rendering a white splash screen
// before the players are loaded. See crbug/307113 for details.
mContentViewRenderView.setSurfaceViewBackgroundColor(Color.BLACK);
}
/**
* @return The window used to generate all shells.
*/
public WindowAndroid getWindow() {
return mWindow;
}
/**
* @return The currently visible shell view or null if one is not showing.
*/
public CastWindowAndroid getActiveCastWindow() {
return mActiveCastWindow;
}
/**
* Creates a new shell pointing to the specified URL.
* @param url The URL the shell should load upon creation.
* @return Pointer of native cast shell instance.
*/
public long launchCastWindow(String url) {
return nativeLaunchCastWindow(url);
}
/**
* Stops a native cast shell instance created by {@link #launchCastWindow(String)}.
* @param nativeCastWindow Pointer of native cast shell instance returned
* by {@link #launchCastWindow(String)}.
* @param gracefully Whether or not to call RVH::ClosePage to deliver unload event.
* @see #launchCastWindow(String)
*/
public void stopCastWindow(long nativeCastWindow, boolean gracefully) {
nativeStopCastWindow(nativeCastWindow, gracefully);
}
@SuppressWarnings("unused")
@CalledByNative
private Object createCastWindow() {
assert mContentViewRenderView != null;
LayoutInflater inflater =
(LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
CastWindowAndroid shellView =
(CastWindowAndroid) inflater.inflate(R.layout.cast_window_view, null);
shellView.setWindow(mWindow);
if (mActiveCastWindow != null) closeCastWindow(mActiveCastWindow);
shellView.setContentViewRenderView(mContentViewRenderView);
addView(shellView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
mActiveCastWindow = shellView;
ContentViewCore contentViewCore = mActiveCastWindow.getContentViewCore();
if (contentViewCore != null) {
mContentViewRenderView.setCurrentContentViewCore(contentViewCore);
contentViewCore.onShow();
}
if (mDelegate != null) {
mDelegate.onCreated();
}
return shellView;
}
@SuppressWarnings("unused")
@CalledByNative
private void closeCastWindow(CastWindowAndroid shellView) {
if (shellView == mActiveCastWindow) mActiveCastWindow = null;
ContentViewCore contentViewCore = shellView.getContentViewCore();
if (contentViewCore != null) contentViewCore.onHide();
shellView.setContentViewRenderView(null);
shellView.setWindow(null);
removeView(shellView);
mContentViewRenderView.destroy();
mContentViewRenderView = null;
if (mDelegate != null) {
mDelegate.onClosed();
}
}
private static native void nativeInit(Object shellManagerInstance);
private static native long nativeLaunchCastWindow(String url);
private static native void nativeStopCastWindow(long pointerOfNativeCastWindow,
boolean gracefully);
public static native void nativeEnableDevTools(boolean enable);
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/android/cast_content_window_android.h"
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/memory/ptr_util.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/renderer_preferences.h"
#include "ipc/ipc_message.h"
#include "jni/CastContentWindowAndroid_jni.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/keyboard_code_conversion_android.h"
namespace chromecast {
namespace shell {
namespace {
base::android::ScopedJavaLocalRef<jobject> CreateJavaWindow(
jlong nativeWindow) {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_CastContentWindowAndroid_create(env, nativeWindow);
}
} // namespace
// static
bool CastContentWindowAndroid::RegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
// static
std::unique_ptr<CastContentWindow> CastContentWindow::Create(
CastContentWindow::Delegate* delegate) {
return base::WrapUnique(new CastContentWindowAndroid(delegate));
}
CastContentWindowAndroid::CastContentWindowAndroid(
CastContentWindow::Delegate* delegate)
: delegate_(delegate),
transparent_(false),
java_window_(CreateJavaWindow(reinterpret_cast<jlong>(this))) {
DCHECK(delegate_);
}
CastContentWindowAndroid::~CastContentWindowAndroid() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_onNativeDestroyed(env, java_window_.obj());
}
void CastContentWindowAndroid::SetTransparent() {
transparent_ = true;
}
void CastContentWindowAndroid::ShowWebContents(
content::WebContents* web_contents) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_web_contents =
web_contents->GetJavaWebContents();
Java_CastContentWindowAndroid_showWebContents(env, java_window_.obj(),
java_web_contents.obj());
}
std::unique_ptr<content::WebContents>
CastContentWindowAndroid::CreateWebContents(
content::BrowserContext* browser_context) {
CHECK(display::Screen::GetScreen());
gfx::Size display_size =
display::Screen::GetScreen()->GetPrimaryDisplay().size();
content::WebContents::CreateParams create_params(browser_context, nullptr);
create_params.routing_id = MSG_ROUTING_NONE;
create_params.initial_size = display_size;
std::unique_ptr<content::WebContents> web_contents(
content::WebContents::Create(create_params));
content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
prefs->use_video_overlay_for_embedded_encrypted_video = true;
web_contents->GetRenderViewHost()->SyncRendererPrefs();
content::WebContentsObserver::Observe(web_contents.get());
return web_contents;
}
void CastContentWindowAndroid::DidFirstVisuallyNonEmptyPaint() {
metrics::CastMetricsHelper::GetInstance()->LogTimeToFirstPaint();
}
void CastContentWindowAndroid::MediaStartedPlaying(
const MediaPlayerInfo& media_info,
const MediaPlayerId& id) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPlay();
}
void CastContentWindowAndroid::MediaStoppedPlaying(
const MediaPlayerInfo& media_info,
const MediaPlayerId& id) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPause();
}
void CastContentWindowAndroid::RenderViewCreated(
content::RenderViewHost* render_view_host) {
content::RenderWidgetHostView* view =
render_view_host->GetWidget()->GetView();
if (view) {
view->SetBackgroundColor(transparent_ ? SK_ColorTRANSPARENT
: SK_ColorBLACK);
}
}
void CastContentWindowAndroid::OnActivityStopped(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller) {
delegate_->OnWindowDestroyed();
}
void CastContentWindowAndroid::OnKeyDown(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
int keycode) {
ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
ui::KeyboardCodeFromAndroidKeyCode(keycode),
ui::EF_NONE);
delegate_->OnKeyEvent(key_event);
}
} // namespace shell
} // namespace chromecast
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BROWSER_ANDROID_CAST_CONTENT_WINDOW_ANDROID_H_
#define CHROMECAST_BROWSER_ANDROID_CAST_CONTENT_WINDOW_ANDROID_H_
#include <jni.h>
#include <memory>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "chromecast/browser/cast_content_window.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
class BrowserContext;
class WebContents;
}
namespace chromecast {
namespace shell {
// Android implementation of CastContentWindow, which displays WebContents in
// CastWebContentsActivity.
class CastContentWindowAndroid : public CastContentWindow,
public content::WebContentsObserver {
public:
static bool RegisterJni(JNIEnv* env);
~CastContentWindowAndroid() override;
// CastContentWindow implementation:
void SetTransparent() override;
void ShowWebContents(content::WebContents* web_contents) override;
std::unique_ptr<content::WebContents> CreateWebContents(
content::BrowserContext* browser_context) override;
// content::WebContentsObserver implementation:
void DidFirstVisuallyNonEmptyPaint() override;
void MediaStartedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) override;
void MediaStoppedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) override;
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
// Called through JNI.
void OnActivityStopped(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller);
void OnKeyDown(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
int keycode);
private:
friend class CastContentWindow;
// This class should only be instantiated by CastContentWindow::Create.
explicit CastContentWindowAndroid(CastContentWindow::Delegate* delegate);
CastContentWindow::Delegate* const delegate_;
bool transparent_;
base::android::ScopedJavaGlobalRef<jobject> java_window_;
DISALLOW_COPY_AND_ASSIGN(CastContentWindowAndroid);
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_ANDROID_CAST_CONTENT_WINDOW_ANDROID_H_
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/android/cast_metrics_helper_android.h"
#include "chromecast/browser/android/cast_metrics_helper_android.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "jni/CastMetricsHelper_jni.h"
......@@ -10,6 +10,7 @@
using base::android::JavaParamRef;
namespace chromecast {
namespace shell {
// static
bool CastMetricsHelperAndroid::RegisterJni(JNIEnv* env) {
......@@ -24,4 +25,5 @@ void LogMediaPause(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPause();
}
} // namespace shell
} // namespace chromecast
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_ANDROID_CAST_METRICS_HELPER_ANDROID_H_
#define CHROMECAST_ANDROID_CAST_METRICS_HELPER_ANDROID_H_
#ifndef CHROMECAST_BROWSER_ANDROID_CAST_METRICS_HELPER_ANDROID_H_
#define CHROMECAST_BROWSER_ANDROID_CAST_METRICS_HELPER_ANDROID_H_
#include <jni.h>
#include <vector>
......@@ -11,7 +11,7 @@
#include "base/macros.h"
namespace chromecast {
namespace shell {
class CastMetricsHelperAndroid {
public:
// Registers the JNI methods for CastMetricsHelperAndroid.
......@@ -21,6 +21,7 @@ class CastMetricsHelperAndroid {
DISALLOW_IMPLICIT_CONSTRUCTORS(CastMetricsHelperAndroid);
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_ANDROID_CAST_METRICS_HELPER_ANDROID_H_
#endif // CHROMECAST_BROWSER_ANDROID_CAST_METRICS_HELPER_ANDROID_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/android/cast_web_contents_activity.h"
#include "content/public/browser/web_contents.h"
#include "jni/CastWebContentsActivity_jni.h"
namespace chromecast {
namespace shell {
namespace {
const void* kCastWebContentsActivityData;
const void* kCastWebContentsActivityKey =
static_cast<const void*>(&kCastWebContentsActivityData);
} // namespace
// static
void SetContentVideoViewEmbedder(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jobject>& webContents,
const base::android::JavaParamRef<jobject>& embedder) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(webContents);
DCHECK(web_contents);
CastWebContentsActivity* activity =
CastWebContentsActivity::Get(web_contents);
activity->SetContentVideoViewEmbedder(embedder);
}
// static
bool CastWebContentsActivity::RegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
// static
CastWebContentsActivity* CastWebContentsActivity::Get(
content::WebContents* web_contents) {
DCHECK(web_contents);
CastWebContentsActivity* instance = static_cast<CastWebContentsActivity*>(
web_contents->GetUserData(kCastWebContentsActivityKey));
if (!instance) {
instance = new CastWebContentsActivity(web_contents);
web_contents->SetUserData(kCastWebContentsActivityKey, instance);
}
return instance;
}
CastWebContentsActivity::CastWebContentsActivity(
content::WebContents* web_contents)
: content_video_view_embedder_(
base::android::ScopedJavaLocalRef<jobject>()) {}
CastWebContentsActivity::~CastWebContentsActivity() {}
base::android::ScopedJavaLocalRef<jobject>
CastWebContentsActivity::GetContentVideoViewEmbedder() {
return base::android::ScopedJavaLocalRef<jobject>(
content_video_view_embedder_);
}
void CastWebContentsActivity::SetContentVideoViewEmbedder(
const base::android::JavaRef<jobject>& content_video_view_embedder) {
content_video_view_embedder_ =
base::android::ScopedJavaGlobalRef<jobject>(content_video_view_embedder);
}
} // namespace shell
} // namespace chromecast
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_ACTIVITY_H_
#define CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_ACTIVITY_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "base/supports_user_data.h"
namespace content {
class WebContents;
}
namespace chromecast {
namespace shell {
// Helper class to get members of the CastWebContentsActivity displaying a
// given web_contents. This class is lazily created through the Get function and
// will manage its own lifetime via SupportsUserData.
class CastWebContentsActivity : base::SupportsUserData::Data {
public:
static bool RegisterJni(JNIEnv* env);
static CastWebContentsActivity* Get(content::WebContents* web_contents);
base::android::ScopedJavaLocalRef<jobject> GetContentVideoViewEmbedder();
void SetContentVideoViewEmbedder(
const base::android::JavaRef<jobject>& content_video_view_embedder);
private:
explicit CastWebContentsActivity(content::WebContents* web_contents);
~CastWebContentsActivity() override;
base::android::ScopedJavaGlobalRef<jobject> content_video_view_embedder_;
DISALLOW_COPY_AND_ASSIGN(CastWebContentsActivity);
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_ACTIVITY_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/android/cast_window_android.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromecast/base/version.h"
#include "chromecast/browser/android/cast_window_manager.h"
#include "chromecast/browser/cast_content_window.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/renderer_preferences.h"
#include "jni/CastWindowAndroid_jni.h"
#include "ui/gfx/skia_util.h"
namespace chromecast {
namespace shell {
namespace {
// The time (in milliseconds) we wait for after a page is closed (i.e.
// after an app is stopped) before we delete the corresponding WebContents.
const int kWebContentsDestructionDelayInMs = 50;
} // namespace
// static
CastWindowAndroid* CastWindowAndroid::CreateNewWindow(
content::BrowserContext* browser_context,
const GURL& url) {
CastWindowAndroid* window_android = new CastWindowAndroid(browser_context);
window_android->Initialize();
if (!url.is_empty())
window_android->LoadURL(url);
content::RenderWidgetHostView* rwhv =
window_android->web_contents_->GetRenderWidgetHostView();
if (rwhv) {
rwhv->SetBackgroundColor(SK_ColorBLACK);
}
return window_android;
}
CastWindowAndroid::CastWindowAndroid(content::BrowserContext* browser_context)
: browser_context_(browser_context),
content_window_(new CastContentWindow),
weak_factory_(this) {
}
void CastWindowAndroid::Initialize() {
web_contents_ = content_window_->CreateWebContents(browser_context_);
web_contents_->SetDelegate(this);
content::WebContentsObserver::Observe(web_contents_.get());
JNIEnv* env = base::android::AttachCurrentThread();
window_java_.Reset(CreateCastWindowView(this));
Java_CastWindowAndroid_initFromNativeWebContents(
env, window_java_, web_contents_->GetJavaWebContents(),
web_contents_->GetRenderProcessHost()->GetID(),
base::android::ConvertUTF8ToJavaString(env, PRODUCT_VERSION));
// Enabling hole-punching also requires runtime renderer preference
content::RendererPreferences* prefs =
web_contents_->GetMutableRendererPrefs();
prefs->use_video_overlay_for_embedded_encrypted_video = true;
web_contents_->GetRenderViewHost()->SyncRendererPrefs();
}
CastWindowAndroid::~CastWindowAndroid() {
}
void CastWindowAndroid::Close() {
// Close page first, which fires the window.unload event. The WebContents
// itself will be destroyed after browser-process has received renderer
// notification that the page is closed.
web_contents_->ClosePage();
}
void CastWindowAndroid::Destroy() {
// Note: if multiple windows becomes supported, this may close other devtools
// sessions.
content::DevToolsAgentHost::DetachAllClients();
CloseCastWindowView(window_java_.obj());
delete this;
}
void CastWindowAndroid::LoadURL(const GURL& url) {
content::NavigationController::LoadURLParams params(url);
params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED |
ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
web_contents_->GetController().LoadURLWithParams(params);
web_contents_->Focus();
}
void CastWindowAndroid::AddNewContents(content::WebContents* source,
content::WebContents* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture,
bool* was_blocked) {
NOTIMPLEMENTED();
if (was_blocked) {
*was_blocked = true;
}
}
void CastWindowAndroid::CloseContents(content::WebContents* source) {
DCHECK_EQ(source, web_contents_.get());
// We need to delay the deletion of web_contents_ (currently for 50ms) to
// give (and guarantee) the renderer enough time to finish 'onunload'
// handler (but we don't want to wait any longer than that to delay the
// starting of next app).
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&CastWindowAndroid::Destroy, weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kWebContentsDestructionDelayInMs));
}
bool CastWindowAndroid::CanOverscrollContent() const {
return false;
}
bool CastWindowAndroid::DidAddMessageToConsole(
content::WebContents* source,
int32_t level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) {
return false;
}
void CastWindowAndroid::ActivateContents(content::WebContents* contents) {
DCHECK_EQ(contents, web_contents_.get());
contents->GetRenderViewHost()->GetWidget()->Focus();
}
base::android::ScopedJavaLocalRef<jobject>
CastWindowAndroid::GetContentVideoViewEmbedder() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_CastWindowAndroid_getContentVideoViewEmbedder(env, window_java_);
}
void CastWindowAndroid::RenderProcessGone(base::TerminationStatus status) {
LOG(ERROR) << "Render process gone: status=" << status;
Destroy();
}
} // namespace shell
} // namespace chromecast
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BROWSER_ANDROID_CAST_WINDOW_ANDROID_H_
#define CHROMECAST_BROWSER_ANDROID_CAST_WINDOW_ANDROID_H_
#include <jni.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/callback_forward.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
class GURL;
namespace content {
class BrowserContext;
class WebContents;
} // namespace content
namespace chromecast {
namespace shell {
class CastContentWindow;
class CastWindowAndroid : public content::WebContentsDelegate,
public content::WebContentsObserver {
public:
// Creates a new window and immediately loads the given URL.
static CastWindowAndroid* CreateNewWindow(
content::BrowserContext* browser_context,
const GURL& url);
~CastWindowAndroid() override;
void LoadURL(const GURL& url);
// Calls RVH::ClosePage() and waits for acknowledgement before closing/
// deleting the window.
void Close();
// Destroys this window immediately.
void Destroy();
// content::WebContentsDelegate implementation:
void AddNewContents(content::WebContents* source,
content::WebContents* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture,
bool* was_blocked) override;
void CloseContents(content::WebContents* source) override;
bool CanOverscrollContent() const override;
bool DidAddMessageToConsole(content::WebContents* source,
int32_t level,
const base::string16& message,
int32_t line_no,
const base::string16& source_id) override;
void ActivateContents(content::WebContents* contents) override;
base::android::ScopedJavaLocalRef<jobject>
GetContentVideoViewEmbedder() override;
// content::WebContentsObserver implementation:
void RenderProcessGone(base::TerminationStatus status) override;
private:
explicit CastWindowAndroid(content::BrowserContext* browser_context);
void Initialize();
content::BrowserContext* browser_context_;
base::android::ScopedJavaGlobalRef<jobject> window_java_;
std::unique_ptr<content::WebContents> web_contents_;
std::unique_ptr<CastContentWindow> content_window_;
base::WeakPtrFactory<CastWindowAndroid> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CastWindowAndroid);
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_ANDROID_CAST_WINDOW_ANDROID_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/android/cast_window_manager.h"
#include <jni.h>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "chromecast/base/pref_names.h"
#include "chromecast/browser/android/cast_window_android.h"
#include "chromecast/browser/cast_browser_context.h"
#include "chromecast/browser/cast_browser_main_parts.h"
#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/cast_content_browser_client.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_channel.h"
#include "jni/CastWindowManager_jni.h"
#include "url/gurl.h"
using base::android::JavaParamRef;
namespace {
base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >
g_window_manager = LAZY_INSTANCE_INITIALIZER;
} // namespace
namespace chromecast {
namespace shell {
base::android::ScopedJavaLocalRef<jobject>
CreateCastWindowView(CastWindowAndroid* shell) {
JNIEnv* env = base::android::AttachCurrentThread();
jobject j_window_manager = g_window_manager.Get().obj();
return Java_CastWindowManager_createCastWindow(env, j_window_manager);
}
void CloseCastWindowView(jobject shell_wrapper) {
JNIEnv* env = base::android::AttachCurrentThread();
jobject j_window_manager = g_window_manager.Get().obj();
Java_CastWindowManager_closeCastWindow(env, j_window_manager, shell_wrapper);
}
// Register native methods
bool RegisterCastWindowManager(JNIEnv* env) {
return RegisterNativesImpl(env);
}
void Init(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jobject>& obj) {
g_window_manager.Get().Reset(obj);
}
jlong LaunchCastWindow(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& jurl) {
GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
return reinterpret_cast<jlong>(
CastWindowAndroid::CreateNewWindow(
CastBrowserProcess::GetInstance()->browser_context(),
url));
}
void StopCastWindow(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
jlong nativeCastWindow,
jboolean gracefully) {
CastWindowAndroid* window =
reinterpret_cast<CastWindowAndroid*>(nativeCastWindow);
DCHECK(window);
if (gracefully)
window->Close();
else
window->Destroy();
}
void EnableDevTools(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
jboolean enable) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
CastBrowserProcess::GetInstance()->pref_service()->SetBoolean(
prefs::kEnableRemoteDebugging, enable);
}
} // namespace shell
} // namespace chromecast
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BROWSER_ANDROID_CAST_WINDOW_MANAGER_H_
#define CHROMECAST_BROWSER_ANDROID_CAST_WINDOW_MANAGER_H_
#include <jni.h>
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
class CastWindowAndroid;
namespace chromecast {
namespace shell {
// Given a CastWindowAndroid instance, creates and returns a Java wrapper.
base::android::ScopedJavaLocalRef<jobject>
CreateCastWindowView(CastWindowAndroid* shell);
// Closes a previously created Java wrapper.
void CloseCastWindowView(jobject shell_wrapper);
// Registers the CastWindowManager native methods.
bool RegisterCastWindowManager(JNIEnv* env);
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_ANDROID_CAST_WINDOW_MANAGER_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/android/jni_registrar.h"
#include "chromecast/browser/android/cast_content_window_android.h"
#include "chromecast/browser/android/cast_metrics_helper_android.h"
#include "chromecast/browser/android/cast_web_contents_activity.h"
namespace chromecast {
namespace shell {
bool RegisterJni(JNIEnv* env) {
if (!CastContentWindowAndroid::RegisterJni(env))
return false;
if (!CastMetricsHelperAndroid::RegisterJni(env))
return false;
if (!CastWebContentsActivity::RegisterJni(env))
return false;
return true;
}
} // namespace shell
} // namespace chromecast
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BROWSER_ANDROID_JNI_REGISTRAR_H_
#define CHROMECAST_BROWSER_ANDROID_JNI_REGISTRAR_H_
#include <jni.h>
namespace chromecast {
namespace shell {
// Register all JNI bindings necessary for the Android cast shell.
bool RegisterJni(JNIEnv* env);
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_ANDROID_JNI_REGISTRAR_H_
......@@ -8,12 +8,7 @@
#include <memory>
#include "base/macros.h"
#include "chromecast/graphics/cast_vsync_settings.h"
#include "content/public/browser/web_contents_observer.h"
namespace aura {
class WindowTreeHost;
}
#include "ui/events/event.h"
namespace content {
class BrowserContext;
......@@ -23,42 +18,40 @@ class WebContents;
namespace chromecast {
namespace shell {
class CastContentWindow : public content::WebContentsObserver,
public CastVSyncSettings::Observer {
// Class that represents the "window" a WebContents is displayed in cast_shell.
// For Linux, this represents an Aura window. For Android, this is a Activity.
// See CastContentWindowLinux and CastContentWindowAndroid.
class CastContentWindow {
public:
CastContentWindow();
// Removes the window from the screen.
~CastContentWindow() override;
// Sets the window's background to be transparent (call before
// CreateWindowTree).
void SetTransparent() { transparent_ = true; }
class Delegate {
public:
virtual void OnWindowDestroyed() = 0;
virtual void OnKeyEvent(const ui::KeyEvent& key_event) = 0;
// Create a full-screen window for |web_contents|.
void CreateWindowTree(content::WebContents* web_contents);
protected:
virtual ~Delegate() {}
};
std::unique_ptr<content::WebContents> CreateWebContents(
content::BrowserContext* browser_context);
// Creates the platform specific CastContentWindow. |delegate| should outlive
// the created CastContentWindow.
static std::unique_ptr<CastContentWindow> Create(
CastContentWindow::Delegate* delegate);
// content::WebContentsObserver implementation:
void DidFirstVisuallyNonEmptyPaint() override;
void MediaStartedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) override;
void MediaStoppedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) override;
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
virtual ~CastContentWindow() {}
// CastVSyncSettings::Observer implementation:
void OnVSyncIntervalChanged(base::TimeDelta interval) override;
// Sets the window's background to be transparent (call before
// CreateWindowTree).
virtual void SetTransparent() = 0;
private:
#if defined(USE_AURA)
std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
#endif
bool transparent_;
// Creates a full-screen window for |web_contents| and display it.
// |web_contents| should outlive this CastContentWindow.
virtual void ShowWebContents(content::WebContents* web_contents) = 0;
DISALLOW_COPY_AND_ASSIGN(CastContentWindow);
// Creates a WebContents.
// TODO(derekjchow): remove this function from this class, since it doesn't
// have anything to do with displaying web_contents.
virtual std::unique_ptr<content::WebContents> CreateWebContents(
content::BrowserContext* browser_context) = 0;
};
} // namespace shell
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/cast_content_window.h"
#include "chromecast/browser/cast_content_window_linux.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
......@@ -60,19 +60,31 @@ class CastFillLayout : public aura::LayoutManager {
};
#endif
CastContentWindow::CastContentWindow() : transparent_(false) {
// static
std::unique_ptr<CastContentWindow> CastContentWindow::Create(
CastContentWindow::Delegate* delegate) {
DCHECK(delegate);
return base::WrapUnique(new CastContentWindowLinux());
}
CastContentWindow::~CastContentWindow() {
CastContentWindowLinux::CastContentWindowLinux() : transparent_(false) {}
CastContentWindowLinux::~CastContentWindowLinux() {
#if defined(USE_AURA)
CastVSyncSettings::GetInstance()->RemoveObserver(this);
window_tree_host_.reset();
// We don't delete the screen here to avoid a CHECK failure when
// the screen size is queried periodically for metric gathering. b/18101124
// We don't delete the screen here to avoid a CHECK failure when
// the screen size is queried periodically for metric gathering. b/18101124
#endif
}
void CastContentWindow::CreateWindowTree(content::WebContents* web_contents) {
void CastContentWindowLinux::SetTransparent() {
DCHECK(!window_tree_host_);
transparent_ = true;
}
void CastContentWindowLinux::ShowWebContents(
content::WebContents* web_contents) {
#if defined(USE_AURA)
// Aura initialization
DCHECK(display::Screen::GetScreen());
......@@ -109,7 +121,7 @@ void CastContentWindow::CreateWindowTree(content::WebContents* web_contents) {
#endif
}
std::unique_ptr<content::WebContents> CastContentWindow::CreateWebContents(
std::unique_ptr<content::WebContents> CastContentWindowLinux::CreateWebContents(
content::BrowserContext* browser_context) {
CHECK(display::Screen::GetScreen());
gfx::Size display_size =
......@@ -118,47 +130,49 @@ std::unique_ptr<content::WebContents> CastContentWindow::CreateWebContents(
content::WebContents::CreateParams create_params(browser_context, NULL);
create_params.routing_id = MSG_ROUTING_NONE;
create_params.initial_size = display_size;
content::WebContents* web_contents = content::WebContents::Create(
create_params);
content::WebContents* web_contents =
content::WebContents::Create(create_params);
#if defined(USE_AURA)
// Resize window
aura::Window* content_window = web_contents->GetNativeView();
content_window->SetBounds(gfx::Rect(display_size.width(),
display_size.height()));
content_window->SetBounds(
gfx::Rect(display_size.width(), display_size.height()));
#endif
content::WebContentsObserver::Observe(web_contents);
return base::WrapUnique(web_contents);
}
void CastContentWindow::DidFirstVisuallyNonEmptyPaint() {
void CastContentWindowLinux::DidFirstVisuallyNonEmptyPaint() {
metrics::CastMetricsHelper::GetInstance()->LogTimeToFirstPaint();
}
void CastContentWindow::MediaStoppedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPause();
void CastContentWindowLinux::MediaStartedPlaying(
const MediaPlayerInfo& media_info,
const MediaPlayerId& id) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPlay();
}
void CastContentWindow::MediaStartedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPlay();
void CastContentWindowLinux::MediaStoppedPlaying(
const MediaPlayerInfo& media_info,
const MediaPlayerId& id) {
metrics::CastMetricsHelper::GetInstance()->LogMediaPause();
}
void CastContentWindow::RenderViewCreated(
void CastContentWindowLinux::RenderViewCreated(
content::RenderViewHost* render_view_host) {
content::RenderWidgetHostView* view =
render_view_host->GetWidget()->GetView();
if (view)
if (view) {
view->SetBackgroundColor(transparent_ ? SK_ColorTRANSPARENT
: SK_ColorBLACK);
}
}
void CastContentWindow::OnVSyncIntervalChanged(base::TimeDelta interval) {
void CastContentWindowLinux::OnVSyncIntervalChanged(base::TimeDelta interval) {
#if defined(USE_AURA)
window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(
interval);
window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(interval);
#endif
}
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_BROWSER_CAST_CONTENT_WINDOW_LINUX_H_
#define CHROMECAST_BROWSER_CAST_CONTENT_WINDOW_LINUX_H_
#include <memory>
#include "base/macros.h"
#include "chromecast/browser/cast_content_window.h"
#include "chromecast/graphics/cast_vsync_settings.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace aura {
class WindowTreeHost;
}
namespace content {
class BrowserContext;
class WebContents;
}
namespace chromecast {
namespace shell {
class CastContentWindowLinux : public CastContentWindow,
public content::WebContentsObserver,
public CastVSyncSettings::Observer {
public:
// Removes the window from the screen.
~CastContentWindowLinux() override;
// CastContentWindow implementation.
void SetTransparent() override;
void ShowWebContents(content::WebContents* web_contents) override;
std::unique_ptr<content::WebContents> CreateWebContents(
content::BrowserContext* browser_context) override;
// content::WebContentsObserver implementation:
void DidFirstVisuallyNonEmptyPaint() override;
void MediaStartedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) override;
void MediaStoppedPlaying(const MediaPlayerInfo& media_info,
const MediaPlayerId& id) override;
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
// CastVSyncSettings::Observer implementation:
void OnVSyncIntervalChanged(base::TimeDelta interval) override;
private:
friend class CastContentWindow;
// This class should only be instantiated by CastContentWindow::Create.
CastContentWindowLinux();
#if defined(USE_AURA)
std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
#endif
bool transparent_;
DISALLOW_COPY_AND_ASSIGN(CastContentWindowLinux);
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_CAST_CONTENT_WINDOW_LINUX_H_
......@@ -4,9 +4,11 @@
#include "chromecast/browser/service/cast_service_simple.h"
#include <string>
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "chromecast/browser/cast_content_window.h"
#include "base/memory/ptr_util.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "net/base/filename_util.h"
......@@ -51,9 +53,9 @@ void CastServiceSimple::FinalizeInternal() {
}
void CastServiceSimple::StartInternal() {
window_.reset(new CastContentWindow);
window_ = CastContentWindow::Create(this);
web_contents_ = window_->CreateWebContents(browser_context());
window_->CreateWindowTree(web_contents_.get());
window_->ShowWebContents(web_contents_.get());
web_contents_->GetController().LoadURL(startup_url_, content::Referrer(),
ui::PAGE_TRANSITION_TYPED,
......@@ -66,5 +68,9 @@ void CastServiceSimple::StopInternal() {
window_.reset();
}
void CastServiceSimple::OnWindowDestroyed() {}
void CastServiceSimple::OnKeyEvent(const ui::KeyEvent& key_event) {}
} // namespace shell
} // namespace chromecast
......@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
#include "chromecast/browser/cast_content_window.h"
#include "chromecast/service/cast_service.h"
#include "url/gurl.h"
......@@ -17,9 +18,9 @@ class WebContents;
namespace chromecast {
namespace shell {
class CastContentWindow;
class CastServiceSimple : public CastService {
class CastServiceSimple : public CastService,
public CastContentWindow::Delegate {
public:
CastServiceSimple(content::BrowserContext* browser_context,
PrefService* pref_service);
......@@ -32,6 +33,10 @@ class CastServiceSimple : public CastService {
void StartInternal() override;
void StopInternal() override;
// CastContentWindow::Delegate implementation:
void OnWindowDestroyed() override;
void OnKeyEvent(const ui::KeyEvent& key_event) override;
private:
std::unique_ptr<CastContentWindow> window_;
std::unique_ptr<content::WebContents> web_contents_;
......
......@@ -60,11 +60,11 @@ void CastBrowserTest::RunTestOnMainThreadLoop() {
}
content::WebContents* CastBrowserTest::NavigateToURL(const GURL& url) {
window_ = base::MakeUnique<CastContentWindow>();
window_ = CastContentWindow::Create(this);
web_contents_ = window_->CreateWebContents(
CastBrowserProcess::GetInstance()->browser_context());
window_->CreateWindowTree(web_contents_.get());
window_->ShowWebContents(web_contents_.get());
content::WaitForLoadStop(web_contents_.get());
content::TestNavigationObserver same_tab_observer(web_contents_.get(), 1);
......@@ -77,5 +77,9 @@ content::WebContents* CastBrowserTest::NavigateToURL(const GURL& url) {
return web_contents_.get();
}
void CastBrowserTest::OnWindowDestroyed() {}
void CastBrowserTest::OnKeyEvent(const ui::KeyEvent& key_event) {}
} // namespace shell
} // namespace chromecast
......@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
#include "chromecast/browser/cast_content_window.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_base.h"
......@@ -18,14 +19,13 @@ class WebContents;
namespace chromecast {
namespace shell {
class CastContentWindow;
// This test allows for running an entire browser-process lifecycle per unit
// test, using Chromecast's cast_shell. This starts up the shell, runs a test
// case, then shuts down the entire shell.
// Note that this process takes 7-10 seconds per test case on Chromecast, so
// fewer test cases with more assertions are preferable.
class CastBrowserTest : public content::BrowserTestBase {
class CastBrowserTest : public content::BrowserTestBase,
CastContentWindow::Delegate {
protected:
CastBrowserTest();
~CastBrowserTest() override;
......@@ -39,6 +39,10 @@ class CastBrowserTest : public content::BrowserTestBase {
content::WebContents* NavigateToURL(const GURL& url);
private:
// CastContentWindow::Delegate implementation:
void OnWindowDestroyed() override;
void OnKeyEvent(const ui::KeyEvent& key_event) override;
std::unique_ptr<CastContentWindow> window_;
std::unique_ptr<content::WebContents> web_contents_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment