Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1783)

Unified Diff: services/authentication/src/org/chromium/mojo/authentication/AuthenticationServiceImpl.java

Issue 1116653002: Introduce authentication service. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Follow review Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: services/authentication/src/org/chromium/mojo/authentication/AuthenticationServiceImpl.java
diff --git a/services/authentication/src/org/chromium/mojo/authentication/AuthenticationServiceImpl.java b/services/authentication/src/org/chromium/mojo/authentication/AuthenticationServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..90be06b7989a4f413609dbc1058f76f5d6d648ce
--- /dev/null
+++ b/services/authentication/src/org/chromium/mojo/authentication/AuthenticationServiceImpl.java
@@ -0,0 +1,195 @@
+// Copyright 2015 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.mojo.authentication;
+
+import android.accounts.AccountManager;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Parcel;
+
+import com.google.android.gms.auth.GoogleAuthException;
+import com.google.android.gms.auth.GoogleAuthUtil;
+import com.google.android.gms.auth.UserRecoverableAuthException;
+import com.google.android.gms.common.AccountPicker;
+
+import org.chromium.mojo.application.ShellHelper;
+import org.chromium.mojo.bindings.SideEffectFreeCloseable;
+import org.chromium.mojo.intent.IntentReceiver;
+import org.chromium.mojo.intent.IntentReceiverManager;
+import org.chromium.mojo.intent.IntentReceiverManager.RegisterActivityResultReceiverResponse;
+import org.chromium.mojo.system.Core;
+import org.chromium.mojo.system.MojoException;
+import org.chromium.mojom.mojo.Shell;
+
+import java.io.IOException;
+
+/**
+ * Implementation of AuthenticationService from services/authentication/authentication.mojom
+ */
+public class AuthenticationServiceImpl
+ extends SideEffectFreeCloseable implements AuthenticationService {
+ /**
+ * An callback that takes a serialized intent, add the intent the shell needs to send and start
+ * the container intent.
+ */
+ private final class RegisterActivityResultReceiverCallback
+ implements RegisterActivityResultReceiverResponse {
+ /**
+ * The intent that the requesting application needs to be run by shell on its
+behalf.
+ */
+ private final Intent mIntent;
+
+ private RegisterActivityResultReceiverCallback(Intent intent) {
+ mIntent = intent;
+ }
+
+ /**
+ * @see RegisterActivityResultReceiverResponse#call(byte[])
+ */
+ @Override
+ public void call(byte[] serializedIntent) {
+ Intent trampolineIntent = bytesToIntent(serializedIntent);
+ trampolineIntent.putExtra("intent", mIntent);
+ mContext.startService(trampolineIntent);
+ }
+ }
+
+ private final Activity mContext;
+ private final String mConsumerURL;
+ private final IntentReceiverManager mIntentReceiverManager;
+
+ public AuthenticationServiceImpl(Context context, Core core, String consumerURL, Shell shell) {
+ mContext = (Activity) context;
+ mConsumerURL = consumerURL;
+ mIntentReceiverManager = ShellHelper.connectToService(
+ core, shell, "mojo:android_handler", IntentReceiverManager.MANAGER);
+ }
+
+ /**
+ * @see AuthenticationService#onConnectionError(MojoException)
+ */
+ @Override
+ public void onConnectionError(MojoException e) {}
+
+ /**
+ * @see AuthenticationService#getOAuth2Token(String, String[],
+ * AuthenticationService.GetOAuth2TokenResponse)
+ */
+ @Override
+ public void getOAuth2Token(
+ final String username, final String[] scopes, final GetOAuth2TokenResponse callback) {
+ if (scopes.length == 0) {
+ callback.call(null, "scopes cannot be empty");
+ return;
+ }
+ StringBuilder scope = new StringBuilder("oauth2:");
+ for (int i = 0; i < scopes.length; ++i) {
+ if (i > 0) {
+ scope.append(" ");
+ }
+ scope.append(scopes[i]);
+ }
+ try {
+ callback.call(GoogleAuthUtil.getToken(mContext, username, scope.toString()), null);
+ } catch (final UserRecoverableAuthException e) {
+ // If an error occurs that the user can recover from, this exception will contain the
+ // intent to run to allow the user to act. This will use the intent manager to start it.
+ mIntentReceiverManager.registerActivityResultReceiver(new IntentReceiver() {
+ GetOAuth2TokenResponse mPendingCallback = callback;
+
+ @Override
+ public void close() {
+ call(null, "User denied the request.");
+ }
+
+ @Override
+ public void onConnectionError(MojoException e) {
+ call(null, e.getMessage());
+ }
+
+ @Override
+ public void onIntent(byte[] bytes) {
+ if (mPendingCallback == null) {
+ return;
+ }
+ getOAuth2Token(username, scopes, mPendingCallback);
+ mPendingCallback = null;
+ }
+
+ private void call(String token, String error) {
+ if (mPendingCallback == null) {
+ return;
+ }
+ mPendingCallback.call(token, error);
+ mPendingCallback = null;
+ }
+ }, new RegisterActivityResultReceiverCallback(e.getIntent()));
+ return;
+ } catch (IOException | GoogleAuthException e) {
+ // Unrecoverable error.
+ callback.call(null, e.getMessage());
+ }
+ }
+
+ /**
+ * @see AuthenticationService#selectAccount(AuthenticationService.SelectAccountResponse)
+ */
+ @Override
+ public void selectAccount(final SelectAccountResponse callback) {
+ String[] accountTypes = new String[] {"com.google"};
+ String message = "Select an account to use with application: " + mConsumerURL;
+ Intent accountPickerIntent = AccountPicker.newChooseAccountIntent(
+ null, null, accountTypes, false, message, null, null, null);
+
+ mIntentReceiverManager.registerActivityResultReceiver(new IntentReceiver() {
+ SelectAccountResponse mPendingCallback = callback;
+
+ @Override
+ public void close() {
+ call(null, "User denied the request.");
+ }
+
+ @Override
+ public void onConnectionError(MojoException e) {
+ call(null, e.getMessage());
+ }
+
+ @Override
+ public void onIntent(byte[] bytes) {
+ Intent intent = bytesToIntent(bytes);
+ call(intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME), null);
+ }
+
+ private void call(String username, String error) {
+ if (mPendingCallback == null) {
+ return;
+ }
+ mPendingCallback.call(username, error);
+ mPendingCallback = null;
+ }
+ }, new RegisterActivityResultReceiverCallback(accountPickerIntent));
+ }
+
+ /**
+ * @see AuthenticationService#clearOAuth2Token(String)
+ */
+ @Override
+ public void clearOAuth2Token(String token) {
+ try {
+ GoogleAuthUtil.clearToken(mContext, token);
+ } catch (GoogleAuthException | IOException e) {
+ // Nothing to do.
+ }
+ }
+
+ private static Intent bytesToIntent(byte[] bytes) {
+ Parcel p = Parcel.obtain();
+ p.unmarshall(bytes, 0, bytes.length);
+ p.setDataPosition(0);
+ return Intent.CREATOR.createFromParcel(p);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698