summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorBrian Attwell <brianattwell@google.com>2015-02-18 18:14:08 -0800
committerBrian Attwell <brianattwell@google.com>2015-02-19 10:39:30 -0800
commit148374fdbe3d723c7485e149afcfed314b2814e0 (patch)
treed24ef0366febc8fc3448eb115ad80b72c1165127 /src/com
parent30165add8f1eef3bcf14dba37fe8e78d6e83bfd7 (diff)
downloadpackages_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.java45
-rw-r--r--src/com/android/providers/contacts/ContactsProvider2.java48
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;