Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.toolbar;
7 import org.mozilla.gecko.BrowserApp;
8 import org.mozilla.gecko.R;
9 import org.mozilla.gecko.GeckoAppShell;
10 import org.mozilla.gecko.GeckoEvent;
11 import org.mozilla.gecko.SiteIdentity;
12 import org.mozilla.gecko.SiteIdentity.SecurityMode;
13 import org.mozilla.gecko.widget.ArrowPopup;
14 import org.mozilla.gecko.widget.DoorHanger;
15 import org.mozilla.gecko.widget.DoorHanger.OnButtonClickListener;
17 import org.json.JSONException;
18 import org.json.JSONObject;
20 import android.content.res.Resources;
21 import android.text.TextUtils;
22 import android.util.Log;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 import android.widget.ImageView;
26 import android.widget.LinearLayout;
27 import android.widget.TextView;
29 /**
30 * SiteIdentityPopup is a singleton class that displays site identity data in
31 * an arrow panel popup hanging from the lock icon in the browser toolbar.
32 */
33 public class SiteIdentityPopup extends ArrowPopup {
34 private static final String LOGTAG = "GeckoSiteIdentityPopup";
36 // FIXME: Update this URL for mobile. See bug 885923.
37 private static final String MIXED_CONTENT_SUPPORT_URL =
38 "https://support.mozilla.org/kb/how-does-content-isnt-secure-affect-my-safety";
40 private SiteIdentity mSiteIdentity;
42 private Resources mResources;
44 private LinearLayout mIdentity;
45 private TextView mHost;
46 private TextView mOwner;
47 private TextView mVerifier;
49 private DoorHanger mMixedContentNotification;
51 private final OnButtonClickListener mButtonClickListener;
53 SiteIdentityPopup(BrowserApp activity) {
54 super(activity);
56 mResources = activity.getResources();
57 mButtonClickListener = new PopupButtonListener();
58 }
60 @Override
61 protected void init() {
62 super.init();
64 // Make the popup focusable so it doesn't inadvertently trigger click events elsewhere
65 // which may reshow the popup (see bug 785156)
66 setFocusable(true);
68 LayoutInflater inflater = LayoutInflater.from(mActivity);
69 mIdentity = (LinearLayout) inflater.inflate(R.layout.site_identity, null);
70 mContent.addView(mIdentity);
72 mHost = (TextView) mIdentity.findViewById(R.id.host);
73 mOwner = (TextView) mIdentity.findViewById(R.id.owner);
74 mVerifier = (TextView) mIdentity.findViewById(R.id.verifier);
75 }
77 private void updateUi() {
78 if (!mInflated) {
79 init();
80 }
82 if (mSiteIdentity.getSecurityMode() == SecurityMode.MIXED_CONTENT_LOADED ||
83 mSiteIdentity.getSecurityMode() == SecurityMode.MIXED_CONTENT_BLOCKED) {
84 // Hide the identity data if there isn't valid site identity data.
85 // Set some top padding on the popup content to create a of light blue
86 // between the popup arrow and the mixed content notification.
87 mContent.setPadding(0, (int) mResources.getDimension(R.dimen.identity_padding_top), 0, 0);
88 mIdentity.setVisibility(View.GONE);
89 } else {
90 mHost.setText(mSiteIdentity.getHost());
92 String owner = mSiteIdentity.getOwner();
94 // Supplemental data is optional.
95 final String supplemental = mSiteIdentity.getSupplemental();
96 if (!TextUtils.isEmpty(supplemental)) {
97 owner += "\n" + supplemental;
98 }
99 mOwner.setText(owner);
101 final String verifier = mSiteIdentity.getVerifier();
102 final String encrypted = mSiteIdentity.getEncrypted();
103 mVerifier.setText(verifier + "\n" + encrypted);
105 mContent.setPadding(0, 0, 0, 0);
106 mIdentity.setVisibility(View.VISIBLE);
107 }
108 }
110 private void addMixedContentNotification(boolean blocked) {
111 // Remove any exixting mixed content notification.
112 removeMixedContentNotification();
113 mMixedContentNotification = new DoorHanger(mActivity, DoorHanger.Theme.DARK);
115 String message;
116 if (blocked) {
117 message = mActivity.getString(R.string.blocked_mixed_content_message_top) + "\n\n" +
118 mActivity.getString(R.string.blocked_mixed_content_message_bottom);
119 } else {
120 message = mActivity.getString(R.string.loaded_mixed_content_message);
121 }
122 mMixedContentNotification.setMessage(message);
123 mMixedContentNotification.addLink(mActivity.getString(R.string.learn_more), MIXED_CONTENT_SUPPORT_URL, "\n\n");
125 if (blocked) {
126 mMixedContentNotification.setIcon(R.drawable.shield_doorhanger);
127 mMixedContentNotification.addButton(mActivity.getString(R.string.disable_protection),
128 "disable", mButtonClickListener);
129 mMixedContentNotification.addButton(mActivity.getString(R.string.keep_blocking),
130 "keepBlocking", mButtonClickListener);
131 } else {
132 mMixedContentNotification.setIcon(R.drawable.warning_doorhanger);
133 mMixedContentNotification.addButton(mActivity.getString(R.string.enable_protection),
134 "enable", mButtonClickListener);
135 }
137 mContent.addView(mMixedContentNotification);
138 }
140 private void removeMixedContentNotification() {
141 if (mMixedContentNotification != null) {
142 mContent.removeView(mMixedContentNotification);
143 mMixedContentNotification = null;
144 }
145 }
147 /*
148 * @param identityData A JSONObject that holds the current tab's identity data.
149 */
150 void setSiteIdentity(SiteIdentity siteIdentity) {
151 mSiteIdentity = siteIdentity;
152 }
154 @Override
155 public void show() {
156 if (mSiteIdentity == null) {
157 Log.e(LOGTAG, "Can't show site identity popup for undefined state");
158 return;
159 }
161 final SecurityMode mode = mSiteIdentity.getSecurityMode();
162 if (mode == SecurityMode.UNKNOWN) {
163 Log.e(LOGTAG, "Can't show site identity popup in non-identified state");
164 return;
165 }
167 updateUi();
169 if (mode == SecurityMode.MIXED_CONTENT_LOADED ||
170 mode == SecurityMode.MIXED_CONTENT_BLOCKED) {
171 addMixedContentNotification(mode == SecurityMode.MIXED_CONTENT_BLOCKED);
172 }
174 super.show();
175 }
177 @Override
178 public void dismiss() {
179 super.dismiss();
180 removeMixedContentNotification();
181 }
183 private class PopupButtonListener implements OnButtonClickListener {
184 @Override
185 public void onButtonClick(DoorHanger dh, String tag) {
186 try {
187 JSONObject data = new JSONObject();
188 data.put("allowMixedContent", tag.equals("disable"));
189 GeckoEvent e = GeckoEvent.createBroadcastEvent("Session:Reload", data.toString());
190 GeckoAppShell.sendEventToGecko(e);
191 } catch (JSONException e) {
192 Log.e(LOGTAG, "Exception creating message to enable/disable mixed content blocking", e);
193 }
195 dismiss();
196 }
197 }
198 }