Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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.chromoting; | |
| 6 | |
| 7 import android.app.Activity; | |
| 8 import android.text.TextUtils; | |
| 9 import android.util.Log; | |
| 10 | |
| 11 import java.util.ArrayList; | |
| 12 import java.util.Arrays; | |
| 13 import java.util.List; | |
| 14 | |
| 15 /** | |
| 16 * A manager for the capabilities of the Android client. Based on the negotiated set of | |
| 17 * capabilities, it creates the associated ClientExtensions, and enables their c ommunication with | |
| 18 * the Chromoting host by dispatching extension messages appropriately. | |
| 19 * | |
| 20 * The CapabilityManager mirrors how the Chromoting host handles extension messa ges. For each | |
| 21 * incoming extension message, runs through a list of HostExtensionSession objec ts, giving each one | |
| 22 * a chance to handle the message. | |
| 23 * | |
| 24 * The CapabilityManager is a singleton class so we can manage client extensions on an application | |
| 25 * level. The singleton object may be used from multiple Activities, thus allowi ng it to support | |
| 26 * different capabilities at different stages of the application. | |
| 27 */ | |
| 28 public class CapabilityManager { | |
| 29 | |
| 30 /** Lazily-initialized singleton object that can be used from different Acti vities. */ | |
| 31 private static CapabilityManager sInstance; | |
| 32 | |
| 33 /** Protects access to |sInstance|. */ | |
| 34 private static final Object sInstanceLock = new Object(); | |
| 35 | |
| 36 /** List of all capabilities that are supported by the application. */ | |
| 37 private List<String> mLocalCapabilities; | |
| 38 | |
| 39 /** List of negotiated capabilities received from the host. */ | |
| 40 private List<String> mNegotiatedCapabilities; | |
| 41 | |
| 42 /** List of extensions to the client based on capabilities negotiated with t he host. */ | |
| 43 private List<ClientExtension> mClientExtensions; | |
| 44 | |
| 45 /** | |
| 46 * Constructs the Capability Manager. The same manager is used for an entire application run. | |
|
Lambros
2014/08/14 23:54:25
I don't think this comment is needed.
aiguha
2014/08/15 03:37:29
Done.
| |
| 47 */ | |
| 48 private CapabilityManager() { | |
| 49 mLocalCapabilities = new ArrayList<String>(); | |
| 50 mClientExtensions = new ArrayList<ClientExtension>(); | |
| 51 | |
| 52 mLocalCapabilities.add(Capabilities.CAST_CAPABILITY); | |
| 53 } | |
| 54 | |
| 55 /** | |
| 56 * Returns |sInstance|. Thread-safe. | |
|
Lambros
2014/08/14 23:54:25
nit: Don't reference private fields inside public
aiguha
2014/08/15 03:37:29
Done.
| |
| 57 */ | |
| 58 public static CapabilityManager getInstance() { | |
| 59 synchronized (sInstanceLock) { | |
| 60 if (sInstance == null) { | |
|
Lambros
2014/08/14 23:54:25
nit: the lines inside synchronized {...} should be
aiguha
2014/08/15 03:37:29
Done.
| |
| 61 sInstance = new CapabilityManager(); | |
| 62 } | |
| 63 return sInstance; | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 /** | |
| 68 * Returns a space-separated list (required by host) of the capabilities sup ported using | |
|
Lambros
2014/08/14 23:54:25
nit: Same here. Suggest: "... supported by this cl
aiguha
2014/08/15 03:37:29
Done.
| |
| 69 * |mLocalCapabilities|. | |
| 70 */ | |
| 71 public String getLocalCapabilities() { | |
| 72 return TextUtils.join(" ", mLocalCapabilities); | |
| 73 } | |
| 74 | |
| 75 /** | |
| 76 * Returns the ActivityLifecycleListener associated with the specified capab ility, if | |
| 77 * |capability| is enabled and such a listener exists. | |
| 78 * | |
| 79 * Activities that call this method agree to appropriately notify the listen er of lifecycle | |
| 80 * events., thus supporting |capability|. This allows extensions like the Ca stExtensionHandler | |
|
Lambros
2014/08/14 23:54:25
Not sure what "thus supporting |capability|" means
aiguha
2014/08/15 03:37:29
Discussed offline.
| |
| 81 * to hook into an existing activity's lifecycle. | |
| 82 */ | |
| 83 public ActivityLifecycleListener onActivityAcceptingListener( | |
| 84 Activity activity, String capability) { | |
| 85 | |
| 86 ActivityLifecycleListener listener = new DummyActivityLifecycleListener( ); | |
| 87 | |
| 88 if (isCapabilityEnabled(capability)) { | |
| 89 for (ClientExtension ext : mClientExtensions) { | |
| 90 if (ext.getCapability().equals(capability)) { | |
| 91 listener = ext.onActivityAcceptingListener(activity); | |
| 92 if (listener != null) | |
| 93 return listener; | |
| 94 } | |
| 95 } | |
| 96 } | |
| 97 return listener; | |
| 98 } | |
| 99 | |
| 100 /** | |
| 101 * Receives the capabilities negotiated between client and host and creates the appropriate | |
| 102 * extension handlers. | |
| 103 * | |
| 104 * Currently only the CAST_CAPABILITY exists, so that is the only extension constructed. | |
| 105 */ | |
| 106 public void setNegotiatedCapabilities(String capabilities) { | |
| 107 mNegotiatedCapabilities = Arrays.asList(capabilities.split(" ")); | |
| 108 mClientExtensions.clear(); | |
| 109 if (isCapabilityEnabled(Capabilities.CAST_CAPABILITY)) { | |
| 110 mClientExtensions.add(maybeCreateCastExtensionHandler()); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 /** | |
| 115 * Passes the deconstructed extension message to each ClientExtension in tur n until the message | |
| 116 * is handled or none remain. Returns true if the message was handled. | |
| 117 */ | |
| 118 public boolean onExtensionMessage(String type, String data) { | |
| 119 if (type == null || type.isEmpty()) { | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 for (ClientExtension ext : mClientExtensions) { | |
| 124 if (ext.onExtensionMessage(type, data)) { | |
| 125 return true; | |
| 126 } | |
| 127 } | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 131 /** | |
| 132 * Return true if the capability is enabled for this connection with the hos t. | |
| 133 */ | |
| 134 private boolean isCapabilityEnabled(String capability) { | |
| 135 return (mNegotiatedCapabilities != null && mNegotiatedCapabilities.conta ins(capability)); | |
| 136 } | |
| 137 | |
| 138 /** | |
| 139 * Tries to reflectively instantiate a CastExtensionHandler object. | |
| 140 * | |
| 141 * Note: The ONLY reason this is done is that by default, the regular androi d application | |
| 142 * will be built, without this experimental extension. | |
| 143 */ | |
| 144 private ClientExtension maybeCreateCastExtensionHandler() { | |
| 145 try { | |
| 146 Class<?> cls = Class.forName("org.chromium.chromoting.CastExtensionH andler"); | |
| 147 return (ClientExtension) cls.newInstance(); | |
| 148 } catch (ClassNotFoundException e) { | |
| 149 Log.w("CapabilityManager", "Failed to create CastExtensionHandler.") ; | |
|
Lambros
2014/08/14 23:54:25
Optional: Since the try {} block ends with a retur
aiguha
2014/08/15 03:37:29
I wanted to do this but findbugs complains about i
| |
| 150 return new DummyClientExtension(); | |
| 151 } catch (InstantiationException e) { | |
| 152 Log.w("CapabilityManager", "Failed to create CastExtensionHandler.") ; | |
| 153 return new DummyClientExtension(); | |
| 154 } catch (IllegalAccessException e) { | |
| 155 Log.w("CapabilityManager", "Failed to create CastExtensionHandler.") ; | |
| 156 return new DummyClientExtension(); | |
| 157 } | |
| 158 } | |
| 159 } | |
| OLD | NEW |