diff options
author | Brian Attwell <brianattwell@google.com> | 2015-02-18 18:14:08 -0800 |
---|---|---|
committer | Brian Attwell <brianattwell@google.com> | 2015-02-19 10:39:30 -0800 |
commit | 148374fdbe3d723c7485e149afcfed314b2814e0 (patch) | |
tree | d24ef0366febc8fc3448eb115ad80b72c1165127 /src/com | |
parent | 30165add8f1eef3bcf14dba37fe8e78d6e83bfd7 (diff) | |
download | packages_providers_ContactsProvider-148374fdbe3d723c7485e149afcfed314b2814e0.zip packages_providers_ContactsProvider-148374fdbe3d723c7485e149afcfed314b2814e0.tar.gz packages_providers_ContactsProvider-148374fdbe3d723c7485e149afcfed314b2814e0.tar.bz2 |
Persist pre-authorized URIs
When exposing the Authority API, reviewers requested the
API be implemented properly instead of storing the pre-authorized
values in memory.
Bug: 18777272
Change-Id: I31e719b10803344f579bb89c8269f0a597a83c3c
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/providers/contacts/ContactsDatabaseHelper.java | 45 | ||||
-rw-r--r-- | src/com/android/providers/contacts/ContactsProvider2.java | 48 |
2 files changed, 65 insertions, 28 deletions
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java index ed907f8..e4688ee 100644 --- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java +++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java @@ -1,5 +1,5 @@ /* -T * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,7 +88,6 @@ import com.android.providers.contacts.util.NeededForTesting; import com.google.android.collect.Sets; import com.google.common.annotations.VisibleForTesting; -import java.util.HashMap; import java.util.Locale; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -120,7 +119,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { * 1000-1100 M * </pre> */ - static final int DATABASE_VERSION = 1001; + static final int DATABASE_VERSION = 1002; public interface Tables { public static final String CONTACTS = "contacts"; @@ -150,6 +149,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { public static final String SEARCH_INDEX = "search_index"; public static final String VOICEMAIL_STATUS = "voicemail_status"; public static final String METADATA_SYNC = "metadata_sync"; + public static final String PRE_AUTHORIZED_URIS = "pre_authorized_uris"; // This list of tables contains auto-incremented sequences. public static final String[] SEQUENCE_TABLES = new String[] { @@ -683,6 +683,12 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { public static final String TOKENS = "tokens"; } + public interface PreAuthorizedUris { + public static final String _ID = BaseColumns._ID; + public static final String URI = "uri"; + public static final String EXPIRATION = "expiration"; + } + /** * Private table for calculating per-contact-method ranking. */ @@ -1585,6 +1591,11 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { MetadataSyncColumns.RAW_CONTACT_BACKUP_ID + ", " + MetadataSyncColumns.ACCOUNT_ID +");"); + db.execSQL("CREATE TABLE " + Tables.PRE_AUTHORIZED_URIS + " ("+ + PreAuthorizedUris._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + PreAuthorizedUris.URI + " STRING NOT NULL, " + + PreAuthorizedUris.EXPIRATION + " INTEGER NOT NULL DEFAULT 0);"); + // When adding new tables, be sure to also add size-estimates in updateSqliteStats createContactsViews(db); createGroupsView(db); @@ -2856,6 +2867,12 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { oldVersion = 1001; } + if (oldVersion < 1002) { + rebuildSqliteStats = true; + upgradeToVersion1002(db); + oldVersion = 1002; + } + if (upgradeViewsAndTriggers) { createContactsViews(db); createGroupsView(db); @@ -2961,12 +2978,12 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { // For each Contact, find the RawContact that contributed the display name db.execSQL( "UPDATE " + Tables.CONTACTS + - " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" + + " SET " + Contacts.NAME_RAW_CONTACT_ID + "=(" + " SELECT " + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts.CONTACT_ID + "=" + ContactsColumns.CONCRETE_ID + " AND " + RawContactsColumns.CONCRETE_DISPLAY_NAME + "=" + - Tables.CONTACTS + "." + Contacts.DISPLAY_NAME + + Tables.CONTACTS + "." + Contacts.DISPLAY_NAME + " ORDER BY " + RawContacts._ID + " LIMIT 1)" ); @@ -3077,11 +3094,11 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { SQLiteStatement structuredNameUpdate = db.compileStatement( "UPDATE " + Tables.DATA + - " SET " + + " SET " + StructuredName.FULL_NAME_STYLE + "=?," + StructuredName.DISPLAY_NAME + "=?," + StructuredName.PHONETIC_NAME_STYLE + "=?" + - " WHERE " + Data._ID + "=?"); + " WHERE " + Data._ID + "=?"); NameSplitter.Name name = new NameSplitter.Name(); Cursor cursor = db.query(StructName205Query.TABLE, @@ -3545,7 +3562,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { private void insertNicknameLookup(SQLiteDatabase db, SQLiteStatement nameLookupInsert) { final long mimeTypeId = lookupMimeTypeId(db, Nickname.CONTENT_ITEM_TYPE); Cursor cursor = db.query(NicknameQuery.TABLE, NicknameQuery.COLUMNS, - NicknameQuery.SELECTION, new String[] {String.valueOf(mimeTypeId)}, + NicknameQuery.SELECTION, new String[]{String.valueOf(mimeTypeId)}, null, null, null); try { while (cursor.moveToNext()) { @@ -4309,6 +4326,15 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { "raw_contact_backup_id, account_id);"); } + @VisibleForTesting + public void upgradeToVersion1002(SQLiteDatabase db) { + db.execSQL("DROP TABLE IF EXISTS pre_authorized_uris;"); + db.execSQL("CREATE TABLE pre_authorized_uris ("+ + "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "uri STRING NOT NULL, " + + "expiration INTEGER NOT NULL DEFAULT 0);"); + } + public String extractHandleFromEmailAddress(String email) { Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); if (tokens.length == 0) { @@ -4479,6 +4505,9 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { updateIndexStats(db, Tables.ACCOUNTS, null, "3"); + updateIndexStats(db, Tables.PRE_AUTHORIZED_URIS, + null, "1"); + updateIndexStats(db, Tables.VISIBLE_CONTACTS, null, "2000"); diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 06d198e..e853833 100644 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -129,6 +129,7 @@ import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns; +import com.android.providers.contacts.ContactsDatabaseHelper.PreAuthorizedUris; import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; import com.android.providers.contacts.ContactsDatabaseHelper.Projections; import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; @@ -1345,9 +1346,6 @@ public class ContactsProvider2 extends AbstractContactsProvider private final ThreadLocal<TransactionContext> mTransactionContext = new ThreadLocal<TransactionContext>(); - // Map of single-use pre-authorized URIs to expiration times. - private final Map<Uri, Long> mPreAuthorizedUris = Maps.newHashMap(); - // Random number generator. private final SecureRandom mRandom = new SecureRandom(); @@ -2214,8 +2212,13 @@ public class ContactsProvider2 extends AbstractContactsProvider Uri authUri = uri.buildUpon() .appendQueryParameter(PREAUTHORIZED_URI_TOKEN, token) .build(); - long expiration = SystemClock.elapsedRealtime() + mPreAuthorizedUriDuration; - mPreAuthorizedUris.put(authUri, expiration); + long expiration = Clock.getInstance().currentTimeMillis() + mPreAuthorizedUriDuration; + + final SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); + final ContentValues values = new ContentValues(); + values.put(PreAuthorizedUris.EXPIRATION, expiration); + values.put(PreAuthorizedUris.URI, authUri.toString()); + db.insert(Tables.PRE_AUTHORIZED_URIS, null, values); return authUri; } @@ -2229,22 +2232,27 @@ public class ContactsProvider2 extends AbstractContactsProvider public boolean isValidPreAuthorizedUri(Uri uri) { // Only proceed if the URI has a permission token parameter. if (uri.getQueryParameter(PREAUTHORIZED_URI_TOKEN) != null) { - // First expire any pre-authorization URIs that are no longer valid. - long now = SystemClock.elapsedRealtime(); - Set<Uri> expiredUris = Sets.newHashSet(); - for (Uri preAuthUri : mPreAuthorizedUris.keySet()) { - if (mPreAuthorizedUris.get(preAuthUri) < now) { - expiredUris.add(preAuthUri); - } - } - for (Uri expiredUri : expiredUris) { - mPreAuthorizedUris.remove(expiredUri); - } + final long now = Clock.getInstance().currentTimeMillis(); + final SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); + db.beginTransaction(); + try { + // First delete any pre-authorization URIs that are no longer valid. Unfortunately, + // this operation will grab a write lock for readonly queries. Since this only + // affects readonly queries that use PREAUTHORIZED_URI_TOKEN, it isn't worth moving + // this deletion into a BACKGROUND_TASK. + db.delete(Tables.PRE_AUTHORIZED_URIS, PreAuthorizedUris.EXPIRATION + " < ?1", + new String[]{String.valueOf(now)}); + + // Now check to see if the pre-authorized URI map contains the URI. + final Cursor c = db.query(Tables.PRE_AUTHORIZED_URIS, null, + PreAuthorizedUris.URI + "=?1", + new String[]{uri.toString()}, null, null, null); + final boolean isValid = c.getCount() != 0; - // Now check to see if the pre-authorized URI map contains the URI. - if (mPreAuthorizedUris.containsKey(uri)) { - // Unexpired token - skip the permission check. - return true; + db.setTransactionSuccessful(); + return isValid; + } finally { + db.endTransaction(); } } return false; |