Bug 946857 - Part 1: Expose disabled hosts through Password CP r=nalexander
authorvivek <vivekb.balakrishnan@gmail.com>
Tue, 15 Dec 2015 19:23:14 +0200
changeset 322947 b5774ec699c9678535e082d16238a331073e272c
parent 322946 b8297417dfc432d000211b91ac8ea2a6187a0e1c
child 322948 2c6222ddc0330ef5b0473363889a46110a8ade07
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs946857
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 946857 - Part 1: 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
mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
mobile/android/base/java/org/mozilla/gecko/db/PasswordsProvider.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
@@ -244,16 +244,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()) {