Bug 945212 - Encapsulate identity data/security mode behind a type-safe API (r=margaret)

This commit is contained in:
Lucas Rocha 2013-12-12 00:28:15 +00:00
parent f9cbf23895
commit 03f47d073e
5 changed files with 159 additions and 85 deletions

View File

@ -0,0 +1,110 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* 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;
import org.json.JSONObject;
import android.text.TextUtils;
public class SiteIdentity {
private SecurityMode mSecurityMode;
private String mHost;
private String mOwner;
private String mSupplemental;
private String mVerifier;
private String mEncrypted;
// The order of the items here correspond to image
// levels in site_security_level.xml
public enum SecurityMode {
UNKNOWN("unknown"),
VERIFIED("verified"),
IDENTIFIED("identified"),
MIXED_CONTENT_BLOCKED("mixed_content_blocked"),
MIXED_CONTENT_LOADED("mixed_content_loaded");
private final String mId;
private SecurityMode(String id) {
mId = id;
}
public static SecurityMode fromString(String id) {
if (id == null) {
throw new IllegalArgumentException("Can't convert null String to SiteIdentity");
}
for (SecurityMode mode : SecurityMode.values()) {
if (TextUtils.equals(mode.mId, id.toLowerCase())) {
return mode;
}
}
throw new IllegalArgumentException("Could not convert String id to SiteIdentity");
}
@Override
public String toString() {
return mId;
}
}
public SiteIdentity() {
reset(SecurityMode.UNKNOWN);
}
private void reset(SecurityMode securityMode) {
mSecurityMode = securityMode;
mHost = null;
mOwner = null;
mSupplemental = null;
mVerifier = null;
mEncrypted = null;
}
void update(JSONObject identityData) {
try {
mSecurityMode = SecurityMode.fromString(identityData.getString("mode"));
} catch (Exception e) {
reset(SecurityMode.UNKNOWN);
return;
}
try {
mHost = identityData.getString("host");
mOwner = identityData.getString("owner");
mSupplemental = identityData.optString("supplemental", null);
mVerifier = identityData.getString("verifier");
mEncrypted = identityData.getString("encrypted");
} catch (Exception e) {
reset(mSecurityMode);
}
}
public SecurityMode getSecurityMode() {
return mSecurityMode;
}
public String getHost() {
return mHost;
}
public String getOwner() {
return mOwner;
}
public String getSupplemental() {
return mSupplemental;
}
public String getVerifier() {
return mVerifier;
}
public String getEncrypted() {
return mEncrypted;
}
}

View File

