| Index: chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
|
| diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..49a1f14afd152a51e33bb29eafab327e8639a022
|
| --- /dev/null
|
| +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
|
| @@ -0,0 +1,134 @@
|
| +// 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);
|
| +}
|
|
|