| Index: remoting/android/java/src/org/chromium/chromoting/CapabilityManager.java
|
| diff --git a/remoting/android/java/src/org/chromium/chromoting/CapabilityManager.java b/remoting/android/java/src/org/chromium/chromoting/CapabilityManager.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f6b2a29858166189bd7e3006478669b3f2670faa
|
| --- /dev/null
|
| +++ b/remoting/android/java/src/org/chromium/chromoting/CapabilityManager.java
|
| @@ -0,0 +1,134 @@
|
| +// 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.chromoting;
|
| +
|
| +import android.app.Activity;
|
| +import android.text.TextUtils;
|
| +import android.util.Log;
|
| +
|
| +import java.util.ArrayList;
|
| +import java.util.Arrays;
|
| +import java.util.List;
|
| +
|
| +/**
|
| + * A manager for the capabilities of the Android client, in charge of creating any required
|
| + * extension handlers based on capability negotiation.
|
| + * TODO(aiguha): CapabilityManager currently mimicks the webapp in terms of how it handles
|
| + * extension messages. By this, I mean that it itself routes messages to different handlers based
|
| + * on the message's type. This is in contrast to the Chromoting host, which, for each incoming
|
| + * extension message, runs through a list of HostExtensionSession objects, giving each one a chance
|
| + * to handle the message.
|
| + */
|
| +public class CapabilityManager {
|
| +
|
| + /** Singleton object that can be used from different Activities within the application. */
|
| + private static CapabilityManager sInstance;
|
| +
|
| + /** The list of all capabilities that are supported by the app. */
|
| + private List<String> mLocalCapabilities;
|
| +
|
| + /** The list of negotiated capabilities received from the host. */
|
| + private List<String> mNegotiatedCapabilities;
|
| +
|
| + /** List of extensions to the client based on capabilities negotiated with the host. */
|
| + private List<ClientExtension> mClientExtensions;
|
| +
|
| + private CapabilityManager() {
|
| + mLocalCapabilities = new ArrayList<String>();
|
| + mClientExtensions = new ArrayList<ClientExtension>();
|
| +
|
| + mLocalCapabilities.add(Capabilities.CAST_CAPABILITY);
|
| + }
|
| +
|
| + public static CapabilityManager getInstance() {
|
| + synchronized (CapabilityManager.class) {
|
| + if (sInstance == null) {
|
| + sInstance = new CapabilityManager();
|
| + }
|
| + return sInstance;
|
| + }
|
| + }
|
| +
|
| + /** Returns a space separated list of the capabilities supported using mLocalCapabilities.*/
|
| + public String getLocalCapabilities() {
|
| + return TextUtils.join(" ", mLocalCapabilities);
|
| + }
|
| +
|
| + /**
|
| + * Returns the ActivityLifecycleListener associated with the specified capability, if capability
|
| + * is enabled and such a listener exists. Activities that call this method agree to support this
|
| + * capability by appropriately notifying the listener of lifecycle events. This allows
|
| + * extensions like the CastExtensionHandler to hook into an existing activity's lifecycle.
|
| + */
|
| + public ActivityLifecycleListener onActivityAcceptingListener(
|
| + Activity activity, String capability) {
|
| +
|
| + ActivityLifecycleListener listener = new DummyActivityLifecycleListener();
|
| +
|
| + if (isCapabilityEnabled(capability)) {
|
| + for (ClientExtension ext : mClientExtensions) {
|
| + if (ext.getCapability().equals(capability)) {
|
| + listener = ext.onActivityAcceptingListener(activity);
|
| + if (listener != null)
|
| + return listener;
|
| + }
|
| + }
|
| + }
|
| + return listener;
|
| + }
|
| +
|
| + /**
|
| + * Receives the capabilities negotiated between client and host and creates the appropriate
|
| + * extension handlers.
|
| + */
|
| + public void setNegotiatedCapabilities(String capabilities) {
|
| + mNegotiatedCapabilities = Arrays.asList(capabilities.split(" "));
|
| +
|
| + if (isCapabilityEnabled(Capabilities.CAST_CAPABILITY)) {
|
| + mClientExtensions.add(tryConstructingCastExtensionHandler());
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Passes the deconstructed extension message to each ClientExtension in turn until the message
|
| + * is handled or none remain. Returns true if the message was handled.
|
| + */
|
| + public boolean onExtensionMessage(String type, String data) {
|
| + if (type == null || type.isEmpty()) {
|
| + return false;
|
| + }
|
| +
|
| + for (ClientExtension ext : mClientExtensions) {
|
| + if (ext.onExtensionMessage(type, data)) {
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + Log.i("CapabilityManager", String.format("Unexpected Message: (%s, %s)", type, data));
|
| + return false;
|
| + }
|
| +
|
| + /** Return true if the capability is enabled for this connection with the host. */
|
| + private boolean isCapabilityEnabled(String capability) {
|
| + return (mNegotiatedCapabilities != null && mNegotiatedCapabilities.contains(capability));
|
| + }
|
| +
|
| + /** Tries to reflectively instantiate a CastExtensionHandler object. */
|
| + private ClientExtension tryConstructingCastExtensionHandler() {
|
| + try {
|
| + Class<?> cls = Class.forName("org.chromium.chromoting.CastExtensionHandler");
|
| + return (ClientExtension) cls.newInstance();
|
| + } catch (ClassNotFoundException e) {
|
| + Log.w("CapabilityManager", "Failed to create CastExtensionHandler.");
|
| + return new DummyClientExtension();
|
| + } catch (InstantiationException e) {
|
| + Log.w("CapabilityManager", "Failed to create CastExtensionHandler.");
|
| + return new DummyClientExtension();
|
| + } catch (IllegalAccessException e) {
|
| + Log.w("CapabilityManager", "Failed to create CastExtensionHandler.");
|
| + return new DummyClientExtension();
|
| + }
|
| + }
|
| +}
|
|
|