From 88c3cb0c19cf09accb77f60be88b398bbe4ce5ac Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Tue, 10 Feb 2015 15:31:13 +0100 Subject: [PATCH] Auth mostly done, checkin should be next --- AndroidManifest.xml | 33 ++++--- GmsApi | 2 +- build.gradle | 2 +- res/layout/ask_permission.xml | 17 +++- res/values/permissions.xml | 85 +++++++++++++++++++ res/values/strings.xml | 3 +- .../gms/people/service/PeopleService.java | 53 ++++++++++++ .../GoogleLocationManagerService.java | 6 +- .../gms/auth/AskPermissionActivity.java | 77 ++++++++++++++--- src/org/microg/gms/auth/AuthManager.java | 15 +++- .../gms/auth/AuthManagerServiceImpl.java | 16 ++-- .../gms/gservices/GServicesProvider.java | 5 +- .../gms/people/service/PeopleServiceImpl.java | 27 ++++++ 13 files changed, 303 insertions(+), 38 deletions(-) create mode 100644 src/com/google/android/gms/people/service/PeopleService.java create mode 100644 src/org/microg/gms/people/service/PeopleServiceImpl.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 397b84ee..32c2a785 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -25,6 +25,7 @@ android:targetSdkVersion="21" /> + + android:authorities="com.google.android.gsf.gservices"/> + + + + + + + + + + + @@ -132,15 +152,8 @@ - - + android:excludeFromRecents="true" /> + + diff --git a/res/values/permissions.xml b/res/values/permissions.xml index ff75ab88..f2afd012 100644 --- a/res/values/permissions.xml +++ b/res/values/permissions.xml @@ -89,4 +89,89 @@ Allows app to access YouTube through any associated Google account. YouTube usernames Allows app to access YouTube username(s) used with any associated Google account. + + View the activity history of your Google Apps + Manage your Ad Exchange buyer account configuration + View your Ad Exchange data + View and manage your Ad Exchange data + View and manage your AdSense host data and associated accounts + View your AdSense data + View and manage your AdSense data + View your Google Analytics data + View and manage your Google Analytics data + Access to the Google Play Android Developer + App engine admin scope. + Read and write access to Groups Migration API. + View and manage the settings of a Google Apps Group + Read/write access to License Manager API. + For reseller administrators and users read/write access when testing in the API\'s sandbox, or read/write access when calling an API operation directly. + In addition to the overall read/write OAuth scope, use the read only OAuth scope when retrieving the customer\'s data. + Access to the Admin Audit API ReadOnly + Scope for using the App State service. + View your data in Google BigQuery + View and manage your data in Google BigQuery + Manage your Blogger account + View your Blogger account + Manage your books + Manage your calendars + View your calendars + View and manage your google cloud print data + View your Google Compute Engine resources + View and manage your Google Compute Engine resources + View your Google Coordinate jobs + View and manage your Google Maps Coordinate jobs + Manage your data and permissions in Google Cloud Storage + View your data in Google Cloud Storage + Manage your data in Google Cloud Storage + View and manage DoubleClick for Advertisers reports + Allows access to the Application Data folder + View your Google Drive apps + View and manage Google Drive files that you have opened or created with this app + Special scope used to let users approve installation of an app + View metadata for files and documents in your Google Drive + View the files and documents in your Google Drive + Modify your Google Apps Script scripts\' behavior + View and manage the files and documents in your Google Drive + view your Freebase account + Sign in to Freebase with your account + Manage your Fusion Tables + View your Fusion Tables + Scope for accessing data from Google Play Games. + Manage your GAN data + View your GAN data + CloudMessaging for chrome + Glass timeline scope + Create, read, update, and delete drafts. Send messages and drafts. + All read/write operations except immediate, permanent deletion of threads and messages, bypassing Trash. + Read all resources and their metadata—no write operations. + Manage your best-available location and location history + Manage your city-level location and location history + Manage your best-available location + Manage your city-level location + provides read and write access to the user\'s Maps Engine data from your application. + provides read-only access to the user\'s Maps Engine data from your + Manage your Orkut activity + View your Orkut data + Know your name, basic info, and list of people you\'re connected to on Google+ + Know who you are on Google + Manage your data in the Google Prediction API + View your product data + Manage the list of sites and domains you control + Manage your new site verifications with Google + Read/write access to Shopping Content API. + Consume Tasks from your Taskqueues + Manage your Tasks + Manage your tasks + View your tasks + Google Maps Tracks API, This scope allows read and write access to your project\'s data. + Manage your goo.gl short URLs + View your email address + View basic information about your account + Manage your YouTube account + View and manage your assets and associated content on YouTube + View your YouTube account + Manage your YouTube videos + View YouTube Analytics monetary reports for your YouTube content + View YouTube Analytics reports for your YouTube content + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 89e17b67..3cbc3fc0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -20,7 +20,8 @@ com.google Google By continuing, you allow this app and Google to use your information in accordance with their respective terms of service and privacy policies. - %s would like to: + %s would like to: + %s would like to use: µg Google Account Manager Allow Deny diff --git a/src/com/google/android/gms/people/service/PeopleService.java b/src/com/google/android/gms/people/service/PeopleService.java new file mode 100644 index 00000000..cd3b9929 --- /dev/null +++ b/src/com/google/android/gms/people/service/PeopleService.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2015 µg Project Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.gms.people.service; + +import android.app.Service; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.google.android.gms.common.internal.IGmsCallbacks; + +import org.microg.gms.AbstractGmsServiceBroker; +import org.microg.gms.people.service.PeopleServiceImpl; + +import static org.microg.gms.common.Constants.ACTION_GMS_PEOPLE_SERVICE_START; + +public class PeopleService extends Service { + private static final String TAG = "GmsPeopleService"; + + private PeopleServiceImpl impl = new PeopleServiceImpl(this); + private AbstractGmsServiceBroker broker = new AbstractGmsServiceBroker() { + @Override + public void getPeopleService(IGmsCallbacks callback, int versionCode, String packageName, Bundle params) throws RemoteException { + Log.d(TAG, "bound by: " + packageName); + callback.onPostInitComplete(0, impl.asBinder(), null); + } + }; + + @Override + public IBinder onBind(Intent intent) { + if (ACTION_GMS_PEOPLE_SERVICE_START.equals(intent.getAction())) { + return broker.asBinder(); + } else { + return null; + } + } +} diff --git a/src/com/google/android/location/internal/GoogleLocationManagerService.java b/src/com/google/android/location/internal/GoogleLocationManagerService.java index 703ba809..0f7e7ab9 100644 --- a/src/com/google/android/location/internal/GoogleLocationManagerService.java +++ b/src/com/google/android/location/internal/GoogleLocationManagerService.java @@ -22,8 +22,10 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; -import org.microg.gms.AbstractGmsServiceBroker; + import com.google.android.gms.common.internal.IGmsCallbacks; + +import org.microg.gms.AbstractGmsServiceBroker; import org.microg.gms.location.GoogleLocationManagerServiceImpl; import static org.microg.gms.common.Constants.ACTION_GMS_LOCATION_MANAGER_SERVICE_START; @@ -35,7 +37,7 @@ public class GoogleLocationManagerService extends Service { private AbstractGmsServiceBroker broker = new AbstractGmsServiceBroker() { @Override public void getGoogleLocationManagerService(IGmsCallbacks callback, int versionCode, - String packageName, Bundle params) throws RemoteException { + String packageName, Bundle params) throws RemoteException { Log.d(TAG, "bound by: " + packageName); callback.onPostInitComplete(0, impl.asBinder(), null); } diff --git a/src/org/microg/gms/auth/AskPermissionActivity.java b/src/org/microg/gms/auth/AskPermissionActivity.java index 2cb13940..bdc9b198 100644 --- a/src/org/microg/gms/auth/AskPermissionActivity.java +++ b/src/org/microg/gms/auth/AskPermissionActivity.java @@ -18,9 +18,8 @@ package org.microg.gms.auth; import android.accounts.Account; import android.accounts.AccountAuthenticatorActivity; -import android.accounts.AccountAuthenticatorResponse; import android.accounts.AccountManager; -import android.app.Activity; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; @@ -41,11 +40,16 @@ import com.google.android.gms.R; import org.microg.gms.common.Utils; import org.microg.gms.userinfo.ProfileManager; +import java.io.IOException; + public class AskPermissionActivity extends AccountAuthenticatorActivity { + public static final String EXTRA_FROM_ACCOUNT_MANAGER = "from_account_manager"; + private static final String TAG = "GmsAuthAskPermission"; private Account account; private String packageName; private String service; + private boolean fromAccountManager = false; @Override protected void onCreate(Bundle savedInstanceState) { @@ -63,6 +67,7 @@ public class AskPermissionActivity extends AccountAuthenticatorActivity { getIntent().getStringExtra(AccountManager.KEY_ACCOUNT_TYPE)); packageName = getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME); service = getIntent().getStringExtra(AccountManager.KEY_AUTHTOKEN); + if (getIntent().hasExtra(EXTRA_FROM_ACCOUNT_MANAGER)) fromAccountManager = true; int callerUid = getIntent().getIntExtra(AccountManager.KEY_CALLER_UID, 0); Utils.checkPackage(this, packageName, callerUid); @@ -100,7 +105,11 @@ public class AskPermissionActivity extends AccountAuthenticatorActivity { } ((ImageView) findViewById(R.id.app_icon)).setImageDrawable(appIcon); - ((TextView) findViewById(R.id.title)).setText(getString(R.string.ask_permission_title, appLabel)); + if (isOAuth()) { + ((TextView) findViewById(R.id.title)).setText(getString(R.string.ask_scope_permission_title, appLabel)); + } else { + ((TextView) findViewById(R.id.title)).setText(getString(R.string.ask_service_permission_title, appLabel)); + } findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -118,7 +127,43 @@ public class AskPermissionActivity extends AccountAuthenticatorActivity { public void onAllow() { AuthManager.storePermission(this, account, packageName, service); - finish(); + findViewById(android.R.id.button1).setEnabled(false); + findViewById(android.R.id.button2).setEnabled(false); + findViewById(R.id.progress_bar).setVisibility(View.VISIBLE); + findViewById(R.id.no_progress_bar).setVisibility(View.GONE); + new Thread(new Runnable() { + @Override + public void run() { + Context context = AskPermissionActivity.this; + String sig = Utils.getFirstPackageSignatureDigest(context, packageName); + AuthRequest request = new AuthRequest().fromContext(context) + .email(account.name) + .token(AccountManager.get(context).getPassword(account)) + .service(service) + .app(packageName, sig) + .hasPermission(); + if (fromAccountManager) { + request.callerIsGms().calledFromAccountManager(); + } else { + request.callerIsApp(); + } + try { + AuthResponse response = request.getResponse(); + AuthManager.storeResponse(context, account, packageName, sig, service, response); + Bundle result = new Bundle(); + result.putString(AccountManager.KEY_AUTHTOKEN, response.auth); + result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); + result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); + result.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, packageName); + result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true); + setAccountAuthenticatorResult(result); + } catch (IOException e) { + Log.w(TAG, e); + } + finish(); + + } + }).start(); } public void onDeny() { @@ -130,11 +175,11 @@ public class AskPermissionActivity extends AccountAuthenticatorActivity { super.finish(); } - private class PermissionAdapter extends BaseAdapter { + private boolean isOAuth() { + return service.startsWith("oauth2:") || service.startsWith("oauth:"); + } - private boolean isOAuth() { - return service.startsWith("oauth2:") || service.startsWith("oauth:"); - } + private class PermissionAdapter extends BaseAdapter { @Override public int getCount() { @@ -162,11 +207,19 @@ public class AskPermissionActivity extends AccountAuthenticatorActivity { public View getView(int position, View convertView, ViewGroup parent) { String item = getItem(position); String label = "unknown"; - if (!isOAuth()) { - int stringId = getResources().getIdentifier("permission_service_" + item + "_label", "string", getPackageName()); - if (stringId != 0) { - label = getString(stringId); + String labelResourceId; + if (isOAuth()) { + if (item.startsWith("https://")) { + labelResourceId = "permission_scope_" + item.substring(8).replace("/", "_").replace("-", "_"); + } else { + labelResourceId = "permission_scope_" + item.replace("/", "_").replace("-", "_"); } + } else { + labelResourceId = "permission_service_" + item + "_label"; + } + int labelResource = getResources().getIdentifier(labelResourceId, "string", getPackageName()); + if (labelResource != 0) { + label = getString(labelResource); } View view = convertView; if (view == null) { diff --git a/src/org/microg/gms/auth/AuthManager.java b/src/org/microg/gms/auth/AuthManager.java index fb49e140..1711265b 100644 --- a/src/org/microg/gms/auth/AuthManager.java +++ b/src/org/microg/gms/auth/AuthManager.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.util.Log; +import org.microg.gms.common.Constants; import org.microg.gms.common.Utils; public class AuthManager { @@ -31,6 +32,7 @@ public class AuthManager { public static void storeResponse(Context context, Account account, String packageName, String sig, String service, AuthResponse response) { + if (service.startsWith("weblogin:")) return; AccountManager accountManager = AccountManager.get(context); if (response.accountId != null) accountManager.setUserData(account, "GoogleUserId", response.accountId); @@ -48,6 +50,7 @@ public class AuthManager { public static String getToken(Context context, Account account, String packageName, String sig, String service) { + if (service.startsWith("weblogin:")) return null; AccountManager accountManager = AccountManager.get(context); return accountManager.peekAuthToken(account, buildTokenKey(packageName, sig, service)); } @@ -58,8 +61,13 @@ public class AuthManager { // https://developers.google.com/accounts/docs/CrossClientAuth Log.d(TAG, "Always permitting scope: " + service); return true; - } - if (!service.startsWith("oauth")) { + } else if (service.startsWith("weblogin:")) { + if (Constants.GMS_PACKAGE_SIGNATURE_SHA1.equals(sig)) { + Log.d(TAG, "Permitting weblogin, is Google singed app!"); + return true; + } + return false; + } else if (!service.startsWith("oauth:") && !service.startsWith("oauth2:")) { if (context.getPackageManager().checkPermission(PERMISSION_TREE_BASE + service, packageName) == PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Permitting, permission is present"); return true; @@ -92,7 +100,8 @@ public class AuthManager { accountManager.setUserData(account, buildPermKey(packageName, sig, service), "1"); } - private static String buildTokenKey(String packageName, String sig, String service) { + public static String buildTokenKey(String packageName, String sig, String service) { + if (service.startsWith("weblogin:")) return null; return packageName + ":" + sig + ":" + service; } diff --git a/src/org/microg/gms/auth/AuthManagerServiceImpl.java b/src/org/microg/gms/auth/AuthManagerServiceImpl.java index 4b3f2407..4ffdb3d6 100644 --- a/src/org/microg/gms/auth/AuthManagerServiceImpl.java +++ b/src/org/microg/gms/auth/AuthManagerServiceImpl.java @@ -18,13 +18,14 @@ package org.microg.gms.auth; import android.accounts.Account; import android.accounts.AccountManager; -import android.accounts.AccountManagerFuture; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; import android.os.RemoteException; +import android.support.v4.app.NotificationCompat; import android.util.Log; import com.google.android.auth.IAuthManagerService; @@ -66,7 +67,7 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub { Utils.checkPackage(context, packageName, callerUid, getCallingUid()); boolean notify = extras.getBoolean(KEY_HANDLE_NOTIFICATION, false); - Log.d(TAG, "getToken: account:" + accountName + " scope:" + scope + " extras:" + extras); + Log.d(TAG, "getToken: account:" + accountName + " scope:" + scope + " extras:" + extras + ", notify: " + notify); Account account = new Account(accountName, GOOGLE_ACCOUNT_TYPE); String sig = Utils.getFirstPackageSignatureDigest(context, packageName); @@ -79,7 +80,12 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub { i.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type); i.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name); i.putExtra(AccountManager.KEY_AUTHTOKEN, scope); - result.putParcelable(KEY_USER_RECOVERY_INTENT, i); + if (notify) { + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(i); + } else { + result.putParcelable(KEY_USER_RECOVERY_INTENT, i); + } return result; } try { diff --git a/src/org/microg/gms/gservices/GServicesProvider.java b/src/org/microg/gms/gservices/GServicesProvider.java index d36fbb33..ad4d0410 100644 --- a/src/org/microg/gms/gservices/GServicesProvider.java +++ b/src/org/microg/gms/gservices/GServicesProvider.java @@ -19,6 +19,7 @@ package org.microg.gms.gservices; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; +import android.database.MatrixCursor; import android.net.Uri; public class GServicesProvider extends ContentProvider{ @@ -29,7 +30,9 @@ public class GServicesProvider extends ContentProvider{ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - return null; + MatrixCursor cursor = new MatrixCursor(new String[]{"name", "value"}); + cursor.addRow(new Object[]{"", null}); + return cursor; } @Override diff --git a/src/org/microg/gms/people/service/PeopleServiceImpl.java b/src/org/microg/gms/people/service/PeopleServiceImpl.java new file mode 100644 index 00000000..660e3188 --- /dev/null +++ b/src/org/microg/gms/people/service/PeopleServiceImpl.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2015 µg Project Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.microg.gms.people.service; + +import android.content.Context; +import android.os.Binder; + +import com.google.android.gms.people.internal.IPeopleService; + +public class PeopleServiceImpl extends IPeopleService.Stub { + public PeopleServiceImpl(Context context) { + } +}