Home | History | Annotate | Download | only in customtabs
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.browser.customtabs;
     18 
     19 import android.content.Intent;
     20 import android.net.Uri;
     21 import android.os.Bundle;
     22 import android.os.IBinder;
     23 import android.os.RemoteException;
     24 import android.support.customtabs.ICustomTabsCallback;
     25 import android.util.Log;
     26 
     27 import androidx.annotation.NonNull;
     28 import androidx.core.app.BundleCompat;
     29 
     30 /**
     31  * Wrapper class that can be used as a unique identifier for a session. Also contains an accessor
     32  * for the {@link CustomTabsCallback} for the session if there was any.
     33  */
     34 public class CustomTabsSessionToken {
     35     private static final String TAG = "CustomTabsSessionToken";
     36     private final ICustomTabsCallback mCallbackBinder;
     37     private final CustomTabsCallback mCallback;
     38 
     39     /* package */ static class MockCallback extends ICustomTabsCallback.Stub {
     40         @Override
     41         public void onNavigationEvent(int navigationEvent, Bundle extras) {}
     42 
     43         @Override
     44         public void extraCallback(String callbackName, Bundle args) {}
     45 
     46         @Override
     47         public void onMessageChannelReady(Bundle extras) {}
     48 
     49         @Override
     50         public void onPostMessage(String message, Bundle extras) {}
     51 
     52         @Override
     53         public void onRelationshipValidationResult(@CustomTabsService.Relation int relation, Uri requestedOrigin,
     54                 boolean result, Bundle extras) {}
     55 
     56         @Override
     57         public IBinder asBinder() {
     58             return this;
     59         }
     60     }
     61 
     62     /**
     63      * Obtain a {@link CustomTabsSessionToken} from an intent. See {@link CustomTabsIntent.Builder}
     64      * for ways to generate an intent for custom tabs.
     65      * @param intent The intent to generate the token from. This has to include an extra for
     66      *               {@link CustomTabsIntent#EXTRA_SESSION}.
     67      * @return The token that was generated.
     68      */
     69     public static CustomTabsSessionToken getSessionTokenFromIntent(Intent intent) {
     70         Bundle b = intent.getExtras();
     71         IBinder binder = BundleCompat.getBinder(b, CustomTabsIntent.EXTRA_SESSION);
     72         if (binder == null) return null;
     73         return new CustomTabsSessionToken(ICustomTabsCallback.Stub.asInterface(binder));
     74     }
     75 
     76     /**
     77      * Provides browsers a way to generate a mock {@link CustomTabsSessionToken} for testing
     78      * purposes.
     79      *
     80      * @return A mock token with no functionality.
     81      */
     82     @NonNull
     83     public static CustomTabsSessionToken createMockSessionTokenForTesting() {
     84         return new CustomTabsSessionToken(new MockCallback());
     85     }
     86 
     87     CustomTabsSessionToken(ICustomTabsCallback callbackBinder) {
     88         mCallbackBinder = callbackBinder;
     89         mCallback = new CustomTabsCallback() {
     90 
     91             @Override
     92             public void onNavigationEvent(int navigationEvent, Bundle extras) {
     93                 try {
     94                     mCallbackBinder.onNavigationEvent(navigationEvent, extras);
     95                 } catch (RemoteException e) {
     96                     Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
     97                 }
     98             }
     99 
    100             @Override
    101             public void extraCallback(String callbackName, Bundle args) {
    102                 try {
    103                     mCallbackBinder.extraCallback(callbackName, args);
    104                 } catch (RemoteException e) {
    105                     Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
    106                 }
    107             }
    108 
    109             @Override
    110             public void onMessageChannelReady(Bundle extras) {
    111                 try {
    112                     mCallbackBinder.onMessageChannelReady(extras);
    113                 } catch (RemoteException e) {
    114                     Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
    115                 }
    116             }
    117 
    118             @Override
    119             public void onPostMessage(String message, Bundle extras) {
    120                 try {
    121                     mCallbackBinder.onPostMessage(message, extras);
    122                 } catch (RemoteException e) {
    123                     Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
    124                 }
    125             }
    126 
    127             @Override
    128             public void onRelationshipValidationResult(@CustomTabsService.Relation int relation, Uri origin,
    129                                                        boolean result, Bundle extras) {
    130                 try {
    131                     mCallbackBinder.onRelationshipValidationResult(
    132                             relation, origin, result, extras);
    133                 } catch (RemoteException e) {
    134                     Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
    135                 }
    136             }
    137 
    138         };
    139     }
    140 
    141     IBinder getCallbackBinder() {
    142         return mCallbackBinder.asBinder();
    143     }
    144 
    145     @Override
    146     public int hashCode() {
    147         return getCallbackBinder().hashCode();
    148     }
    149 
    150     @Override
    151     public boolean equals(Object o) {
    152         if (!(o instanceof CustomTabsSessionToken)) return false;
    153         CustomTabsSessionToken token = (CustomTabsSessionToken) o;
    154         return token.getCallbackBinder().equals(mCallbackBinder.asBinder());
    155     }
    156 
    157     /**
    158      * @return {@link CustomTabsCallback} corresponding to this session if there was any non-null
    159      *         callbacks passed by the client.
    160      */
    161     public CustomTabsCallback getCallback() {
    162         return mCallback;
    163     }
    164 
    165     /**
    166      * @return Whether this token is associated with the given session.
    167      */
    168     public boolean isAssociatedWith(CustomTabsSession session) {
    169         return session.getBinder().equals(mCallbackBinder);
    170     }
    171 }
    172