1914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal/* 2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project 3914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * 4914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Licensed under the Apache License, Version 2.0 (the "License"); 5914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * you may not use this file except in compliance with the License. 6914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * You may obtain a copy of the License at 7914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * 8914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * http://www.apache.org/licenses/LICENSE-2.0 9914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * 10914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Unless required by applicable law or agreed to in writing, software 11914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * distributed under the License is distributed on an "AS IS" BASIS, 12914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * See the License for the specific language governing permissions and 14914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * limitations under the License. 15914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 16914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.browser.customtabs; 18914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 19914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.content.ComponentName; 20914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.content.Context; 21914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.content.Intent; 22914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.content.ServiceConnection; 23914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.os.Bundle; 24914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.os.IBinder; 25914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalimport android.os.RemoteException; 26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport android.support.customtabs.ICustomTabsCallback; 27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport android.support.customtabs.IPostMessageService; 28914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 29914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal/** 30914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * A {@link ServiceConnection} for Custom Tabs providers to use while connecting to a 31914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * {@link PostMessageService} on the client side. 32914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 33914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysalpublic abstract class PostMessageServiceConnection implements ServiceConnection { 34914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal private final Object mLock = new Object(); 35914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal private final ICustomTabsCallback mSessionBinder; 36914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal private IPostMessageService mService; 37914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 38914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public PostMessageServiceConnection(CustomTabsSessionToken session) { 39914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal mSessionBinder = ICustomTabsCallback.Stub.asInterface(session.getCallbackBinder()); 40914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 41914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 42914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal /** 43914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Binds the browser side to the client app through the given {@link PostMessageService} name. 44914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * After this, this {@link PostMessageServiceConnection} can be used for sending postMessage 45914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * related communication back to the client. 46914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @param context A context to bind to the service. 47914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @param packageName The name of the package to be bound to. 48914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @return Whether the binding was successful. 49914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 50914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public boolean bindSessionToPostMessageService(Context context, String packageName) { 51914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal Intent intent = new Intent(); 52914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal intent.setClassName(packageName, PostMessageService.class.getName()); 53914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal return context.bindService(intent, this, Context.BIND_AUTO_CREATE); 54914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 55914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 56914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal /** 57914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Unbinds this service connection from the given context. 58914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @param context The context to be unbound from. 59914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 60914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public void unbindFromContext(Context context) { 61914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal context.unbindService(this); 62914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 63914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 64914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal @Override 65914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public final void onServiceConnected(ComponentName name, IBinder service) { 66914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal mService = IPostMessageService.Stub.asInterface(service); 67914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal onPostMessageServiceConnected(); 68914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 69914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 70914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal @Override 71914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public final void onServiceDisconnected(ComponentName name) { 72914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal mService = null; 73914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal onPostMessageServiceDisconnected(); 74914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 75914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 76914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal /** 77914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Notifies the client that the postMessage channel requested with 78914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * {@link CustomTabsService#requestPostMessageChannel( 79914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * CustomTabsSessionToken, android.net.Uri)} is ready. This method should be 80914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * called when the browser binds to the client side {@link PostMessageService} and also readies 81914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * a connection to the web frame. 82914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * 83914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @param extras Reserved for future use. 84914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @return Whether the notification was sent to the remote successfully. 85914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 86914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public final boolean notifyMessageChannelReady(Bundle extras) { 87914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal if (mService == null) return false; 88914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal synchronized (mLock) { 89914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal try { 90914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal mService.onMessageChannelReady(mSessionBinder, extras); 91914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } catch (RemoteException e) { 92914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal return false; 93914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 94914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 95914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal return true; 96914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 97914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 98914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal /** 99914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Posts a message to the client. This should be called when a tab controlled by related 100914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * {@link CustomTabsSession} has sent a postMessage. If postMessage() is called from a single 101914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * thread, then the messages will be posted in the same order. 102914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * 103914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @param message The message sent. 104914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @param extras Reserved for future use. 105914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * @return Whether the postMessage was sent to the remote successfully. 106914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 107914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public final boolean postMessage(String message, Bundle extras) { 108914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal if (mService == null) return false; 109914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal synchronized (mLock) { 110914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal try { 111914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal mService.onPostMessage(mSessionBinder, message, extras); 112914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } catch (RemoteException e) { 113914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal return false; 114914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 115914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 116914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal return true; 117914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal } 118914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 119914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal /** 120914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Called when the {@link PostMessageService} connection is established. 121914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 122914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public void onPostMessageServiceConnected() {} 123914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal 124914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal /** 125914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal * Called when the connection is lost with the {@link PostMessageService}. 126914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal */ 127914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal public void onPostMessageServiceDisconnected() {} 128914073c7cf933229a3f51ddeddb63bb9725a70beYusuf Ozuysal} 129