Commit 24b43eb2 authored by Wes Johnston's avatar Wes Johnston
Browse files

Bug 704682 - Add passwords content provider. r=blassey,gpascutto

parent 39269e3e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -163,6 +163,12 @@
                  android:authorities="@ANDROID_PACKAGE_NAME@.db.browser"
                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>

        <provider android:name="@ANDROID_PACKAGE_NAME@.db.PasswordsProvider"
                  android:authorities="@ANDROID_PACKAGE_NAME@.db.passwords"
                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"
									android:protectionLevel="signature"/>


#include ../sync/manifests/SyncAndroidManifest_services.xml.in
    </application>

+2 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ FENNEC_JAVA_FILES = \
  db/AndroidBrowserDB.java \
  db/BrowserDB.java \
  db/LocalBrowserDB.java \
  db/DBUtils.java \
  DoorHanger.java \
  DoorHangerPopup.java \
  Favicons.java \
@@ -149,6 +150,7 @@ FENNEC_PP_JAVA_FILES = \
  Restarter.java \
  db/BrowserContract.java \
  db/BrowserProvider.java \
  db/PasswordsProvider.java \
  SmsManager.java \
  $(NULL)

+56 −0
Original line number Diff line number Diff line
@@ -43,8 +43,16 @@ import android.net.Uri;
public class BrowserContract {
    public static final String AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.browser";

    public static final String PASSWORDS_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.passwords";

    public static final String DELETED_PASSWORDS_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.deleted-passwords";

    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
    
    public static final Uri PASSWORDS_AUTHORITY_URI = Uri.parse("content://" + PASSWORDS_AUTHORITY);

    public static final Uri DELETED_PASSWORDS_AUTHORITY_URI = Uri.parse("content://" + DELETED_PASSWORDS_AUTHORITY);

    public static final String DEFAULT_PROFILE = "default";

    public static final String PARAM_PROFILE = "profile";
@@ -141,4 +149,52 @@ public class BrowserContract {

        public static final String VERSION = "version";
    }

    public static final class Passwords implements CommonColumns, SyncColumns {
        private Passwords() {}

        public static final Uri CONTENT_URI = Uri.withAppendedPath(PASSWORDS_AUTHORITY_URI, "passwords");

        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/passwords";

        public static final String ID = "id";

        public static final String HOSTNAME = "hostname";

        public static final String HTTP_REALM = "httpRealm";

        public static final String FORM_SUBMIT_URL = "formSubmitURL";

        public static final String USERNAME_FIELD = "usernameField";

        public static final String PASSWORD_FIELD = "passwordField";

        public static final String ENCRYPTED_USERNAME = "encryptedUsername";

        public static final String ENCRYPTED_PASSWORD = "encryptedPassword";

        public static final String ENC_TYPE = "encType";

        public static final String TIME_CREATED = "timeCreated";

        public static final String TIME_LAST_USED = "timeLastUsed";

        public static final String TIME_PASSWORD_CHANGED = "timePasswordChanged";

        public static final String TIMES_USED = "timesUsed";
    }

    public static final class DeletedPasswords implements CommonColumns, SyncColumns {
        private DeletedPasswords() {}

        public static final Uri CONTENT_URI = Uri.withAppendedPath(DELETED_PASSWORDS_AUTHORITY_URI, "deleted-passwords");

        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/deleted-passwords";

        public static final String ID = "id";

        public static final String GUID = "guid";

        public static final String TIME_DELETED = "timeDeleted";
    }
}
+27 −71
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ import org.mozilla.gecko.db.BrowserContract.Schema;
import org.mozilla.gecko.db.BrowserContract.SyncColumns;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.DBUtils;
import org.mozilla.gecko.sync.Utils;

import android.content.ContentProvider;
import android.content.ContentUris;
@@ -208,52 +210,6 @@ public class BrowserProvider extends ContentProvider {
        return table + "." + column;
    }

    public static String generateGuid() {
        byte[] encodedBytes = GeckoAppShell.encodeBase64(generateRandomBytes(9), GeckoAppShell.BASE64_URL_SAFE);
        return new String(encodedBytes);
    }

    private static byte[] generateRandomBytes(int length) {
        byte[] bytes = new byte[length];

        Random random = new Random(System.nanoTime());
        random.nextBytes(bytes);

        return bytes;
    }

    // This is available in Android >= 11. Implemented locally to be
    // compatible with older versions.
    public static String concatenateWhere(String a, String b) {
        if (TextUtils.isEmpty(a)) {
            return b;
        }

        if (TextUtils.isEmpty(b)) {
            return a;
        }

        return "(" + a + ") AND (" + b + ")";
    }

    // This is available in Android >= 11. Implemented locally to be
    // compatible with older versions.
    public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) {
        if (originalValues == null || originalValues.length == 0) {
            return newValues;
        }

        if (newValues == null || newValues.length == 0) {
            return originalValues;
        }

        String[] result = new String[originalValues.length + newValues.length];
        System.arraycopy(originalValues, 0, result, 0, originalValues.length);
        System.arraycopy(newValues, 0, result, originalValues.length, newValues.length);

        return result;
    }

    private static boolean hasImagesInProjection(String[] projection) {
        if (projection == null) return true;
        for (int i = 0; i < projection.length; ++i) {
@@ -619,8 +575,8 @@ public class BrowserProvider extends ContentProvider {
            case BOOKMARKS_ID:
                Log.d(LOGTAG, "Delete on BOOKMARKS_ID: " + uri);

                selection = concatenateWhere(selection, TABLE_BOOKMARKS + "._id = ?");
                selectionArgs = appendSelectionArgs(selectionArgs,
                selection = DBUtils.concatenateWhere(selection, TABLE_BOOKMARKS + "._id = ?");
                selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                        new String[] { Long.toString(ContentUris.parseId(uri)) });
                // fall through
            case BOOKMARKS: {
@@ -633,8 +589,8 @@ public class BrowserProvider extends ContentProvider {
            case HISTORY_ID:
                Log.d(LOGTAG, "Delete on HISTORY_ID: " + uri);

                selection = concatenateWhere(selection, TABLE_HISTORY + "._id = ?");
                selectionArgs = appendSelectionArgs(selectionArgs,
                selection = DBUtils.concatenateWhere(selection, TABLE_HISTORY + "._id = ?");
                selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                        new String[] { Long.toString(ContentUris.parseId(uri)) });
                // fall through
            case HISTORY: {
@@ -647,8 +603,8 @@ public class BrowserProvider extends ContentProvider {
            case IMAGES_ID:
                Log.d(LOGTAG, "Delete on IMAGES_ID: " + uri);

                selection = concatenateWhere(selection, TABLE_IMAGES + "._id = ?");
                selectionArgs = appendSelectionArgs(selectionArgs,
                selection = DBUtils.concatenateWhere(selection, TABLE_IMAGES + "._id = ?");
                selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                        new String[] { Long.toString(ContentUris.parseId(uri)) });
                // fall through
            case IMAGES: {
@@ -707,7 +663,7 @@ public class BrowserProvider extends ContentProvider {

                // Generate GUID for new bookmark. Don't override specified GUIDs.
                if (!values.containsKey(Bookmarks.GUID)) {
                  values.put(Bookmarks.GUID, generateGuid());
                  values.put(Bookmarks.GUID, Utils.generateGuid());
                }

                if (!values.containsKey(Bookmarks.POSITION)) {
@@ -740,7 +696,7 @@ public class BrowserProvider extends ContentProvider {

                // Generate GUID for new history entry. Don't override specified GUIDs.
                if (!values.containsKey(History.GUID)) {
                  values.put(History.GUID, generateGuid());
                  values.put(History.GUID, Utils.generateGuid());
                }

                String url = values.getAsString(History.URL);
@@ -767,7 +723,7 @@ public class BrowserProvider extends ContentProvider {
                values.put(History.DATE_MODIFIED, now);

                // Generate GUID for new history entry
                values.put(History.GUID, generateGuid());
                values.put(History.GUID, Utils.generateGuid());

                String url = values.getAsString(Images.URL);

@@ -825,8 +781,8 @@ public class BrowserProvider extends ContentProvider {
            case BOOKMARKS_ID:
                Log.d(LOGTAG, "Update on BOOKMARKS_ID: " + uri);

                selection = concatenateWhere(selection, TABLE_BOOKMARKS + "._id = ?");
                selectionArgs = appendSelectionArgs(selectionArgs,
                selection = DBUtils.concatenateWhere(selection, TABLE_BOOKMARKS + "._id = ?");
                selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                        new String[] { Long.toString(ContentUris.parseId(uri)) });
                // fall through
            case BOOKMARKS: {
@@ -838,8 +794,8 @@ public class BrowserProvider extends ContentProvider {
            case HISTORY_ID:
                Log.d(LOGTAG, "Update on HISTORY_ID: " + uri);

                selection = concatenateWhere(selection, TABLE_HISTORY + "._id = ?");
                selectionArgs = appendSelectionArgs(selectionArgs,
                selection = DBUtils.concatenateWhere(selection, TABLE_HISTORY + "._id = ?");
                selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                        new String[] { Long.toString(ContentUris.parseId(uri)) });
                // fall through
            case HISTORY: {
@@ -887,17 +843,17 @@ public class BrowserProvider extends ContentProvider {
                Log.d(LOGTAG, "Query is on bookmarks: " + uri);

                if (match == BOOKMARKS_ID) {
                    selection = concatenateWhere(selection, Bookmarks._ID + " = ?");
                    selectionArgs = appendSelectionArgs(selectionArgs,
                    selection = DBUtils.concatenateWhere(selection, Bookmarks._ID + " = ?");
                    selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                            new String[] { Long.toString(ContentUris.parseId(uri)) });
                } else if (match == BOOKMARKS_FOLDER_ID) {
                    selection = concatenateWhere(selection, Bookmarks.PARENT + " = ?");
                    selectionArgs = appendSelectionArgs(selectionArgs,
                    selection = DBUtils.concatenateWhere(selection, Bookmarks.PARENT + " = ?");
                    selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                            new String[] { Long.toString(ContentUris.parseId(uri)) });
                }

                if (!shouldShowDeleted(uri))
                    selection = concatenateWhere(Bookmarks.IS_DELETED + " = 0", selection);
                    selection = DBUtils.concatenateWhere(Bookmarks.IS_DELETED + " = 0", selection);

                if (TextUtils.isEmpty(sortOrder)) {
                    sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER;
@@ -920,13 +876,13 @@ public class BrowserProvider extends ContentProvider {
                Log.d(LOGTAG, "Query is on history: " + uri);

                if (match == HISTORY_ID) {
                    selection = concatenateWhere(selection, History._ID + " = ?");
                    selectionArgs = appendSelectionArgs(selectionArgs,
                    selection = DBUtils.concatenateWhere(selection, History._ID + " = ?");
                    selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                            new String[] { Long.toString(ContentUris.parseId(uri)) });
                }

                if (!shouldShowDeleted(uri))
                    selection = concatenateWhere(History.IS_DELETED + " = 0", selection);
                    selection = DBUtils.concatenateWhere(History.IS_DELETED + " = 0", selection);

                if (TextUtils.isEmpty(sortOrder))
                    sortOrder = DEFAULT_HISTORY_SORT_ORDER;
@@ -946,13 +902,13 @@ public class BrowserProvider extends ContentProvider {
                Log.d(LOGTAG, "Query is on images: " + uri);

                if (match == IMAGES_ID) {
                    selection = concatenateWhere(selection, Images._ID + " = ?");
                    selectionArgs = appendSelectionArgs(selectionArgs,
                    selection = DBUtils.concatenateWhere(selection, Images._ID + " = ?");
                    selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
                            new String[] { Long.toString(ContentUris.parseId(uri)) });
                }

                if (!shouldShowDeleted(uri))
                    selection = concatenateWhere(Images.IS_DELETED + " = 0", selection);
                    selection = DBUtils.concatenateWhere(Images.IS_DELETED + " = 0", selection);

                qb.setProjectionMap(IMAGES_PROJECTION_MAP);
                qb.setTables(TABLE_IMAGES);
@@ -1181,7 +1137,7 @@ public class BrowserProvider extends ContentProvider {
        if (updated == 0 && insertIfNeeded) {
            // Generate GUID for new image, if one is not already provided.
            if (!values.containsKey(Images.GUID)) {
              values.put(Images.GUID, generateGuid());
              values.put(Images.GUID, Utils.generateGuid());
            }

            values.put(Images.DATE_CREATED, now);
+66 −0
Original line number Diff line number Diff line
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.db;

import org.mozilla.gecko.sync.Utils;

import android.content.ContentValues;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import java.util.UUID;

import java.util.Random;

public class DBUtils {
    public static final String qualifyColumn(String table, String column) {
        return table + "." + column;
    }

    // This is available in Android >= 11. Implemented locally to be
    // compatible with older versions.
    public static String concatenateWhere(String a, String b) {
        if (TextUtils.isEmpty(a)) {
            return b;
        }

        if (TextUtils.isEmpty(b)) {
            return a;
        }

        return "(" + a + ") AND (" + b + ")";
    }

    // This is available in Android >= 11. Implemented locally to be
    // compatible with older versions.
    public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) {
        if (originalValues == null || originalValues.length == 0) {
            return newValues;
        }

        if (newValues == null || newValues.length == 0) {
            return originalValues;
        }

        String[] result = new String[originalValues.length + newValues.length];
        System.arraycopy(originalValues, 0, result, 0, originalValues.length);
        System.arraycopy(newValues, 0, result, originalValues.length, newValues.length);

        return result;
    }

    public static void replaceKey(ContentValues aValues, String aOriginalKey,
                                  String aNewKey, String aDefault) {
        String value = aDefault;
        if (aOriginalKey != null && aValues.containsKey(aOriginalKey)) {
            value = aValues.get(aOriginalKey).toString();
            aValues.remove(aOriginalKey);
        }

        if (!aValues.containsKey(aOriginalKey)) {
            aValues.put(aNewKey, value);
        }
    }
}
Loading