Bug 757646 - Throw from NSSBridge if Master password is set. r=rnewman,gbrown

This commit is contained in:
Wes Johnston 2012-05-25 10:04:12 -07:00
parent 35b5448ba4
commit ecb051e05d
6 changed files with 92 additions and 38 deletions

View File

@ -29,6 +29,13 @@ public interface Actions {
public void blockUntilClear(long millis);
}
/**
* Sends an event to Gecko.
*
* @param geckoEvent The geckoEvent JSONObject's type
*/
void sendGeckoEvent(String geckoEvent, String data);
/**
* Listens for a gecko event to be sent from the Gecko instance.
* The returned object can be used to test if the event has been

View File

@ -13,6 +13,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.Long;
import java.lang.NoSuchMethodException;
import java.util.concurrent.SynchronousQueue;
import java.util.ArrayList;
@ -180,6 +181,20 @@ public class FennecNativeActions implements Actions {
return null;
}
public void sendGeckoEvent(String geckoEvent, String data) {
try {
Method cbe = mGe.getMethod("createBroadcastEvent", String.class, String.class);
Object event = cbe.invoke(null, geckoEvent, data);
mSendGE.invoke(null, event);
} catch (NoSuchMethodException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (IllegalAccessException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
}
}
class DrawListenerProxy implements InvocationHandler {
private final PaintExpecter mPaintExpecter;

View File

@ -15,49 +15,37 @@ public class NSSBridge {
private static native String nativeEncrypt(String aDb, String aValue);
private static native String nativeDecrypt(String aDb, String aValue);
static public String encrypt(Context context, String aValue) {
static public String encrypt(Context context, String aValue)
throws Exception {
String resourcePath = context.getPackageResourcePath();
GeckoAppShell.loadNSSLibs(context, resourcePath);
String res = "";
try {
String path = GeckoProfile.get(context).getDir().toString();
res = nativeEncrypt(path, aValue);
} catch(Exception ex) { }
return res;
String path = GeckoProfile.get(context).getDir().toString();
return nativeEncrypt(path, aValue);
}
static public String encrypt(Context context, String profilePath, String aValue) {
static public String encrypt(Context context, String profilePath, String aValue)
throws Exception {
String resourcePath = context.getPackageResourcePath();
GeckoAppShell.loadNSSLibs(context, resourcePath);
String res = "";
try {
res = nativeEncrypt(profilePath, aValue);
} catch(Exception ex) { }
return res;
return nativeEncrypt(profilePath, aValue);
}
static public String decrypt(Context context, String aValue) {
static public String decrypt(Context context, String aValue)
throws Exception {
String resourcePath = context.getPackageResourcePath();
GeckoAppShell.loadNSSLibs(context, resourcePath);
String res = "";
try {
String path = GeckoProfile.get(context).getDir().toString();
res = nativeDecrypt(path, aValue);
} catch(Exception ex) { }
return res;
String path = GeckoProfile.get(context).getDir().toString();
return nativeDecrypt(path, aValue);
}
static public String decrypt(Context context, String profilePath, String aValue) {
static public String decrypt(Context context, String profilePath, String aValue)
throws Exception {
String resourcePath = context.getPackageResourcePath();
GeckoAppShell.loadNSSLibs(context, resourcePath);
String res = "";
try {
res = nativeDecrypt(profilePath, aValue);
} catch(Exception ex) { }
return res;
return nativeDecrypt(profilePath, aValue);
}
}

View File

@ -142,7 +142,6 @@ public abstract class GeckoProvider extends ContentProvider {
// call to Gecko. Gecko will handle building the database file correctly, as well as any
// migrations that are necessary
if (dbNeedsSetup) {
Log.i(mLogTag, "Sending init to gecko");
bridge = null;
initGecko();
}
@ -154,7 +153,6 @@ public abstract class GeckoProvider extends ContentProvider {
private SQLiteBridge getDatabaseForProfile(String profile) {
if (TextUtils.isEmpty(profile)) {
Log.d(mLogTag, "No profile provided, using default");
profile = BrowserContract.DEFAULT_PROFILE;
}
@ -167,7 +165,6 @@ public abstract class GeckoProvider extends ContentProvider {
}
}
Log.d(mLogTag, "Successfully created database helper for profile: " + profile);
return db;
}
@ -181,18 +178,15 @@ public abstract class GeckoProvider extends ContentProvider {
}
}
Log.d(mLogTag, "Successfully created database helper for path: " + profilePath);
return db;
}
private String getDatabasePathForProfile(String profile) {
File profileDir = GeckoProfile.get(mContext, profile).getDir();
if (profileDir == null) {
Log.d(mLogTag, "Couldn't find directory for profile: " + profile);
return null;
}
Log.d(mLogTag, "Using path: " + profileDir.getPath());
String databasePath = new File(profileDir, mDBName).getAbsolutePath();
return databasePath;
}

View File

@ -203,12 +203,23 @@ public class PasswordsProvider extends GeckoProvider {
}
String result = "";
if (encrypt) {
if (profilePath != null) result = NSSBridge.encrypt(mContext, profilePath, initialValue);
else result = NSSBridge.encrypt(mContext, initialValue);
} else {
if (profilePath != null) result = NSSBridge.decrypt(mContext, profilePath, initialValue);
else result = NSSBridge.decrypt(mContext, initialValue);
try {
if (encrypt) {
if (profilePath != null) {
result = NSSBridge.encrypt(mContext, profilePath, initialValue);
} else {
result = NSSBridge.encrypt(mContext, initialValue);
}
} else {
if (profilePath != null) {
result = NSSBridge.decrypt(mContext, profilePath, initialValue);
} else {
result = NSSBridge.decrypt(mContext, initialValue);
}
}
} catch (Exception ex) {
Log.e(getLogTag(), "Error in NSSBridge");
throw new RuntimeException(ex);
}
return result;
}

View File

@ -11,11 +11,16 @@ 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 {
public void testPasswordEncrypt() {
setTestType("mochitest");
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");
@ -77,6 +82,24 @@ public class testPasswordEncrypt extends BaseTest {
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;
@ -95,6 +118,22 @@ public class testPasswordEncrypt extends BaseTest {
}
}
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) { }
JSONArray getPrefData = new JSONArray();
getPrefData.put("privacy.masterpassword.enabled");
Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", getPrefData.toString());
contentEventExpecter.blockForEvent();
}
public void tearDown() throws Exception {
super.tearDown();