mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
162 lines
7.2 KiB
Java
162 lines
7.2 KiB
Java
#filter substitution
|
|
package @ANDROID_PACKAGE_NAME@.tests;
|
|
|
|
import @ANDROID_PACKAGE_NAME@.*;
|
|
import android.app.Activity;
|
|
import android.content.ContentValues;
|
|
import android.content.ContentResolver;
|
|
import android.database.Cursor;
|
|
import android.content.Context;
|
|
import android.net.Uri;
|
|
import java.io.File;
|
|
import java.lang.reflect.Method;
|
|
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
public class testPasswordEncrypt extends BaseTest {
|
|
@Override
|
|
protected int getTestType() {
|
|
return TEST_MOCHITEST;
|
|
}
|
|
|
|
public void testPasswordEncrypt() {
|
|
Context context = (Context)getActivity();
|
|
ContentResolver cr = context.getContentResolver();
|
|
mAsserter.isnot(cr, null, "Found a content resolver");
|
|
ContentValues cvs = new ContentValues();
|
|
|
|
Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("Gecko:Ready");
|
|
contentEventExpecter.blockForEvent();
|
|
|
|
File db = new File(mProfile, "signons.sqlite");
|
|
String dbPath = db.getPath();
|
|
|
|
Uri passwordUri;
|
|
try {
|
|
ClassLoader classLoader = getActivity().getClassLoader();
|
|
Class pwds = classLoader.loadClass("org.mozilla.gecko.db.BrowserContract$Passwords");
|
|
Class nss = classLoader.loadClass("org.mozilla.gecko.NSSBridge");
|
|
Class contextClass = classLoader.loadClass("android.content.Context");
|
|
Class stringClass = classLoader.loadClass("java.lang.String");
|
|
Class appshell = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
|
|
|
|
Method loadNSSLibs = appshell.getMethod("loadNSSLibs", contextClass, stringClass);
|
|
Method decrypt = nss.getMethod("decrypt", contextClass, stringClass, stringClass);
|
|
Method encrypt = nss.getMethod("encrypt", contextClass, stringClass, stringClass);
|
|
|
|
cvs.put("hostname", "http://www.example.com");
|
|
cvs.put("encryptedUsername", "username");
|
|
cvs.put("encryptedPassword", "password");
|
|
|
|
// Attempt to insert into the db
|
|
passwordUri = (Uri)pwds.getField("CONTENT_URI").get(null);
|
|
Uri.Builder builder = passwordUri.buildUpon();
|
|
passwordUri = builder.appendQueryParameter("profilePath", mProfile).build();
|
|
|
|
Uri uri = cr.insert(passwordUri, cvs);
|
|
Uri expectedUri = passwordUri.buildUpon().appendPath("1").build();
|
|
mAsserter.is(uri.toString(), expectedUri.toString(), "Insert returned correct uri");
|
|
|
|
Cursor list = mActions.querySql(dbPath, "SELECT encryptedUsername FROM moz_logins");
|
|
String resourcePath = getActivity().getApplication().getPackageResourcePath();
|
|
loadNSSLibs.invoke(null, (Context)getActivity(), resourcePath);
|
|
|
|
list.moveToFirst();
|
|
String decryptedU = (String)decrypt.invoke(null, context, mProfile, list.getString(0));
|
|
mAsserter.is(decryptedU, "username", "Username was encrypted correctly when inserting");
|
|
|
|
list = mActions.querySql(dbPath, "SELECT encryptedPassword, encType FROM moz_logins");
|
|
list.moveToFirst();
|
|
String decryptedP = (String)decrypt.invoke(null, context, mProfile, list.getString(0));
|
|
mAsserter.is(decryptedP, "password", "Password was encrypted correctly when inserting");
|
|
mAsserter.is(list.getInt(1), 1, "Password has correct encryption type");
|
|
|
|
cvs.put("encryptedUsername", "username2");
|
|
cvs.put("encryptedPassword", "password2");
|
|
cr.update(passwordUri, cvs, null, null);
|
|
|
|
list = mActions.querySql(dbPath, "SELECT encryptedUsername FROM moz_logins");
|
|
list.moveToFirst();
|
|
decryptedU = (String)decrypt.invoke(null, context, mProfile, list.getString(0));
|
|
mAsserter.is(decryptedU, "username2", "Username was encrypted when updating");
|
|
|
|
list = mActions.querySql(dbPath, "SELECT encryptedPassword FROM moz_logins");
|
|
list.moveToFirst();
|
|
decryptedP = (String)decrypt.invoke(null, context, mProfile, list.getString(0));
|
|
mAsserter.is(decryptedP, "password2", "Password was encrypted when updating");
|
|
|
|
// Trying to store a password while master password is enabled should throw,
|
|
// but because Android can't send Exceptions across processes
|
|
// it just results in a null uri/cursor being returned.
|
|
toggleMasterPassword("password");
|
|
try {
|
|
uri = cr.insert(passwordUri, cvs);
|
|
mAsserter.is(uri, null, "Storing a password while MP was set should fail");
|
|
|
|
Cursor c = cr.query(passwordUri, null, null, null, null);
|
|
mAsserter.is(c, null, "Querying passwords while MP was set should fail");
|
|
} catch (Exception ex) {
|
|
// Password provider currently can not throw across process
|
|
// so we should not catch this exception here
|
|
mAsserter.ok(false, "Caught exception", ex.toString());
|
|
}
|
|
toggleMasterPassword("password");
|
|
|
|
} catch(ClassNotFoundException ex) {
|
|
mAsserter.ok(false, "Error getting class", ex.toString());
|
|
return;
|
|
} catch(NoSuchFieldException ex) {
|
|
mAsserter.ok(false, "Error getting field", ex.toString());
|
|
return;
|
|
} catch(IllegalAccessException ex) {
|
|
mAsserter.ok(false, "Error using field", ex.toString());
|
|
return;
|
|
} catch(java.lang.NoSuchMethodException ex) {
|
|
mAsserter.ok(false, "Error getting method", ex.toString());
|
|
return;
|
|
} catch(java.lang.reflect.InvocationTargetException ex) {
|
|
mAsserter.ok(false, "Error invoking method", ex.toString());
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void toggleMasterPassword(String passwd) {
|
|
JSONObject jsonPref = new JSONObject();
|
|
try {
|
|
jsonPref.put("name", "privacy.masterpassword.enabled");
|
|
jsonPref.put("type", "string");
|
|
jsonPref.put("value", passwd);
|
|
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
|
|
} catch (Exception ex) {
|
|
mAsserter.ok(false, "exception in toggleMasterPassword", ex.toString());
|
|
}
|
|
|
|
// Wait for confirmation of the pref change before proceeding with the test.
|
|
JSONArray getPrefData = new JSONArray();
|
|
getPrefData.put("privacy.masterpassword.enabled");
|
|
Actions.RepeatedEventExpecter contentEventExpecter = mActions.expectGeckoEvent("Preferences:Data");
|
|
mActions.sendGeckoEvent("Preferences:Get", getPrefData.toString());
|
|
// Receiving a Preferences:Data event is not conclusive evidence that *our*
|
|
// preference has been set -- another component may be changing preferences
|
|
// at the same time. Mitigate this risk by waiting for a Preference:Data
|
|
// and then waiting for a period of time in which no more Preference:Data
|
|
// events are received.
|
|
contentEventExpecter.blockUntilClear(2000);
|
|
}
|
|
|
|
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()) {
|
|
mAsserter.dumpLog("tearDown deleted "+db.toString());
|
|
} else {
|
|
mAsserter.dumpLog("tearDown did not delete "+db.toString());
|
|
}
|
|
|
|
super.tearDown();
|
|
}
|
|
}
|