Relanding bug 383183: include an identity indicator in primary chrome, patch by Johnathan Nightingale <johnath@mozilla.com>, r=mconnor, r=me

This commit is contained in:
gavin@gavinsharp.com 2007-09-03 17:42:41 -07:00
Родитель 5e2a2c1ee3
Коммит 692f748626
10 изменённых файлов: 460 добавлений и 122 удалений

Просмотреть файл

@ -3698,9 +3698,8 @@ nsBrowserStatusHandler.prototype =
var securityUI = gBrowser.securityUI;
this.securityButton.setAttribute("tooltiptext", securityUI.tooltipText);
var lockIcon = document.getElementById("lock-icon");
if (lockIcon)
lockIcon.setAttribute("tooltiptext", securityUI.tooltipText);
getIdentityHandler().checkIdentity(aWebProgress, aRequest, aState);
},
// simulate all change notifications after switching tabs
@ -5583,3 +5582,172 @@ function showToolbars() {
return false; // Dismiss the notification message
}
/**
* Utility class to handle manipulations of the identity indicators in the UI
*/
function IdentityHandler() {}
IdentityHandler.prototype = {
// Mode strings used to control CSS display
IDENTITY_MODE_IDENTIFIED : "verifiedIdentity", // High-quality identity information
IDENTITY_MODE_DOMAIN_VERIFIED : "verifiedDomain", // Minimal SSL CA-signed domain verification
IDENTITY_MODE_UNKNOWN : "unknownIdentity", // No trusted identity information
/**
* Handler for mouseclicks on the "Tell me more about this website" link text
* in the "identity-popup" panel.
*/
handleMoreInfoClick : function(event) {
if (event.button == 0) {
displaySecurityInfo();
event.stopPropagation();
}
},
/**
* Determine the identity of the page being displayed by examining its SSL cert
* (if available) and, if necessary, update the UI to reflect this. Intended to
* be called by an nsIWebProgressListener.
*
* @param nsIWebProgress webProgress
* @param nsIRequest request
* @param PRUint32 state
*/
checkIdentity : function(webProgress, request, state) {
if (state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL)
this.setMode(this.IDENTITY_MODE_IDENTIFIED);
else if (state & Components.interfaces.nsIWebProgressListener.STATE_SECURE_HIGH)
this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED);
else
this.setMode(this.IDENTITY_MODE_UNKNOWN);
},
/**
* Update the UI to reflect the specified mode, which should be one of the
* IDENTITY_MODE_* constants.
*/
setMode : function(newMode) {
document.getElementById("identity-popup").className = newMode;
document.getElementById("identity-box").className = newMode;
document.getElementById("identity-popup-content-box").className = newMode;
this.setMessages(newMode);
},
/**
* Set up the title and content messages for the identity message bubble, based
* on the specified mode.
*
* @param newMode The newly set identity mode. Should be one of the IDENTITY_MODE_* constants.
*/
setMessages : function(newMode) {
var stringBundle = document.getElementById("bundle_browser");
var brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
// Initialize the optional strings to empty values
var supplemental = "";
var verifier = "";
var icon_label = "";
if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
var title = stringBundle.getString("identity.domainverified.title");
var encryption_label = stringBundle.getString("identity.encrypted");
var status = gBrowser.securityUI
.QueryInterface(Components.interfaces.nsISSLStatusProvider)
.SSLStatus.QueryInterface(Components.interfaces.nsISSLStatus);
var cert = status.serverCert;
// It would be sort of nice to use the CN= field in the cert, since that's
// typically what we want here, but thanks to x509 certs being extensible,
// it's not the only place you have to check, there can be more than one domain,
// et cetera, ad nauseum. We know the cert is valid for location.host, so
// let's just use that, it's what the status bar does too.
var body = icon_label = gBrowser.contentWindow.location.host;
var caOrg = cert.issuerOrganization || cert.issuerCommonName;
verifier = stringBundle.getFormattedString("identity.identified.verifier",
[caOrg]);
var tooltip = verifier;
supplemental = stringBundle.getString("identity.domainverified.supplemental");
}
else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
title = stringBundle.getString("identity.identified.title");
encryption_label = stringBundle.getString("identity.encrypted");
// If it's identified, then we can populate the dialog with credentials
status = gBrowser.securityUI
.QueryInterface(Components.interfaces.nsISSLStatusProvider)
.SSLStatus.QueryInterface(Components.interfaces.nsISSLStatus);
cert = status.serverCert;
// Pull the basics out with fallback options in case common
// (optional) fields are left blank
body = cert.organization || cert.commonName;
caOrg = cert.issuerOrganization || cert.issuerCommonName;
verifier = stringBundle.getFormattedString("identity.identified.verifier",
[caOrg]);
tooltip = verifier;
// Now try to extract out supplemental location fields and append
// them, where available. subjectName is a comma-delimited list of
// key=value pairs.
if (cert.subjectName) {
var subjectNameFields = {};
cert.subjectName.split(",").forEach(function(v) {
var field = v.split("=");
this[field[0]] = field[1];
}, subjectNameFields);
if (subjectNameFields.L) // City
supplemental += subjectNameFields.L + "\n";
if (subjectNameFields.ST && subjectNameFields.C) // State and Country
supplemental += stringBundle.getFormattedString("identity.identified.state_and_country",
[subjectNameFields.ST,
subjectNameFields.C]);
else if (subjectNameFields.ST) // State only
supplemental += subjectNameFields.ST;
else if (subjectNameFields.C) // Country only
supplemental += subjectNameFields.C;
// Include country code in top-level label, if we have one
if (subjectNameFields.C)
icon_label = stringBundle.getFormattedString("identity.identified.title_with_country",
[body, subjectNameFields.C]);
else
icon_label = body;
}
}
else {
encryption_label = stringBundle.getString("identity.unencrypted");
title = stringBundle.getString("identity.unknown.title");
body = stringBundle.getFormattedString("identity.unknown.body", [brandShortName], 1);
tooltip = body;
}
// Push the appropriate strings out to the UI
document.getElementById("identity-popup-title").value = title;
document.getElementById("identity-popup-content").textContent = body;
document.getElementById("identity-popup-content-supplemental")
.textContent = supplemental;
document.getElementById("identity-popup-content-verifier")
.textContent = verifier;
document.getElementById("identity-box").tooltipText = tooltip;
document.getElementById("identity-icon-label").value = icon_label;
document.getElementById("identity-popup-encryption-label")
.textContent = encryption_label;
}
};
var gIdentityHandler;
/**
* Returns the singleton instance of the identity handler class. Should always be
* used instead of referencing the global variable directly or creating new instances
*/
function getIdentityHandler() {
if (!gIdentityHandler)
gIdentityHandler = new IdentityHandler();
return gIdentityHandler;
}

