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

Side by Side Diff: chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java

Issue 2874943002: [Chromecast] Add service for "displaying" cast web contents. (Closed)
Patch Set: Created 3 years, 7 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chromecast.shell; 5 package org.chromium.chromecast.shell;
6 6
7 import android.app.Activity; 7 import android.app.Activity;
8 import android.content.BroadcastReceiver; 8 import android.content.BroadcastReceiver;
9 import android.content.Context; 9 import android.content.Context;
10 import android.content.Intent; 10 import android.content.Intent;
11 import android.content.IntentFilter; 11 import android.content.IntentFilter;
12 import android.graphics.Color; 12 import android.graphics.Color;
13 import android.media.AudioManager; 13 import android.media.AudioManager;
14 import android.net.Uri;
15 import android.os.Bundle; 14 import android.os.Bundle;
16 import android.os.Handler; 15 import android.os.Handler;
17 import android.os.PatternMatcher; 16 import android.os.PatternMatcher;
18 import android.support.v4.content.LocalBroadcastManager; 17 import android.support.v4.content.LocalBroadcastManager;
19 import android.view.KeyEvent; 18 import android.view.KeyEvent;
20 import android.view.MotionEvent; 19 import android.view.MotionEvent;
21 import android.view.WindowManager; 20 import android.view.WindowManager;
22 import android.widget.FrameLayout; 21 import android.widget.FrameLayout;
23 import android.widget.Toast; 22 import android.widget.Toast;
24 23
25 import org.chromium.base.Log; 24 import org.chromium.base.Log;
26 import org.chromium.base.annotations.JNINamespace; 25 import org.chromium.base.annotations.JNINamespace;
27 import org.chromium.content.browser.ActivityContentVideoViewEmbedder; 26 import org.chromium.content.browser.ActivityContentVideoViewEmbedder;
28 import org.chromium.content.browser.ContentVideoViewEmbedder; 27 import org.chromium.content.browser.ContentVideoViewEmbedder;
29 import org.chromium.content.browser.ContentView; 28 import org.chromium.content.browser.ContentView;
30 import org.chromium.content.browser.ContentViewCore; 29 import org.chromium.content.browser.ContentViewCore;
31 import org.chromium.content.browser.ContentViewRenderView; 30 import org.chromium.content.browser.ContentViewRenderView;
32 import org.chromium.content_public.browser.WebContents; 31 import org.chromium.content_public.browser.WebContents;
33 import org.chromium.ui.base.ViewAndroidDelegate; 32 import org.chromium.ui.base.ViewAndroidDelegate;
34 import org.chromium.ui.base.WindowAndroid; 33 import org.chromium.ui.base.WindowAndroid;
35 34
36 /** 35 /**
37 * Activity for displaying a WebContents in CastShell. 36 * Activity for displaying a WebContents in CastShell.
38 * 37 * <p>
39 * Typically, this class is controlled by CastContentWindowAndroid, which will 38 * Typically, this class is controlled by CastContentWindowAndroid, which will
40 * start a new instance of this activity. If the CastContentWindowAndroid is 39 * start a new instance of this activity. If the CastContentWindowAndroid is
41 * destroyed, CastWebContentsActivity should finish(). Similarily, if this 40 * destroyed, CastWebContentsActivity should finish(). Similarily, if this
42 * activity is destroyed, CastContentWindowAndroid should be notified by intent. 41 * activity is destroyed, CastContentWindowAndroid should be notified by intent.
43 */ 42 */
44 @JNINamespace("chromecast::shell") 43 @JNINamespace("chromecast::shell")
45 public class CastWebContentsActivity extends Activity { 44 public class CastWebContentsActivity extends Activity {
46 private static final String TAG = "cr_CastWebActivity"; 45 private static final String TAG = "cr_CastWebActivity";
47 private static final boolean DEBUG = true; 46 private static final boolean DEBUG = true;
48 47
49 private Handler mHandler; 48 private Handler mHandler;
50 private String mInstanceId; 49 private String mInstanceId;
51 private BroadcastReceiver mWindowDestroyedBroadcastReceiver; 50 private BroadcastReceiver mWindowDestroyedBroadcastReceiver;
52 private IntentFilter mWindowDestroyedIntentFilter; 51 private IntentFilter mWindowDestroyedIntentFilter;
53 private FrameLayout mCastWebContentsLayout; 52 private FrameLayout mCastWebContentsLayout;
54 private AudioManager mAudioManager; 53 private AudioManager mAudioManager;
55 private ContentViewRenderView mContentViewRenderView; 54 private ContentViewRenderView mContentViewRenderView;
56 private WindowAndroid mWindow; 55 private WindowAndroid mWindow;
57 private ContentViewCore mContentViewCore; 56 private ContentViewCore mContentViewCore;
58 private ContentView mContentView; 57 private ContentView mContentView;
59 private boolean mReceivedUserLeave = false; 58 private boolean mReceivedUserLeave = false;
60 59
61 private static final int TEARDOWN_GRACE_PERIOD_TIMEOUT_MILLIS = 300; 60 private static final int TEARDOWN_GRACE_PERIOD_TIMEOUT_MILLIS = 300;
62 public static final String ACTION_DATA_SCHEME = "cast"; 61 public static final String ACTION_DATA_SCHEME = "cast";
63 public static final String ACTION_DATA_AUTHORITY = "webcontents"; 62 public static final String ACTION_DATA_AUTHORITY = "webcontents";
64 63
65 public static final String ACTION_EXTRA_WEB_CONTENTS = 64 public static final String ACTION_EXTRA_WEB_CONTENTS =
66 "com.google.android.apps.castshell.intent.extra.WEB_CONTENTS"; 65 "com.google.android.apps.castshell.intent.extra.WEB_CONTENTS";
67 public static final String ACTION_EXTRA_KEY_CODE =
68 "com.google.android.apps.castshell.intent.extra.KEY_CODE";
69 public static final String ACTION_KEY_EVENT =
70 "com.google.android.apps.castshell.intent.action.KEY_EVENT";
71 public static final String ACTION_STOP_ACTIVITY = 66 public static final String ACTION_STOP_ACTIVITY =
72 "com.google.android.apps.castshell.intent.action.STOP_ACTIVITY"; 67 "com.google.android.apps.castshell.intent.action.STOP_ACTIVITY";
73 public static final String ACTION_ACTIVITY_STOPPED =
74 "com.google.android.apps.castshell.intent.action.ACTIVITY_STOPPED";
75 68
76 /* 69 /*
77 * Intended to be called from "onStop" to determine if this is a "legitimate " stop or not. 70 * Intended to be called from "onStop" to determine if this is a "legitimate " stop or not.
78 * When starting CastShellActivity from the TV in sleep mode, an extra onPau se/onStop will be 71 * When starting CastShellActivity from the TV in sleep mode, an extra onPau se/onStop will be
79 * fired. 72 * fired.
80 * Details: http://stackoverflow.com/questions/25369909/ 73 * Details: http://stackoverflow.com/questions/25369909/
81 * We use onUserLeaveHint to determine if the onPause/onStop called because of user intent. 74 * We use onUserLeaveHint to determine if the onPause/onStop called because of user intent.
82 */ 75 */
83 private boolean isStopping() { 76 private boolean isStopping() {
84 return mReceivedUserLeave; 77 return mReceivedUserLeave;
85 } 78 }
86 79
87 @Override 80 @Override
88 protected void onCreate(final Bundle savedInstanceState) { 81 protected void onCreate(final Bundle savedInstanceState) {
89 if (DEBUG) Log.d(TAG, "onCreate"); 82 if (DEBUG) Log.d(TAG, "onCreate");
90 super.onCreate(savedInstanceState); 83 super.onCreate(savedInstanceState);
91 84
92 mHandler = new Handler(); 85 mHandler = new Handler();
93 86
94 // TODO(derekjchow): Remove this call. 87 // TODO(derekjchow): Remove this call.
Simeon 2017/05/15 19:47:24 Do the unittests have a problem if we remove the i
thoren 2017/05/15 22:25:23 Doesn't seem to break anything. Done
95 if (!CastBrowserHelper.initializeBrowser(getApplicationContext())) { 88 if (!CastBrowserHelper.initializeBrowser(getApplicationContext())) {
96 Toast.makeText(this, R.string.browser_process_initialization_failed, Toast.LENGTH_SHORT) 89 Toast.makeText(this, R.string.browser_process_initialization_failed, Toast.LENGTH_SHORT)
97 .show(); 90 .show();
98 finish(); 91 finish();
99 } 92 }
100 93
101 // Whenever our app is visible, volume controls should modify the music stream. 94 // Whenever our app is visible, volume controls should modify the music stream.
102 // For more information read: 95 // For more information read:
103 // http://developer.android.com/training/managing-audio/volume-playback. html 96 // http://developer.android.com/training/managing-audio/volume-playback. html
104 setVolumeControlStream(AudioManager.STREAM_MUSIC); 97 setVolumeControlStream(AudioManager.STREAM_MUSIC);
(...skipping 26 matching lines...) Expand all
131 FrameLayout.LayoutParams.MATCH_PARENT)); 124 FrameLayout.LayoutParams.MATCH_PARENT));
132 125
133 Intent intent = getIntent(); 126 Intent intent = getIntent();
134 handleIntent(intent); 127 handleIntent(intent);
135 } 128 }
136 129
137 protected void handleIntent(Intent intent) { 130 protected void handleIntent(Intent intent) {
138 intent.setExtrasClassLoader(WebContents.class.getClassLoader()); 131 intent.setExtrasClassLoader(WebContents.class.getClassLoader());
139 mInstanceId = intent.getData().getPath(); 132 mInstanceId = intent.getData().getPath();
140 133
141 final String instanceId = mInstanceId;
142 if (mWindowDestroyedBroadcastReceiver != null) { 134 if (mWindowDestroyedBroadcastReceiver != null) {
143 LocalBroadcastManager.getInstance(this).unregisterReceiver( 135 LocalBroadcastManager.getInstance(this).unregisterReceiver(
144 mWindowDestroyedBroadcastReceiver); 136 mWindowDestroyedBroadcastReceiver);
145 } 137 }
146 mWindowDestroyedBroadcastReceiver = new BroadcastReceiver() { 138 mWindowDestroyedBroadcastReceiver = new BroadcastReceiver() {
147 @Override 139 @Override
148 public void onReceive(Context context, Intent intent) { 140 public void onReceive(Context context, Intent intent) {
149 detachWebContentsIfAny(); 141 detachWebContentsIfAny();
150 maybeFinishLater(); 142 maybeFinishLater();
151 } 143 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 releaseStreamMuteIfNecessary(); 200 releaseStreamMuteIfNecessary();
209 } 201 }
210 super.onStop(); 202 super.onStop();
211 } 203 }
212 204
213 @Override 205 @Override
214 protected void onResume() { 206 protected void onResume() {
215 if (DEBUG) Log.d(TAG, "onResume"); 207 if (DEBUG) Log.d(TAG, "onResume");
216 super.onResume(); 208 super.onResume();
217 209
218 if (mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, 210 if (mAudioManager.requestAudioFocus(
219 AudioManager.AUDIOFOCUS_GAIN) != AudioManager.AUDIOFOCUS_REQ UEST_GRANTED) { 211 null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAI N)
212 != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
220 Log.e(TAG, "Failed to obtain audio focus"); 213 Log.e(TAG, "Failed to obtain audio focus");
221 } 214 }
222 } 215 }
223 216
224 @Override 217 @Override
225 protected void onPause() { 218 protected void onPause() {
226 if (DEBUG) Log.d(TAG, "onPause"); 219 if (DEBUG) Log.d(TAG, "onPause");
227 super.onPause(); 220 super.onPause();
228 221
229 // Release the audio focus. Note that releasing audio focus does not sto p audio playback, 222 // Release the audio focus. Note that releasing audio focus does not sto p audio playback,
(...skipping 17 matching lines...) Expand all
247 240
248 // Similar condition for all single-click events. 241 // Similar condition for all single-click events.
249 if (action == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { 242 if (action == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
250 if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER 243 if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER
251 || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE 244 || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
252 || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY 245 || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY
253 || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE 246 || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE
254 || keyCode == KeyEvent.KEYCODE_MEDIA_STOP 247 || keyCode == KeyEvent.KEYCODE_MEDIA_STOP
255 || keyCode == KeyEvent.KEYCODE_MEDIA_NEXT 248 || keyCode == KeyEvent.KEYCODE_MEDIA_NEXT
256 || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS) { 249 || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS) {
257 Intent intent = new Intent(ACTION_KEY_EVENT, getInstanceUri()); 250 CastWebContentsComponent.onKeyDown(this, mInstanceId, keyCode);
258 intent.putExtra(ACTION_EXTRA_KEY_CODE, keyCode);
259 LocalBroadcastManager.getInstance(this).sendBroadcastSync(intent );
260 251
261 // Stop key should end the entire session. 252 // Stop key should end the entire session.
262 if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) { 253 if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) {
263 mReceivedUserLeave = true; 254 mReceivedUserLeave = true;
264 finish(); 255 finish();
265 } 256 }
266 257
267 return true; 258 return true;
268 } 259 }
269 } 260 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // Set ContentVideoViewEmbedder to allow video playback. 326 // Set ContentVideoViewEmbedder to allow video playback.
336 nativeSetContentVideoViewEmbedder(webContents, new ActivityContentVideoV iewEmbedder(this)); 327 nativeSetContentVideoViewEmbedder(webContents, new ActivityContentVideoV iewEmbedder(this));
337 328
338 // TODO(derekjchow): productVersion 329 // TODO(derekjchow): productVersion
339 mContentViewCore = new ContentViewCore(this, ""); 330 mContentViewCore = new ContentViewCore(this, "");
340 mContentView = ContentView.createContentView(this, mContentViewCore); 331 mContentView = ContentView.createContentView(this, mContentViewCore);
341 mContentViewCore.initialize(ViewAndroidDelegate.createBasicDelegate(mCon tentView), 332 mContentViewCore.initialize(ViewAndroidDelegate.createBasicDelegate(mCon tentView),
342 mContentView, webContents, mWindow); 333 mContentView, webContents, mWindow);
343 // Enable display of current webContents. 334 // Enable display of current webContents.
344 if (getParent() != null) mContentViewCore.onShow(); 335 if (getParent() != null) mContentViewCore.onShow();
345 mCastWebContentsLayout.addView( 336 mCastWebContentsLayout.addView(mContentView,
346 mContentView, new FrameLayout.LayoutParams(FrameLayout.LayoutPar ams.MATCH_PARENT, 337 new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARE NT,
347 FrameLayout.LayoutPar ams.MATCH_PARENT)); 338 FrameLayout.LayoutParams.MATCH_PARENT));
348 mContentView.requestFocus(); 339 mContentView.requestFocus();
349 mContentViewRenderView.setCurrentContentViewCore(mContentViewCore); 340 mContentViewRenderView.setCurrentContentViewCore(mContentViewCore);
350 } 341 }
351 342
352 // Remove the currently displayed webContents. no-op if nothing is being dis played. 343 // Remove the currently displayed webContents. no-op if nothing is being dis played.
353 private void detachWebContentsIfAny() { 344 private void detachWebContentsIfAny() {
354 if (DEBUG) Log.d(TAG, "detachWebContentsIfAny"); 345 if (DEBUG) Log.d(TAG, "detachWebContentsIfAny");
355 if (mContentView != null) { 346 if (mContentView != null) {
356 mCastWebContentsLayout.removeView(mContentView); 347 mCastWebContentsLayout.removeView(mContentView);
357 mContentView = null; 348 mContentView = null;
358 mContentViewCore = null; 349 mContentViewCore = null;
359 350
360 // Inform CastContentWindowAndroid we're detaching. 351 CastWebContentsComponent.onComponentClosed(this, mInstanceId);
361 Intent intent = new Intent(ACTION_ACTIVITY_STOPPED, getInstanceUri() );
362 LocalBroadcastManager.getInstance(this).sendBroadcastSync(intent);
363 } 352 }
364 } 353 }
365 354
366 private Uri getInstanceUri() {
367 Uri instanceUri = new Uri.Builder()
368 .scheme(CastWebContentsActivity.ACTION_DATA_SCHEME)
369 .authority(CastWebContentsActivity.ACTION_DATA_AUTHORITY)
370 .path(mInstanceId)
371 .build();
372 return instanceUri;
373 }
374
375 private native void nativeSetContentVideoViewEmbedder( 355 private native void nativeSetContentVideoViewEmbedder(
376 WebContents webContents, ContentVideoViewEmbedder embedder); 356 WebContents webContents, ContentVideoViewEmbedder embedder);
377 } 357 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698