@ -5,10 +5,10 @@
package org.mozilla.gecko;
import org.mozilla.gecko.SiteIdentity.SecurityMode;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.home.HomePager;
import org.mozilla.gecko.toolbar.SiteIdentityPopup;
import org.mozilla.gecko.util.ThreadUtils;
import org.json.JSONException;
@ -46,7 +46,7 @@ public class Tab {
private int mFaviconSize;
private boolean mHasFeeds;
private boolean mHasOpenSearch;
private JSONObject mIdentityData;
private SiteIdentity mSiteIdentity;
private boolean mReaderEnabled;
private BitmapDrawable mThumbnail;
private int mHistoryIndex;
@ -102,7 +102,7 @@ public class Tab {
mFaviconSize = 0;
mHasFeeds = false;
mHasOpenSearch = false;
mIdentityData = null;
mSiteIdentity = new SiteIdentity();
mReaderEnabled = false;
mEnteringReaderMode = false;
mThumbnail = null;
@ -247,17 +247,12 @@ public class Tab {
return mHasOpenSearch;
}
public String getSecurityMode() {
try {
return mIdentityData.getString("mode");
} catch (Exception e) {
// If mIdentityData is null, or we get a JSONException
return SiteIdentityPopup.UNKNOWN;
}
public SecurityMode getSecurityMode() {
return mSiteIdentity.getSecurityMode();
}
public JSONObject getIdentityData() {
return mIdentityData;
public SiteIdentity getSiteIdentity() {
return mSiteIdentity;
}
public boolean getReaderEnabled() {
@ -416,7 +411,7 @@ public class Tab {
}
public void updateIdentityData(JSONObject identityData) {
mIdentityData = identityData;
mSiteIdentity.update(identityData);
}
public void setReaderEnabled(boolean readerEnabled) {

View File

@ -278,6 +278,7 @@ gbjar.sources += [
'ServiceNotificationClient.java',
'SessionParser.java',
'SharedPreferencesHelper.java',
'SiteIdentity.java',
'SmsManager.java',
'sqlite/ByteBufferInputStream.java',
'sqlite/MatrixBlobCursor.java',

View File

@ -12,6 +12,8 @@ import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.LightweightTheme;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SiteIdentity;
import org.mozilla.gecko.SiteIdentity.SecurityMode;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.animation.PropertyAnimator;
@ -428,13 +430,15 @@ public class BrowserToolbar extends GeckoRelativeLayout
if (mSiteSecurity.getVisibility() != View.VISIBLE)
return;
JSONObject identityData = Tabs.getInstance().getSelectedTab().getIdentityData();
if (identityData == null) {
final Tab tab = Tabs.getInstance().getSelectedTab();
final SiteIdentity siteIdentity = tab.getSiteIdentity();
if (siteIdentity.getSecurityMode() == SecurityMode.UNKNOWN) {
Log.e(LOGTAG, "Selected tab has no identity data");
return;
}
mSiteIdentityPopup.updateIdentity(identityData);
mSiteIdentityPopup.updateIdentity(siteIdentity);
mSiteIdentityPopup.show();
}
};
@ -978,11 +982,10 @@ public class BrowserToolbar extends GeckoRelativeLayout
mFavicon.setImageDrawable(null);
}
}
private void setSecurityMode(String mode) {
int imageLevel = SiteIdentityPopup.getSecurityImageLevel(mode);
mSiteSecurity.setImageLevel(imageLevel);
mShowSiteSecurity = (imageLevel != SiteIdentityPopup.LEVEL_UKNOWN);
private void setSecurityMode(SecurityMode mode) {
mSiteSecurity.setImageLevel(mode.ordinal());
mShowSiteSecurity = (mode != SecurityMode.UNKNOWN);
setPageActionVisibility(mStop.getVisibility() == View.VISIBLE);
}

View File

@ -8,6 +8,8 @@ import org.mozilla.gecko.BrowserApp;
import org.mozilla.gecko.R;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.SiteIdentity;
import org.mozilla.gecko.SiteIdentity.SecurityMode;
import org.mozilla.gecko.widget.ArrowPopup;
import org.mozilla.gecko.widget.DoorHanger;
import org.mozilla.gecko.widget.DoorHanger.OnButtonClickListener;
@ -31,19 +33,6 @@ import android.widget.TextView;
public class SiteIdentityPopup extends ArrowPopup {
private static final String LOGTAG = "GeckoSiteIdentityPopup";
public static final String UNKNOWN = "unknown";
public static final String VERIFIED = "verified";
public static final String IDENTIFIED = "identified";
public static final String MIXED_CONTENT_BLOCKED = "mixed_content_blocked";
public static final String MIXED_CONTENT_LOADED = "mixed_content_loaded";
// Security states corresponding to image levels in site_security_level.xml
static final int LEVEL_UKNOWN = 0;
static final int LEVEL_IDENTIFIED = 1;
static final int LEVEL_VERIFIED = 2;
static final int LEVEL_MIXED_CONTENT_BLOCKED = 3;
static final int LEVEL_MIXED_CONTENT_LOADED = 4;
// FIXME: Update this URL for mobile. See bug 885923.
private static final String MIXED_CONTENT_SUPPORT_URL =
"https://support.mozilla.org/kb/how-does-content-isnt-secure-affect-my-safety";
@ -66,22 +55,6 @@ public class SiteIdentityPopup extends ArrowPopup {
mButtonClickListener = new PopupButtonListener();
}
static int getSecurityImageLevel(String mode) {
if (IDENTIFIED.equals(mode)) {
return LEVEL_IDENTIFIED;
}
if (VERIFIED.equals(mode)) {
return LEVEL_VERIFIED;
}
if (MIXED_CONTENT_BLOCKED.equals(mode)) {
return LEVEL_MIXED_CONTENT_BLOCKED;
}
if (MIXED_CONTENT_LOADED.equals(mode)) {
return LEVEL_MIXED_CONTENT_LOADED;
}
return LEVEL_UKNOWN;
}
@Override
protected void init() {
super.init();
@ -99,33 +72,31 @@ public class SiteIdentityPopup extends ArrowPopup {
mVerifier = (TextView) mIdentity.findViewById(R.id.verifier);
}
private void setIdentity(JSONObject identityData) {
try {
String host = identityData.getString("host");
mHost.setText(host);
String owner = identityData.getString("owner");
// Supplemental data is optional.
String supplemental = identityData.optString("supplemental");
if (!TextUtils.isEmpty(supplemental)) {
owner += "\n" + supplemental;
}
mOwner.setText(owner);
String verifier = identityData.getString("verifier");
String encrypted = identityData.getString("encrypted");
mVerifier.setText(verifier + "\n" + encrypted);
mContent.setPadding(0, 0, 0, 0);
mIdentity.setVisibility(View.VISIBLE);
} catch (JSONException e) {
private void setIdentity(SiteIdentity siteIdentity) {
if (siteIdentity.getSecurityMode() == SecurityMode.MIXED_CONTENT_LOADED) {
// Hide the identity data if there isn't valid site identity data.
// Set some top padding on the popup content to create a of light blue
// between the popup arrow and the mixed content notification.
mContent.setPadding(0, (int) mResources.getDimension(R.dimen.identity_padding_top), 0, 0);
mIdentity.setVisibility(View.GONE);
} else {
mHost.setText(siteIdentity.getHost());
String owner = siteIdentity.getOwner();
// Supplemental data is optional.
final String supplemental = siteIdentity.getSupplemental();
if (!TextUtils.isEmpty(supplemental)) {
owner += "\n" + supplemental;
}
mOwner.setText(owner);
final String verifier = siteIdentity.getVerifier();
final String encrypted = siteIdentity.getEncrypted();
mVerifier.setText(verifier + "\n" + encrypted);
mContent.setPadding(0, 0, 0, 0);
mIdentity.setVisibility(View.VISIBLE);
}
}
@ -169,16 +140,9 @@ public class SiteIdentityPopup extends ArrowPopup {
/*
* @param identityData A JSONObject that holds the current tab's identity data.
*/
void updateIdentity(JSONObject identityData) {
String mode;
try {
mode = identityData.getString("mode");
} catch (JSONException e) {
Log.e(LOGTAG, "Exception trying to get identity mode", e);
return;
}
if (UNKNOWN.equals(mode)) {
void updateIdentity(SiteIdentity siteIdentity) {
final SecurityMode mode = siteIdentity.getSecurityMode();
if (mode == SecurityMode.UNKNOWN) {
Log.e(LOGTAG, "Can't show site identity popup in non-identified state");
return;
}
@ -186,10 +150,11 @@ public class SiteIdentityPopup extends ArrowPopup {
if (!mInflated)
init();
setIdentity(identityData);
setIdentity(siteIdentity);
if (MIXED_CONTENT_BLOCKED.equals(mode) || MIXED_CONTENT_LOADED.equals(mode)) {
addMixedContentNotification(MIXED_CONTENT_BLOCKED.equals(mode));
if (mode == SecurityMode.MIXED_CONTENT_LOADED ||
mode == SecurityMode.MIXED_CONTENT_BLOCKED) {
addMixedContentNotification(mode == SecurityMode.MIXED_CONTENT_BLOCKED);
}
}