Просмотреть файл

@ -28,6 +28,7 @@
# Joe Hewitt <hewitt@netscape.com>
# Pierre Chanial <chanial@noos.fr>
# Dean Tessman <dean_tessman@hotmail.com>
# Johnathan Nightingale <johnath@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -136,6 +137,34 @@
<popup id="placesContext"/>
<!-- Popup for site identity information -->
<panel id="identity-popup" position="after_start">
<hbox id="identity-popup-container" align="top">
<image id="identity-popup-icon"/>
<vbox id="identity-popup-content-box">
<!-- Title Bar -->
<label id="identity-popup-title"/>
<!-- Content area -->
<description id="identity-popup-content"/>
<description id="identity-popup-content-supplemental"/>
<description id="identity-popup-content-verifier"/>
<hbox id="identity-popup-encryption" flex="1">
<vbox>
<image id="identity-popup-encryption-icon"/>
<spacer flex="1"/>
</vbox>
<description id="identity-popup-encryption-label" flex="1"/>
</hbox>
<spacer flex="1"/>
<!-- Footer link to page info -->
<label id="identity-popup-more-info-link"
class="text-link plain"
value="&identity.moreInfoLinkText;"
onclick="getIdentityHandler().handleMoreInfoClick(event);"/>
</vbox>
</hbox>
</panel>
<tooltip id="urlTooltip">
<label crop="center" flex="1"/>
</tooltip>
@ -231,19 +260,27 @@
oninput="gBrowser.userTypedValue = this.value"
ontextentered="return handleURLBarCommand(param);"
ontextreverted="return handleURLBarRevert();">
<deck id="page-proxy-deck" onclick="PageProxyClickHandler(event);">
<image id="page-proxy-button"
ondraggesture="PageProxyDragGesture(event);"
tooltiptext="&proxyIcon.tooltip;"/>
<image id="page-proxy-favicon" validate="never"
ondraggesture="PageProxyDragGesture(event);"
onload="this.parentNode.selectedIndex = 1;
event.stopPropagation();"
onerror="gBrowser.addToMissedIconCache(this.src);
this.removeAttribute('src');
this.parentNode.selectedIndex = 0;"
tooltiptext="&proxyIcon.tooltip;"/>
</deck>
<!-- Use onmouseup instead of normal popup= syntax since the popup
code fires onmousedown, and hence eats our favicon drag events -->
<box id="identity-box" align="center"
onmouseup="if (event.button == 0)
document.getElementById('identity-popup')
.openPopup(document.getElementById('identity-box'), 'after_start');">
<deck id="page-proxy-deck" onclick="PageProxyClickHandler(event);">
<image id="page-proxy-button"
ondraggesture="PageProxyDragGesture(event);"
tooltiptext="&proxyIcon.tooltip;"/>
<image id="page-proxy-favicon" validate="never"
ondraggesture="PageProxyDragGesture(event);"
onload="this.parentNode.selectedIndex = 1;
event.stopPropagation();"
onerror="gBrowser.addToMissedIconCache(this.src);
this.removeAttribute('src');
this.parentNode.selectedIndex = 0;"
tooltiptext="&proxyIcon.tooltip;"/>
</deck>
<label id="identity-icon-label"/>
</box>
<hbox id="urlbar-icons">
<button type="menu"
style="-moz-user-focus: none"
@ -256,7 +293,6 @@
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"/>
</button>
<image id="lock-icon" onclick="if (event.button == 0) displaySecurityInfo(); event.stopPropagation();"/>
#ifdef MOZ_SAFE_BROWSING
<image id="safebrowsing-urlbar-icon" tooltiptext="&safeb.urlbaricon.tooltip;"
level="safe"

