Commit 0ad3fbda authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

[Android] Make creation of vault key retrieval intent async

Analogous to the recent https://crrev.com/c/1968991, this patch adopts
org.chromium.base.Promise as mechanism to avoid blocking the UI thread
while the Intent is constructed as part of
TrustedVaultClient.createKeyRetrievalIntent().

This patch also adopts PendingIntent as opposed to Intent, which fits
better the need to launch a possibly external flow.

Bug: 1012659
Change-Id: Ib8db263f8b5ce3aa255b90603e4def60456d1459
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1972131
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarBoris Sazonov <bsazonov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732338}
parent 95dbab5c
......@@ -271,6 +271,15 @@ public class Promise<T> {
return promise;
}
/**
* Convenience method to return a rejected Promise.
*/
public static <T> Promise<T> rejected() {
Promise<T> promise = new Promise<>();
promise.reject();
return promise;
}
private void checkThread() {
assert mThread == Thread.currentThread() : "Promise must only be used on a single Thread.";
}
......
......@@ -9,6 +9,8 @@ import android.content.Intent;
import android.os.Build;
import android.util.Log;
import androidx.annotation.StringRes;
import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.chrome.R;
......@@ -89,14 +91,21 @@ public class SyncNotificationController implements ProfileSyncService.SyncStateC
CoreAccountInfo primaryAccountInfo =
IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo();
if (primaryAccountInfo != null) {
Intent intent =
TrustedVaultClient.get().createKeyRetrievalIntent(primaryAccountInfo);
if (intent != null) {
showSyncNotification(mProfileSyncService.isEncryptEverythingEnabled()
int flags = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP;
TrustedVaultClient.get()
.createKeyRetrievalIntent(primaryAccountInfo)
.then(
(pendingIntent)
-> {
showSyncNotificationForPendingIntent(
mProfileSyncService.isEncryptEverythingEnabled()
? R.string.sync_error_card_title
: R.string.sync_passwords_error_card_title,
intent);
}
new PendingIntentProvider(pendingIntent, flags));
},
(exception) -> {
Log.w(TAG, "Error creating key retrieval intent: ", exception);
});
}
} else {
mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SYNC);
......@@ -108,9 +117,10 @@ public class SyncNotificationController implements ProfileSyncService.SyncStateC
* Builds and shows a notification for the |message|.
*
* @param message Resource id of the message to display in the notification.
* @param intent Intent to send when the user activates the notification.
* @param contentIntent represents intent to send when the user activates the notification.
*/
private void showSyncNotification(int message, Intent intent) {
private void showSyncNotificationForPendingIntent(
@StringRes int message, PendingIntentProvider contentIntent) {
Context applicationContext = ContextUtils.getApplicationContext();
String title = null;
String text = null;
......@@ -125,9 +135,6 @@ public class SyncNotificationController implements ProfileSyncService.SyncStateC
+ applicationContext.getString(message);
}
PendingIntentProvider contentIntent =
PendingIntentProvider.getActivity(applicationContext, 0, intent, 0);
// There is no need to provide a group summary notification because the NOTIFICATION_ID_SYNC
// notification id ensures there's only one sync notification at a time.
ChromeNotificationBuilder builder =
......@@ -153,6 +160,19 @@ public class SyncNotificationController implements ProfileSyncService.SyncStateC
NotificationUmaTracker.SystemNotificationType.SYNC, notification.getNotification());
}
/**
* Builds and shows a notification for the |message|.
*
* @param message Resource id of the message to display in the notification.
* @param intent Intent to send when the user activates the notification.
*/
private void showSyncNotification(@StringRes int message, Intent intent) {
Context applicationContext = ContextUtils.getApplicationContext();
PendingIntentProvider contentIntent =
PendingIntentProvider.getActivity(applicationContext, 0, intent, 0);
showSyncNotificationForPendingIntent(message, contentIntent);
}
private boolean shouldSyncAuthErrorBeShown() {
switch (mProfileSyncService.getAuthError()) {
case State.NONE:
......
......@@ -4,17 +4,16 @@
package org.chromium.chrome.browser.sync;
import android.content.Context;
import android.content.Intent;
import android.app.Activity;
import android.app.PendingIntent;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.Log;
import org.chromium.base.Promise;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.AppHooks;
import org.chromium.chrome.browser.util.IntentUtils;
import org.chromium.components.signin.base.CoreAccountInfo;
import java.util.Collections;
......@@ -39,14 +38,14 @@ public class TrustedVaultClient {
Promise<List<byte[]>> fetchKeys(CoreAccountInfo accountInfo);
/**
* Gets an Intent that can be used to display a UI that allows the user to reauthenticate
* and retrieve the sync encryption keys.
* Gets a PendingIntent that can be used to display a UI that allows the user to
* reauthenticate and retrieve the sync encryption keys.
*
* @param accountInfo Account representing the user.
* @return the Intent object or null is something went wrong.
* @return a promise for a PendingIntent object. The promise will be rejected if no
* retrieval is actually required.
*/
@Nullable
Intent createKeyRetrievalIntent(CoreAccountInfo accountInfo);
Promise<PendingIntent> createKeyRetrievalIntent(CoreAccountInfo accountInfo);
/**
* Invoked when the result of fetchKeys() represents keys that cannot decrypt Nigori, which
......@@ -69,8 +68,8 @@ public class TrustedVaultClient {
}
@Override
public Intent createKeyRetrievalIntent(CoreAccountInfo accountInfo) {
return null;
public Promise<PendingIntent> createKeyRetrievalIntent(CoreAccountInfo accountInfo) {
return Promise.rejected();
}
@Override
......@@ -79,6 +78,8 @@ public class TrustedVaultClient {
}
};
private static final String TAG = "TrustedVaultClient";
private static TrustedVaultClient sInstance;
private final Backend mBackend;
......@@ -106,28 +107,35 @@ public class TrustedVaultClient {
/**
* Displays a UI that allows the user to reauthenticate and retrieve the sync encryption keys.
*
* @param context Context to use when starting the dialog activity.
* @param activity Activity to use when starting the dialog.
* @param accountInfo Account representing the user.
*/
public void displayKeyRetrievalDialog(Context context, CoreAccountInfo accountInfo) {
Intent intent = createKeyRetrievalIntent(accountInfo);
if (intent == null) return;
IntentUtils.safeStartActivity(context, intent);
// TODO(crbug.com/1012659): Upon intent completion, the new keys should
// fetched.
public void displayKeyRetrievalDialog(Activity activity, CoreAccountInfo accountInfo) {
createKeyRetrievalIntent(accountInfo)
.then(
(pendingIntent)
-> {
try {
// TODO(crbug.com/1012659): Upon intent completion, the new keys
// should be fetched.
pendingIntent.send(activity, 0, null, null, null, null, null);
} catch (PendingIntent.CanceledException exception) {
Log.w(TAG, "Error sending key retrieval intent: ", exception);
}
},
(exception) -> {
Log.e(TAG, "Error opening key retrieval dialog: ", exception);
});
}
/**
* Creates an intent that launches an activity that triggers the key retrieval UI.
*
* @param accountInfo Account representing the user.
* @return the intent for opening the key retrieval activity or null if none is actually
* required
* @return a promise with the intent for opening the key retrieval activity. The promise will be
* rejected if no retrieval is actually required.
*/
@Nullable
public Intent createKeyRetrievalIntent(CoreAccountInfo accountInfo) {
public Promise<PendingIntent> createKeyRetrievalIntent(CoreAccountInfo accountInfo) {
return mBackend.createKeyRetrievalIntent(accountInfo);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment