Bug 946857 - pre : Expose disabled hosts through Password CP r?nalexander
Added a simple robocop test to verify that it is possible to query disabledHosts with PasswordProviders.
MozReview-Commit-ID: K4j4Aczp2xv
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
@@ -243,16 +243,25 @@ public class BrowserContract {
}
public static final class DeletedPasswords implements DeletedColumns {
private DeletedPasswords() {}
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/deleted-passwords";
public static final Uri CONTENT_URI = Uri.withAppendedPath(PASSWORDS_AUTHORITY_URI, "deleted-passwords");
}
+ @RobocopTarget
+ public static final class GeckoDisabledHosts {
+ private GeckoDisabledHosts() {}
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/disabled-hosts";
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(PASSWORDS_AUTHORITY_URI, "disabled-hosts");
+
+ public static final String HOSTNAME = "hostname";
+ }
+
public static final class FormHistory {
private FormHistory() {}
public static final Uri CONTENT_URI = Uri.withAppendedPath(FORM_HISTORY_AUTHORITY_URI, "formhistory");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/formhistory";
public static final String ID = "id";
public static final String FIELD_NAME = "fieldname";
public static final String VALUE = "value";
--- a/mobile/android/base/java/org/mozilla/gecko/db/PasswordsProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/PasswordsProvider.java
@@ -8,16 +8,17 @@ import java.util.HashMap;
import org.mozilla.gecko.CrashHandler;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.GeckoMessageReceiver;
import org.mozilla.gecko.NSSBridge;
import org.mozilla.gecko.db.BrowserContract.DeletedPasswords;
+import org.mozilla.gecko.db.BrowserContract.GeckoDisabledHosts;
import org.mozilla.gecko.db.BrowserContract.Passwords;
import org.mozilla.gecko.mozglue.GeckoLoader;
import org.mozilla.gecko.sqlite.MatrixBlobCursor;
import org.mozilla.gecko.sqlite.SQLiteBridge;
import org.mozilla.gecko.sync.Utils;
import android.content.ContentValues;
import android.content.Intent;
@@ -25,29 +26,32 @@ import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
public class PasswordsProvider extends SQLiteBridgeContentProvider {
static final String TABLE_PASSWORDS = "moz_logins";
static final String TABLE_DELETED_PASSWORDS = "moz_deleted_logins";
+ static final String TABLE_DISABLED_HOSTS = "moz_disabledHosts";
private static final String TELEMETRY_TAG = "SQLITEBRIDGE_PROVIDER_PASSWORDS";
private static final int PASSWORDS = 100;
private static final int DELETED_PASSWORDS = 101;
+ private static final int DISABLED_HOSTS = 102;
static final String DEFAULT_PASSWORDS_SORT_ORDER = Passwords.HOSTNAME + " ASC";
static final String DEFAULT_DELETED_PASSWORDS_SORT_ORDER = DeletedPasswords.TIME_DELETED + " ASC";
private static final UriMatcher URI_MATCHER;
private static final HashMap<String, String> PASSWORDS_PROJECTION_MAP;
private static final HashMap<String, String> DELETED_PASSWORDS_PROJECTION_MAP;
+ private static final HashMap<String, String> DISABLED_HOSTS_PROJECTION_MAP;
// this should be kept in sync with the version in toolkit/components/passwordmgr/storage-mozStorage.js
private static final int DB_VERSION = 5;
private static final String DB_FILENAME = "signons.sqlite";
private static final String WHERE_GUID_IS_NULL = BrowserContract.DeletedPasswords.GUID + " IS NULL";
private static final String WHERE_GUID_IS_VALUE = BrowserContract.DeletedPasswords.GUID + " = ?";
private static final String LOG_TAG = "GeckoPasswordsProvider";
@@ -77,16 +81,21 @@ public class PasswordsProvider extends S
PASSWORDS_PROJECTION_MAP.put(Passwords.TIMES_USED, Passwords.TIMES_USED);
URI_MATCHER.addURI(BrowserContract.PASSWORDS_AUTHORITY, "deleted-passwords", DELETED_PASSWORDS);
DELETED_PASSWORDS_PROJECTION_MAP = new HashMap<String, String>();
DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.ID, DeletedPasswords.ID);
DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.GUID, DeletedPasswords.GUID);
DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.TIME_DELETED, DeletedPasswords.TIME_DELETED);
+
+ URI_MATCHER.addURI(BrowserContract.PASSWORDS_AUTHORITY, "disabled-hosts", DISABLED_HOSTS);
+
+ DISABLED_HOSTS_PROJECTION_MAP = new HashMap<String, String>();
+ DISABLED_HOSTS_PROJECTION_MAP.put(GeckoDisabledHosts.HOSTNAME, GeckoDisabledHosts.HOSTNAME);
}
public PasswordsProvider() {
super(LOG_TAG);
}
@Override
public boolean onCreate() {
@@ -129,31 +138,37 @@ public class PasswordsProvider extends S
switch (match) {
case PASSWORDS:
return Passwords.CONTENT_TYPE;
case DELETED_PASSWORDS:
return DeletedPasswords.CONTENT_TYPE;
+ case DISABLED_HOSTS:
+ return GeckoDisabledHosts.CONTENT_TYPE;
+
default:
throw new UnsupportedOperationException("Unknown type " + uri);
}
}
@Override
public String getTable(Uri uri) {
final int match = URI_MATCHER.match(uri);
switch (match) {
case DELETED_PASSWORDS:
return TABLE_DELETED_PASSWORDS;
case PASSWORDS:
return TABLE_PASSWORDS;
+ case DISABLED_HOSTS:
+ return TABLE_DISABLED_HOSTS;
+
default:
throw new UnsupportedOperationException("Unknown table " + uri);
}
}
@Override
public String getSortOrder(Uri uri, String aRequested) {
if (!TextUtils.isEmpty(aRequested)) {
@@ -163,16 +178,19 @@ public class PasswordsProvider extends S
final int match = URI_MATCHER.match(uri);
switch (match) {
case DELETED_PASSWORDS:
return DEFAULT_DELETED_PASSWORDS_SORT_ORDER;
case PASSWORDS:
return DEFAULT_PASSWORDS_SORT_ORDER;
+ case DISABLED_HOSTS:
+ return null;
+
default:
throw new UnsupportedOperationException("Unknown URI " + uri);
}
}
@Override
public void setupDefaults(Uri uri, ContentValues values)
throws IllegalArgumentException {
@@ -205,16 +223,22 @@ public class PasswordsProvider extends S
DBUtils.replaceKey(values, null, Passwords.ENCRYPTED_USERNAME, "");
DBUtils.replaceKey(values, null, Passwords.ENCRYPTED_PASSWORD, "");
DBUtils.replaceKey(values, null, Passwords.ENC_TYPE, "0");
DBUtils.replaceKey(values, null, Passwords.TIME_LAST_USED, nowString);
DBUtils.replaceKey(values, null, Passwords.TIME_PASSWORD_CHANGED, nowString);
DBUtils.replaceKey(values, null, Passwords.TIMES_USED, "0");
break;
+ case DISABLED_HOSTS:
+ if (!values.containsKey(GeckoDisabledHosts.HOSTNAME)) {
+ throw new IllegalArgumentException("Must provide a hostname for a disabled host");
+ }
+ break;
+
default:
throw new UnsupportedOperationException("Unknown URI " + uri);
}
}
@Override
public void initGecko() {
// We're not in the main process. The receiver of this Intent can
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java
@@ -1,30 +1,34 @@
/* 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.tests;
import java.io.File;
+import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.db.BrowserContract.GeckoDisabledHosts;
import org.mozilla.gecko.db.BrowserContract.Passwords;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
/**
* A basic password contentprovider test.
* - inserts a password when the database is not yet set up
* - inserts a password
* - updates a password
* - deletes a password
+ * - inserts a disabled host
+ * - queries for disabled host
*/
public class testPasswordProvider extends BaseTest {
private static final String DB_NAME = "signons.sqlite";
public void testPasswordProvider() {
Context context = (Context)getActivity();
ContentResolver cr = context.getContentResolver();
ContentValues[] cvs = new ContentValues[1];
@@ -60,16 +64,33 @@ public class testPasswordProvider extend
c = cr.query(passwordUri, null, null, null, null);
SqliteCompare(c, cvs);
int numDeleted = cr.delete(passwordUri, null, null);
mAsserter.is(1, numDeleted, "Correct number deleted");
cvs = new ContentValues[0];
c = cr.query(passwordUri, null, null, null, null);
SqliteCompare(c, cvs);
+
+ ContentValues values = new ContentValues();
+ values.put("hostname", "http://www.example.com");
+
+ // Attempt to insert into the db.
+ Uri disabledHostUri = GeckoDisabledHosts.CONTENT_URI;
+ builder = disabledHostUri.buildUpon();
+ disabledHostUri = builder.appendQueryParameter("profilePath", mProfile).build();
+
+ uri = cr.insert(disabledHostUri, values);
+ expectedUri = disabledHostUri.buildUpon().appendPath("1").build();
+ mAsserter.is(uri.toString(), expectedUri.toString(), "Insert returned correct uri");
+ Cursor cursor = cr.query(disabledHostUri, null, null, null, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ CursorMatches(cursor, values);
}
@Override
public void tearDown() throws Exception {
// remove the entire signons.sqlite file
File profile = new File(mProfile);
File db = new File(profile, "signons.sqlite");
if (db.delete()) {