OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chromecast.shell; |
| 6 |
| 7 import android.content.BroadcastReceiver; |
| 8 import android.content.ComponentName; |
| 9 import android.content.Context; |
| 10 import android.content.Intent; |
| 11 import android.content.IntentFilter; |
| 12 import android.content.ServiceConnection; |
| 13 import android.net.Uri; |
| 14 import android.os.IBinder; |
| 15 import android.os.PatternMatcher; |
| 16 import android.support.v4.content.LocalBroadcastManager; |
| 17 |
| 18 import org.chromium.base.Log; |
| 19 import org.chromium.content_public.browser.WebContents; |
| 20 |
| 21 /** |
| 22 * A layer of indirection between CastContentWindowAndroid and CastWebContents(A
ctivity|Service). |
| 23 * <p> |
| 24 * On builds with DISPLAY_WEB_CONTENTS_IN_SERVICE set to false, it will use Cast
WebContentsActivity, |
| 25 * otherwise, it will use CastWebContentsService. |
| 26 */ |
| 27 public class CastWebContentsComponent { |
| 28 /** |
| 29 * Callback interface for when the associated component is closed or the |
| 30 * WebContents is detached. |
| 31 */ |
| 32 public interface OnComponentClosedHandler { void onComponentClosed(); } |
| 33 |
| 34 /** |
| 35 * Callback interface for passing along keyDown events. This only applies |
| 36 * to CastWebContentsActivity, really. |
| 37 */ |
| 38 public interface OnKeyDownHandler { void onKeyDown(int keyCode); } |
| 39 |
| 40 private interface Delegate { |
| 41 void start(Context context, WebContents webContents); |
| 42 void stop(Context context); |
| 43 } |
| 44 |
| 45 private class ActivityDelegate implements Delegate { |
| 46 private static final String TAG = "cr_CastWebComponent_AD"; |
| 47 |
| 48 @Override |
| 49 public void start(Context context, WebContents webContents) { |
| 50 if (DEBUG) Log.d(TAG, "start"); |
| 51 |
| 52 Intent intent = new Intent(Intent.ACTION_VIEW, getInstanceUri(mInsta
nceId), context, |
| 53 CastWebContentsActivity.class); |
| 54 intent.putExtra(ACTION_EXTRA_WEB_CONTENTS, webContents); |
| 55 // FLAG_ACTIVITY_SINGLE_TOP will try to reuse existing activity. |
| 56 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY
_MULTIPLE_TASK |
| 57 | Intent.FLAG_ACTIVITY_SINGLE_TOP); |
| 58 context.startActivity(intent); |
| 59 } |
| 60 |
| 61 @Override |
| 62 public void stop(Context context) { |
| 63 if (DEBUG) Log.d(TAG, "stop"); |
| 64 |
| 65 Intent intent = new Intent( |
| 66 CastWebContentsActivity.ACTION_STOP_ACTIVITY, getInstanceUri
(mInstanceId)); |
| 67 LocalBroadcastManager.getInstance(context).sendBroadcastSync(intent)
; |
| 68 } |
| 69 } |
| 70 |
| 71 private class ServiceDelegate implements Delegate { |
| 72 private static final String TAG = "cr_CastWebComponent_SD"; |
| 73 |
| 74 private ServiceConnection mConnection = new ServiceConnection() { |
| 75 @Override |
| 76 public void onServiceConnected(ComponentName name, IBinder service)
{} |
| 77 |
| 78 @Override |
| 79 public void onServiceDisconnected(ComponentName name) { |
| 80 if (DEBUG) Log.d(TAG, "onServiceDisconnected"); |
| 81 |
| 82 if (mComponentClosedHandler != null) mComponentClosedHandler.onC
omponentClosed(); |
| 83 } |
| 84 }; |
| 85 |
| 86 @Override |
| 87 public void start(Context context, WebContents webContents) { |
| 88 if (DEBUG) Log.d(TAG, "start"); |
| 89 |
| 90 Intent intent = new Intent(Intent.ACTION_VIEW, getInstanceUri(mInsta
nceId), context, |
| 91 CastWebContentsService.class); |
| 92 intent.putExtra(ACTION_EXTRA_WEB_CONTENTS, webContents); |
| 93 context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); |
| 94 } |
| 95 |
| 96 @Override |
| 97 public void stop(Context context) { |
| 98 if (DEBUG) Log.d(TAG, "stop"); |
| 99 |
| 100 context.unbindService(mConnection); |
| 101 } |
| 102 } |
| 103 |
| 104 private class Receiver extends BroadcastReceiver { |
| 105 @Override |
| 106 public void onReceive(Context context, Intent intent) { |
| 107 if (intent.getAction().equals(ACTION_ACTIVITY_STOPPED)) { |
| 108 if (DEBUG) Log.d(TAG, "onReceive ACTION_ACTIVITY_STOPPED"); |
| 109 |
| 110 if (mComponentClosedHandler != null) mComponentClosedHandler.onC
omponentClosed(); |
| 111 } else if (intent.getAction().equals(ACTION_KEY_EVENT)) { |
| 112 if (DEBUG) Log.d(TAG, "onReceive ACTION_KEY_EVENT"); |
| 113 |
| 114 int keyCode = intent.getIntExtra(ACTION_EXTRA_KEY_CODE, 0); |
| 115 if (mKeyDownHandler != null) mKeyDownHandler.onKeyDown(keyCode); |
| 116 } |
| 117 } |
| 118 } |
| 119 |
| 120 static final String ACTION_DATA_SCHEME = "cast"; |
| 121 static final String ACTION_DATA_AUTHORITY = "webcontents"; |
| 122 static final String ACTION_EXTRA_WEB_CONTENTS = |
| 123 "com.google.android.apps.castshell.intent.extra.WEB_CONTENTS"; |
| 124 |
| 125 private static final String TAG = "cr_CastWebComponent"; |
| 126 private static final boolean DEBUG = false; |
| 127 |
| 128 private static final String ACTION_EXTRA_KEY_CODE = |
| 129 "com.google.android.apps.castshell.intent.extra.KEY_CODE"; |
| 130 private static final String ACTION_KEY_EVENT = |
| 131 "com.google.android.apps.castshell.intent.action.KEY_EVENT"; |
| 132 private static final String ACTION_ACTIVITY_STOPPED = |
| 133 "com.google.android.apps.castshell.intent.action.ACTIVITY_STOPPED"; |
| 134 |
| 135 private Delegate mDelegate; |
| 136 private OnComponentClosedHandler mComponentClosedHandler; |
| 137 private OnKeyDownHandler mKeyDownHandler; |
| 138 private Receiver mReceiver; |
| 139 private String mInstanceId; |
| 140 |
| 141 public CastWebContentsComponent(String instanceId, |
| 142 OnComponentClosedHandler onComponentClosedHandler, OnKeyDownHandler
onKeyDownHandler) { |
| 143 mComponentClosedHandler = onComponentClosedHandler; |
| 144 mKeyDownHandler = onKeyDownHandler; |
| 145 mInstanceId = instanceId; |
| 146 if (BuildConfig.DISPLAY_WEB_CONTENTS_IN_SERVICE) { |
| 147 mDelegate = new ServiceDelegate(); |
| 148 } else { |
| 149 mDelegate = new ActivityDelegate(); |
| 150 } |
| 151 } |
| 152 |
| 153 public void start(Context context, WebContents webContents) { |
| 154 if (DEBUG) Log.d(TAG, "start"); |
| 155 |
| 156 Uri instanceUri = getInstanceUri(mInstanceId); |
| 157 mReceiver = new Receiver(); |
| 158 IntentFilter filter = new IntentFilter(); |
| 159 filter.addDataScheme(instanceUri.getScheme()); |
| 160 filter.addDataAuthority(instanceUri.getAuthority(), null); |
| 161 filter.addDataPath(instanceUri.getPath(), PatternMatcher.PATTERN_LITERAL
); |
| 162 filter.addAction(ACTION_ACTIVITY_STOPPED); |
| 163 filter.addAction(ACTION_KEY_EVENT); |
| 164 LocalBroadcastManager.getInstance(context).registerReceiver(mReceiver, f
ilter); |
| 165 |
| 166 mDelegate.start(context, webContents); |
| 167 } |
| 168 |
| 169 public void stop(Context context) { |
| 170 if (DEBUG) Log.d(TAG, "stop"); |
| 171 |
| 172 LocalBroadcastManager.getInstance(context).unregisterReceiver(mReceiver)
; |
| 173 mDelegate.stop(context); |
| 174 } |
| 175 |
| 176 public static void onComponentClosed(Context context, String instanceId) { |
| 177 if (DEBUG) Log.d(TAG, "onComponentClosed"); |
| 178 |
| 179 Intent intent = new Intent(ACTION_ACTIVITY_STOPPED, getInstanceUri(insta
nceId)); |
| 180 LocalBroadcastManager.getInstance(context).sendBroadcastSync(intent); |
| 181 } |
| 182 |
| 183 public static void onKeyDown(Context context, String instanceId, int keyCode
) { |
| 184 if (DEBUG) Log.d(TAG, "onKeyDown"); |
| 185 |
| 186 Intent intent = new Intent(ACTION_KEY_EVENT, getInstanceUri(instanceId))
; |
| 187 intent.putExtra(ACTION_EXTRA_KEY_CODE, keyCode); |
| 188 LocalBroadcastManager.getInstance(context).sendBroadcastSync(intent); |
| 189 } |
| 190 |
| 191 private static Uri getInstanceUri(String instanceId) { |
| 192 Uri instanceUri = new Uri.Builder() |
| 193 .scheme(ACTION_DATA_SCHEME) |
| 194 .authority(ACTION_DATA_AUTHORITY) |
| 195 .path(instanceId) |
| 196 .build(); |
| 197 return instanceUri; |
| 198 } |
| 199 } |
OLD | NEW |