From 192f439808de36171eae8cd64bdaaba5065e12b2 Mon Sep 17 00:00:00 2001 From: "gavin%gavinsharp.com" Date: Wed, 5 Sep 2007 20:24:44 +0000 Subject: [PATCH] Relanding bug 383183 with some additional perf fixes: include an identity indicator in primary chrome, patch by Johnathan Nightingale , r=me git-svn-id: svn://10.0.0.236/trunk@233966 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/browser/base/content/browser.js | 203 +++++++++++++++++- mozilla/browser/base/content/browser.xul | 62 ++++-- .../browser/base/content/urlbarBindings.xml | 2 +- .../content/phishing-afterload-displayer.js | 25 --- .../locales/en-US/chrome/browser/browser.dtd | 2 + .../en-US/chrome/browser/browser.properties | 17 ++ .../themes/pinstripe/browser/browser.css | 155 +++++++++---- .../browser/themes/pinstripe/browser/jar.mn | 1 + .../themes/winstripe/browser/browser.css | 141 ++++++++---- .../browser/themes/winstripe/browser/jar.mn | 1 + 10 files changed, 487 insertions(+), 122 deletions(-) diff --git a/mozilla/browser/base/content/browser.js b/mozilla/browser/base/content/browser.js index 91091fb15bc..32927ae18b0 100644 --- a/mozilla/browser/base/content/browser.js +++ b/mozilla/browser/base/content/browser.js @@ -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,201 @@ 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 + + // Cache the most recently seen SSLStatus and URI to prevent unnecessary updates + _lastStatus : null, + _lastURI : null, + + /** + * 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) { + var currentStatus = gBrowser.securityUI + .QueryInterface(Components.interfaces.nsISSLStatusProvider) + .SSLStatus; + var currentURI = gBrowser.currentURI; + if (currentStatus == this._lastStatus && currentURI == this._lastURI) { + // No need to update, this is a no-op check + return; + } + + this._lastStatus = currentStatus; + this._lastURI = currentURI; + + 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, and + * primary UI based on the specified mode, and the details of the SSL cert, where + * applicable + * + * @param newMode The newly set identity mode. Should be one of the IDENTITY_MODE_* constants. + */ + setMessages : function(newMode) { + + var stringBundle = document.getElementById("bundle_browser"); + + // Initialize the optional strings to empty values + var supplemental = ""; + var verifier = ""; + + if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) { + var title = stringBundle.getString("identity.domainverified.title"); + var encryption_label = stringBundle.getString("identity.encrypted"); + var status = this._lastStatus.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 = this._lastURI.host; + var caOrg = cert.issuerOrganization || cert.issuerCommonName; + verifier = stringBundle.getFormattedString("identity.identified.verifier", + [caOrg]); + supplemental = stringBundle.getString("identity.domainverified.supplemental"); + + var icon_label = body; + var tooltip = verifier; + } + 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 = this._lastStatus.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 = tooltip = stringBundle.getFormattedString("identity.identified.verifier", + [caOrg]); + + // 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.getString("identity.unknown.body"); + icon_label = ""; + 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-popup-encryption-label") + .textContent = encryption_label; + document.getElementById("identity-box").tooltipText = tooltip; + document.getElementById("identity-icon-label").value = icon_label; + }, + + /** + * Click handler for the identity-box element in primary chrome. + */ + handleMouseUp : function(event) { + if (event.button != 0) + return; // We only want left-clicks + + // Make sure that the display:none style we set in xul is removed now that + // the popup is actually needed + var popup = document.getElementById('identity-popup'); + popup.hidden = false; + + // Now open the popup, anchored off the primary chrome element + popup.openPopup(document.getElementById('identity-box'), 'after_start'); + } +}; + +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; +} diff --git a/mozilla/browser/base/content/browser.xul b/mozilla/browser/base/content/browser.xul index f6e162cfb77..066844cb2f8 100644 --- a/mozilla/browser/base/content/browser.xul +++ b/mozilla/browser/base/content/browser.xul @@ -28,6 +28,7 @@ # Joe Hewitt # Pierre Chanial # Dean Tessman +# Johnathan Nightingale # # 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 @@ + + + @@ -231,19 +260,25 @@ oninput="gBrowser.userTypedValue = this.value" ontextentered="return handleURLBarCommand(param);" ontextreverted="return handleURLBarRevert();"> - - - - + + + + + + + - #ifdef MOZ_SAFE_BROWSING - + diff --git a/mozilla/browser/components/safebrowsing/content/phishing-afterload-displayer.js b/mozilla/browser/components/safebrowsing/content/phishing-afterload-displayer.js index a0b3ecf3398..09aa7d803f2 100644 --- a/mozilla/browser/components/safebrowsing/content/phishing-afterload-displayer.js +++ b/mozilla/browser/components/safebrowsing/content/phishing-afterload-displayer.js @@ -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 diff --git a/mozilla/browser/locales/en-US/chrome/browser/browser.dtd b/mozilla/browser/locales/en-US/chrome/browser/browser.dtd index 436fe645135..ab572e4bb24 100644 --- a/mozilla/browser/locales/en-US/chrome/browser/browser.dtd +++ b/mozilla/browser/locales/en-US/chrome/browser/browser.dtd @@ -350,3 +350,5 @@ + + diff --git a/mozilla/browser/locales/en-US/chrome/browser/browser.properties b/mozilla/browser/locales/en-US/chrome/browser/browser.properties index a0d47a1a7fb..139d93e8f36 100644 --- a/mozilla/browser/locales/en-US/chrome/browser/browser.properties +++ b/mozilla/browser/locales/en-US/chrome/browser/browser.properties @@ -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. diff --git a/mozilla/browser/themes/pinstripe/browser/browser.css b/mozilla/browser/themes/pinstripe/browser/browser.css index 5905ee37da7..7fea759f9ba 100755 --- a/mozilla/browser/themes/pinstripe/browser/browser.css +++ b/mozilla/browser/themes/pinstripe/browser/browser.css @@ -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; } @@ -1697,3 +1657,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; +} diff --git a/mozilla/browser/themes/pinstripe/browser/jar.mn b/mozilla/browser/themes/pinstripe/browser/jar.mn index 8a6e1d947e1..fd5ae792a55 100644 --- a/mozilla/browser/themes/pinstripe/browser/jar.mn +++ b/mozilla/browser/themes/pinstripe/browser/jar.mn @@ -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 diff --git a/mozilla/browser/themes/winstripe/browser/browser.css b/mozilla/browser/themes/winstripe/browser/browser.css index be1451ea1b2..a32c11c97eb 100644 --- a/mozilla/browser/themes/winstripe/browser/browser.css +++ b/mozilla/browser/themes/winstripe/browser/browser.css @@ -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; @@ -1804,43 +1804,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); @@ -1953,3 +1916,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; +} diff --git a/mozilla/browser/themes/winstripe/browser/jar.mn b/mozilla/browser/themes/winstripe/browser/jar.mn index 3748f3b0cb7..3b0d5030095 100644 --- a/mozilla/browser/themes/winstripe/browser/jar.mn +++ b/mozilla/browser/themes/winstripe/browser/jar.mn @@ -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