Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a9b8556df5c699d70d5e76ce68b53d85a0cb7af8 |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java |
| @@ -0,0 +1,138 @@ |
| +// Copyright 2016 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.chrome.browser.gsa; |
| + |
| +import android.content.BroadcastReceiver; |
| +import android.content.Context; |
| +import android.content.Intent; |
| +import android.content.IntentFilter; |
| +import android.net.Uri; |
| +import android.os.Bundle; |
| + |
| +import org.chromium.base.Callback; |
| +import org.chromium.base.ContextUtils; |
| + |
| +/** |
| + * Listens to te account change notifications from GSA. |
| + * |
| + * Depending on GSA's version, the account change notifications are dispatched: |
| + * - Through SSB_SERVICE, or |
| + * - Through a Broadcast. |
| + * |
| + * We proceed the following way: |
| + * 1. Connect to the GSA service. |
| + * 2. If GSA supports the broadcast, disconnect from it, otherwise keep the old method. |
| + */ |
| +public class GSAAccountChangeListener { |
| + // These are GSA constants. |
| + private static final String GSA_PACKAGE_NAME = "com.google.android.googlequicksearchbox"; |
| + private static final String ACCOUNT_UPDATE_BROADCAST_INTENT = |
| + "com.google.android.apps.now.account_update_broadcast"; |
| + private static final String KEY_SSB_BROADCASTS_ACCOUNT_CHANGE_TO_CHROME = |
| + "ssb_service:ssb_broadcasts_account_change_to_chrome"; |
| + private static final String BROADCAST_INTENT_ACCOUNT_NAME_EXTRA = "account_name"; |
| + public static final String ACCOUNT_UPDATE_BROADCAST_PERMISSION = |
| + "com.google.android.apps.now.CURRENT_ACCOUNT_ACCESS"; |
| + |
| + private static GSAAccountChangeListener sInstance; |
| + |
| + // Reference count for the connection. |
| + private int mUsersCount; |
| + private GSAServiceClient mClient; |
| + |
| + /** |
| + * @return the instance of GSAAccountChangeListener. |
| + */ |
| + public static GSAAccountChangeListener getInstance() { |
| + if (sInstance == null) { |
| + Context context = ContextUtils.getApplicationContext(); |
| + sInstance = new GSAAccountChangeListener(context); |
| + } |
| + return sInstance; |
| + } |
| + |
| + private GSAAccountChangeListener(Context context) { |
| + Context applicationContext = context.getApplicationContext(); |
| + BroadcastReceiver accountChangeReceiver = new BroadcastReceiver() { |
| + @Override |
| + public void onReceive(Context context, Intent intent) { |
| + if (!ACCOUNT_UPDATE_BROADCAST_INTENT.equals(intent.getAction())) return; |
| + String accountName = intent.getStringExtra(BROADCAST_INTENT_ACCOUNT_NAME_EXTRA); |
| + GSAState.getInstance(context.getApplicationContext()).setGsaAccount(accountName); |
| + } |
| + }; |
| + applicationContext.registerReceiver(accountChangeReceiver, |
| + new IntentFilter(ACCOUNT_UPDATE_BROADCAST_INTENT), |
| + ACCOUNT_UPDATE_BROADCAST_PERMISSION, null); |
| + |
| + createGsaClientAndConnect(applicationContext); |
| + |
| + // If some future version of GSA no longer broadcasts the account change |
| + // notification, need to fall back to the service. |
| + // |
| + // The states are: USE_SERVICE and USE_BROADCAST. The initial state (when Chrome starts) is |
| + // USE_SERVICE. |
| + // The state transitions are: |
| + // - USE_SERVICE -> USE_BROADCAST: When GSA sends a message (through the service) declaring |
| + // it supports the broadcasts. |
| + // - USE_BROADCAST -> USE_SERVICE: When GSA is updated. |
| + BroadcastReceiver gsaUpdatedReceiver = new BroadcastReceiver() { |
| + @Override |
| + public void onReceive(Context context, Intent intent) { |
| + Uri data = intent.getData(); |
| + if (data == null) return; |
| + |
| + String packageName = data.getEncodedSchemeSpecificPart(); |
| + if (GSA_PACKAGE_NAME.equals(packageName)) { |
| + Context applicationContext = context.getApplicationContext(); |
| + // We no longer know the account, but GSA will tell us momentarily (through |
| + // the service). |
| + GSAState.getInstance(applicationContext).setGsaAccount(null); |
| + // GSA has been updated, it might no longer support the broadcast. Reconnect to |
| + // check. |
| + mClient = null; |
| + createGsaClientAndConnect(applicationContext); |
| + } |
| + } |
| + }; |
| + IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); |
| + filter.addDataScheme("package"); |
| + context.registerReceiver(gsaUpdatedReceiver, filter); |
| + } |
| + |
| + private void createGsaClientAndConnect(Context context) { |
| + Callback<Bundle> onMessageReceived = new Callback<Bundle>() { |
| + @Override |
| + public void onResult(Bundle result) { |
| + if (result.getBoolean(KEY_SSB_BROADCASTS_ACCOUNT_CHANGE_TO_CHROME)) { |
| + notifyGsaBroadcastsAccountChanges(); |
| + } |
| + } |
| + }; |
| + mClient = new GSAServiceClient(context, onMessageReceived); |
| + mClient.connect(); |
| + } |
| + |
| + /** |
| + * Connects to the GSA service if GSA doesn't support notifications. |
| + */ |
| + public void connect() { |
| + if (mClient != null) mClient.connect(); |
| + mUsersCount++; |
| + } |
| + |
| + /** |
| + * Disconnects from the GSA service if GSA doesn't support notifications. |
|
Maria
2016/10/26 19:43:47
should the comment be disconnects if GSA DOES supp
|
| + */ |
| + public void disconnect() { |
| + mUsersCount--; |
| + if (mClient != null && mUsersCount == 0) mClient.disconnect(); |
| + } |
| + |
| + private void notifyGsaBroadcastsAccountChanges() { |
| + mClient.disconnect(); |
| + mClient = null; |
| + } |
| +} |