Просмотреть файл

@ -46,7 +46,7 @@
<binding id="urlbar" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
<content sizetopopup="pref">
<xul:hbox class="autocomplete-textbox-container" flex="1">
<children includes="image|deck|stack">
<children includes="image|deck|stack|box">
<xul:image class="autocomplete-icon" allowevents="true"/>
</children>

Просмотреть файл

@ -208,7 +208,6 @@ PROT_PhishMsgDisplayerBase.prototype.browserSelected = function() {
this.messageShouldShow_ = true;
}
this.hideLockIcon_(); // Comes back when we are unselected or unloaded
this.addWarningInUrlbar_(); // Goes away when we are unselected or unloaded
// messageShouldShow might be false if the user dismissed the warning,
@ -234,7 +233,6 @@ PROT_PhishMsgDisplayerBase.prototype.explicitShow = function() {
*/
PROT_PhishMsgDisplayerBase.prototype.browserUnselected = function() {
this.removeWarningInUrlbar_();
this.unhideLockIcon_();
if (this.messageShowing_)
this.hideMessage_();
}
@ -290,7 +288,6 @@ PROT_PhishMsgDisplayerBase.prototype.done = function() {
// If we were started, we must be the current problem, so these things
// must be showing
this.removeWarningInUrlbar_();
this.unhideLockIcon_();
// Could be though that they've closed the warning dialog
if (this.messageShowing_)
@ -327,28 +324,6 @@ PROT_PhishMsgDisplayerBase.prototype.removeIfExists_ = function(orig,
return orig;
}
/**
* We don't want to confuse users if they land on a phishy page that uses
* SSL, so ensure that the lock icon never shows when we're showing our
* warning.
*/
PROT_PhishMsgDisplayerBase.prototype.hideLockIcon_ = function() {
var lockIcon = this.doc_.getElementById("lock-icon");
if (!lockIcon)
return;
lockIcon.hidden = true;
}
/**
* Ensure they can see it after our warning is finished.
*/
PROT_PhishMsgDisplayerBase.prototype.unhideLockIcon_ = function() {
var lockIcon = this.doc_.getElementById("lock-icon");
if (!lockIcon)
return;
lockIcon.hidden = false;
}
/**
* This method makes our warning icon visible in the location bar. It will
* be removed only when the problematic document is navigated awy from

Просмотреть файл

@ -350,3 +350,5 @@
<!ENTITY editBookmark.done.label "Done">
<!ENTITY editBookmark.delete.label "Delete">
<!ENTITY identity.moreInfoLinkText "Tell me more about this web site...">

Просмотреть файл

@ -97,3 +97,20 @@ chromelessWindow.warningMessage=The web site at %S has hidden your toolbars.
chromelessWindow.warningNoLocation=This web site has hidden your toolbars.
chromelessWindow.showToolbarsButton=Show Toolbars
chromelessWindow.accessKey=S
# Identity information
identity.domainverified.title=Location Verified
identity.domainverified.body=You are currently visiting:
identity.domainverified.supplemental=Information identifying the owner of this site may not have been validated.
identity.identified.title=Identity Verified
identity.identified.body=This website is owned by:
identity.identified.verifier=Verified by: %S
identity.identified.state_and_country=%S, %S
identity.identified.title_with_country=%S (%S)
identity.unknown.title=Identity Unknown
identity.unknown.body=This web site does not supply identity information.
identity.encrypted=Your connection to this web site is encrypted to prevent eavesdropping.
identity.unencrypted=Your connection to this web site is not encrypted.

Просмотреть файл

@ -827,7 +827,7 @@ toolbar[iconsize="small"] #paste-button:hover:active {
#urlbar {
margin-top: 5px;
margin-bottom: 5px;
-moz-margin-start: 4px;
-moz-margin-start: 0px;
-moz-margin-end: 0px;
width: 7em;
min-width: 7em;
@ -879,46 +879,6 @@ toolbar[iconsize="small"] #paste-button:hover:active {
background: url("chrome://browser/skin/Secure-background.gif") #FFFED8 repeat-x;
}
#urlbar #lock-icon {
height: 18px;
margin: -1px;
}
#urlbar[level="high"] #lock-icon {
list-style-image: url("chrome://browser/skin/Secure.png");
-moz-image-region: rect(0px, 18px, 18px, 0px);
}
#urlbar[level="high"] #lock-icon:hover {
-moz-image-region: rect(18px, 18px, 36px, 0px);
}
#urlbar[level="high"] #lock-icon:active {
-moz-image-region: rect(36px, 18px, 54px, 0px);
}
#urlbar[level="low"] #lock-icon {
list-style-image: url("chrome://browser/skin/Secure.png");
-moz-image-region: rect(0px, 18px, 18px, 0px);
}
#urlbar[level="low"] #lock-icon:hover {
-moz-image-region: rect(18px, 18px, 36px, 0px);
}
#urlbar[level="low"] #lock-icon:active {
-moz-image-region: rect(36px, 18px, 54px, 0px);
}
#urlbar[level="broken"] #lock-icon {
list-style-image: url("chrome://browser/skin/Security-broken.png");
-moz-image-region: rect(0px, 18px, 18px, 0px);
}
#urlbar[level="broken"] #lock-icon:hover {
-moz-image-region: rect(18px, 18px, 36px, 0px);
}
#urlbar[level="broken"] #lock-icon:active {
-moz-image-region: rect(36px, 18px, 54px, 0px);
}
#urlbar-container {
-moz-padding-end: 5px;
}
@ -1703,3 +1663,116 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-border-left-colors: ThreeDLightShadow ThreeDHighlight !important;
}
/* ::::: Identity Indicator Styling ::::: */
/* Location bar visuals*/
#identity-box {
/* Extend our margins out so that our highlight/separator bar covers the
location bar properly */
margin: -1px 0 -2px;
padding: 1px 2px 2px 0;
border-right: 1px solid #888;
background-color: white;
opacity: 0.9;
}
#identity-box:hover {
opacity: 1.0;
}
#identity-box.verifiedIdentity {
background-color: #BFA;
}
#urlbar[level="high"] > #identity-box,
#urlbar[level="low"] > #identity-box {
/* urlbar adds padding when security level is set, which we need to
counteract here so that we still fill the background. */
margin: -2px;
padding: 1px 2px;
}
#identity-icon-label {
padding: 1px 2px 2px;
margin: 0;
color: black;
vertical-align: middle;
}
.unknownIdentity > #identity-icon-label {
display: none;
}
/* Popup Icons */
#identity-popup-icon {
height: 64px;
width: 64px;
padding: 0;
margin: 10px 0 0;
list-style-image: url("chrome://browser/skin/identity.png");
-moz-image-region: rect(0px, 64px, 64px, 0px);
}
.verifiedDomain > #identity-popup-container > #identity-popup-icon {
-moz-image-region: rect(64px, 64px, 128px, 0px);
}
.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
-moz-image-region: rect(128px, 64px, 192px, 0px);
}
/* Popup Title */
#identity-popup-title {
font-size: 120%;
font-weight: bold;
}
.verifiedIdentity > #identity-popup-title {
color: #6A6;
}
.unknownIdentity > #identity-popup-title {
color: #999;
}
.verifiedDomain > #identity-popup-title {
color: black;
}
/* Popup Body Text */
#identity-popup-content-box > description,
#identity-popup-encryption-label {
white-space: -moz-pre-wrap;
color: black;
padding-left: 10px;
}
#identity-popup-content {
padding-top: 5px;
margin-bottom: 0;
max-width: 200px;
}
.verifiedIdentity > #identity-popup-content,
.verifiedDomain > #identity-popup-content {
font-size: 140%;
font-weight: bold;
max-width: 300px;
}
#identity-popup-encryption {
margin: 10px 0;
}
.verifiedIdentity > #identity-popup-encryption > * > #identity-popup-encryption-icon,
.verifiedDomain > #identity-popup-encryption > * >#identity-popup-encryption-icon {
list-style-image: url("chrome://browser/skin/Secure.png");
-moz-image-region: rect(0px, 18px, 18px, 0px);
}
/* Popup Bounding Box */
#identity-popup-container {
background-image: none;
background-color: white;
min-width: 280px;
padding: 10px;
}

Просмотреть файл

@ -10,6 +10,7 @@ classic.jar:
skin/classic/browser/find.png
skin/classic/browser/find-bar-background.png
skin/classic/browser/Go.png
skin/classic/browser/identity.png
skin/classic/browser/Info.png
skin/classic/browser/page-livemarks.png
skin/classic/browser/livemark-item.png

Просмотреть файл

@ -850,7 +850,7 @@ toolbar[iconsize="small"] #paste-button:not([disabled="true"]):hover:active {
margin-bottom: 2px;
margin-top: 2px;
-moz-margin-end: 0px;
-moz-margin-start: 3px;
-moz-margin-start: 0px;
width: 7em;
min-width: 7em;
@ -1810,43 +1810,6 @@ toolbar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text {
color: #000000;
}
#urlbar[level="high"] #lock-icon {
-moz-image-region: rect(0px, 18px, 18px, 0px);
list-style-image: url("chrome://browser/skin/Secure.png");
}
#urlbar[level="high"] #lock-icon:hover {
-moz-image-region: rect(18px, 18px, 36px, 0px);
list-style-image: url("chrome://browser/skin/Secure.png");
}
#urlbar[level="high"] #lock-icon:active {
-moz-image-region: rect(36px, 18px, 54px, 0px);
list-style-image: url("chrome://browser/skin/Secure.png");
}
#urlbar[level="low"] #lock-icon {
-moz-image-region: rect(0px, 18px, 18px, 0px);
list-style-image: url("chrome://browser/skin/Secure.png");
}
#urlbar[level="low"] #lock-icon:hover {
-moz-image-region: rect(18px, 18px, 36px, 0px);
list-style-image: url("chrome://browser/skin/Secure.png");
}
#urlbar[level="low"] #lock-icon:active {
-moz-image-region: rect(36px, 18px, 54px, 0px);
list-style-image: url("chrome://browser/skin/Secure.png");
}
#urlbar[level="broken"] #lock-icon {
-moz-image-region: rect(0px, 18px, 18px, 0px);
list-style-image: url("chrome://browser/skin/Security-broken.png");
}
#urlbar[level="broken"] #lock-icon:hover {
-moz-image-region: rect(18px, 18px, 36px, 0px);
list-style-image: url("chrome://browser/skin/Security-broken.png");
}
#urlbar[level="broken"] #lock-icon:active {
-moz-image-region: rect(36px, 18px, 54px, 0px);
list-style-image: url("chrome://browser/skin/Security-broken.png");
}
%ifdef MOZ_WIDGET_GTK2
#urlbar > .autocomplete-textbox-container {
-moz-binding: url(chrome://browser/skin/browser.xml#autocomplete-security-wrapper);
@ -1959,3 +1922,105 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
.bookmark-item[dragover-bottom="true"] {
-moz-border-bottom-colors: #000000;
}
/* ::::: Identity Indicator Styling ::::: */
/* Location bar visuals*/
#identity-box {
border-right: 1px solid #888;
background-color: white;
opacity: 0.9;
}
#identity-box:hover {
opacity: 1.0;
}
#identity-box.verifiedIdentity {
background-color: #BFA;
}
#identity-icon-label {
padding: 1px 2px 2px;
margin: 0;
color: black;
vertical-align: middle;
}
.unknownIdentity > #identity-icon-label {
display: none;
}
/* Popup Icons */
#identity-popup-icon {
height: 64px;
width: 64px;
padding: 0;
margin: 10px 0 0;
list-style-image: url("chrome://browser/skin/identity.png");
-moz-image-region: rect(0px, 64px, 64px, 0px);
}
.verifiedDomain > #identity-popup-container > #identity-popup-icon {
-moz-image-region: rect(64px, 64px, 128px, 0px);
}
.verifiedIdentity > #identity-popup-container > #identity-popup-icon {
-moz-image-region: rect(128px, 64px, 192px, 0px);
}
/* Popup Title */
#identity-popup-title {
font-size: 120%;
font-weight: bold;
}
.verifiedIdentity > #identity-popup-title {
color: #6A6;
}
.unknownIdentity > #identity-popup-title {
color: #999;
}
.verifiedDomain > #identity-popup-title {
color: black;
}
/* Popup Body Text */
#identity-popup-content-box > description,
#identity-popup-encryption-label {
white-space: -moz-pre-wrap;
color: black;
padding-left: 10px;
}
#identity-popup-content {
padding-top: 5px;
margin-bottom: 0;
max-width: 200px;
}
.verifiedIdentity > #identity-popup-content,
.verifiedDomain > #identity-popup-content {
font-size: 140%;
font-weight: bold;
max-width: 300px;
}
#identity-popup-encryption {
margin: 10px 0;
}
.verifiedIdentity > #identity-popup-encryption > * > #identity-popup-encryption-icon,
.verifiedDomain > #identity-popup-encryption > * >#identity-popup-encryption-icon {
list-style-image: url("chrome://browser/skin/Secure.png");
-moz-image-region: rect(0px, 18px, 18px, 0px);
}
/* Popup Bounding Box */
#identity-popup-container {
background-image: none;
background-color: white;
min-width: 280px;
padding: 10px;
}

Просмотреть файл

@ -4,6 +4,7 @@ classic.jar:
skin/classic/browser/browser.xml
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/Info.png
skin/classic/browser/identity.png
skin/classic/browser/pageInfo.css
skin/classic/browser/pageInfo.png
skin/classic/browser/page-livemarks.png