Bug 1476220 - Show a "site information" header in the identity popup. r=paolo

Differential Revision: https://phabricator.services.mozilla.com/D7090

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Johann Hofmann 2018-10-09 13:47:13 +00:00
parent e7a0afe7cb
commit 3b6d09a99f
9 changed files with 121 additions and 133 deletions

View File

@ -115,15 +115,14 @@ var gIdentityHandler = {
delete this._identityPopupMainView;
return this._identityPopupMainView = document.getElementById("identity-popup-mainView");
},
get _identityPopupContentHosts() {
delete this._identityPopupContentHosts;
return this._identityPopupContentHosts =
[...document.querySelectorAll(".identity-popup-host")];
get _identityPopupMainViewHeaderLabel() {
delete this._identityPopupMainViewHeaderLabel;
return this._identityPopupMainViewHeaderLabel =
document.getElementById("identity-popup-mainView-panel-header-span");
},
get _identityPopupContentHostless() {
delete this._identityPopupContentHostless;
return this._identityPopupContentHostless =
[...document.querySelectorAll(".identity-popup-hostless")];
get _identityPopupContentHost() {
delete this._identityPopupContentHost;
return this._identityPopupContentHost = document.getElementById("identity-popup-host");
},
get _identityPopupContentOwner() {
delete this._identityPopupContentOwner;
@ -703,7 +702,6 @@ var gIdentityHandler = {
let verifier = "";
let host = "";
let owner = "";
let hostless = false;
try {
host = this.getEffectiveHost();
@ -711,16 +709,13 @@ var gIdentityHandler = {
// Some URIs might have no hosts.
}
if (this._pageExtensionPolicy) {
host = this._pageExtensionPolicy.name;
}
// Fallback for special protocols.
if (!host) {
host = this._uri.specIgnoringRef;
// Special URIs without a host (eg, about:) should crop the end so
// the protocol can be seen.
hostless = true;
}
if (this._pageExtensionPolicy) {
host = this._pageExtensionPolicy.name;
}
// Fill in the CA name if we have a valid TLS certificate.
@ -747,14 +742,9 @@ var gIdentityHandler = {
}
// Push the appropriate strings out to the UI.
this._identityPopupContentHosts.forEach((el) => {
el.textContent = host;
el.hidden = hostless;
});
this._identityPopupContentHostless.forEach((el) => {
el.setAttribute("value", host);
el.hidden = !hostless;
});
this._identityPopupMainViewHeaderLabel.textContent =
gNavigatorBundle.getFormattedString("identity.headerWithHost", [host]);
this._identityPopupContentHost.textContent = host;
this._identityPopupContentOwner.textContent = owner;
this._identityPopupContentSupp.textContent = supplemental;
this._identityPopupContentVerif.textContent = verifier;

View File

@ -1,16 +1,6 @@
/* Tests for correct behaviour of getEffectiveHost on identity handler */
function test() {
waitForExplicitFinish();
requestLongerTimeout(2);
ok(gIdentityHandler, "gIdentityHandler should exist");
BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", true).then(() => {
BrowserTestUtils.addContentEventListener(gBrowser.selectedBrowser, "load", checkResult, true);
nextTest();
});
}
requestLongerTimeout(2);
// Greek IDN for 'example.test'.
var idnDomain = "\u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1.\u03B4\u03BF\u03BA\u03B9\u03BC\u03AE";
@ -29,7 +19,6 @@ var tests = [
name: "normal HTTPS",
location: "https://example.com/",
effectiveHost: "example.com",
isHTTPS: true,
},
{
name: "IDN subdomain",
@ -45,13 +34,11 @@ var tests = [
name: "subdomain HTTPS",
location: "https://test1.example.com/",
effectiveHost: "test1.example.com",
isHTTPS: true,
},
{
name: "view-source HTTPS",
location: "view-source:https://example.com/",
effectiveHost: null,
isHTTPS: true,
},
{
name: "IP address",
@ -60,91 +47,73 @@ var tests = [
},
];
var gCurrentTest, gCurrentTestIndex = -1, gTestDesc, gPopupHidden;
// Go through the tests in both directions, to add additional coverage for
// transitions between different states.
var gForward = true;
var gCheckETLD = false;
function nextTest() {
if (!gCheckETLD) {
if (gForward)
gCurrentTestIndex++;
else
gCurrentTestIndex--;
add_task(async function test() {
ok(gIdentityHandler, "gIdentityHandler should exist");
if (gCurrentTestIndex == tests.length) {
// Went too far, reverse
gCurrentTestIndex--;
gForward = false;
}
await BrowserTestUtils.openNewForegroundTab(gBrowser);
if (gCurrentTestIndex == -1) {
gBrowser.removeCurrentTab();
finish();
return;
}
gCurrentTest = tests[gCurrentTestIndex];
gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + ")";
if (!gForward)
gTestDesc += " (second time)";
if (gCurrentTest.isHTTPS) {
gCheckETLD = true;
}
// Navigate to the next page, which will cause checkResult to fire.
let spec = gBrowser.selectedBrowser.currentURI.spec;
if (spec == "about:blank" || spec == gCurrentTest.location) {
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, gCurrentTest.location);
} else {
// Open the Control Center and make sure it closes after nav (Bug 1207542).
let popupShown = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
gPopupHidden = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
gIdentityHandler._identityBox.click();
info("Waiting for the Control Center to be shown");
popupShown.then(async () => {
ok(!BrowserTestUtils.is_hidden(gIdentityHandler._identityPopup), "Control Center is visible");
// Show the subview, which is an easy way in automation to reproduce
// Bug 1207542, where the CC wouldn't close on navigation.
let promiseViewShown = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "ViewShown");
gBrowser.ownerDocument.querySelector("#identity-popup-security-expander").click();
await promiseViewShown;
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, gCurrentTest.location);
});
}
} else {
gCheckETLD = false;
gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + " without eTLD in identity icon label)";
if (!gForward)
gTestDesc += " (second time)";
gBrowser.selectedBrowser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE |
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY);
for (let i = 0; i < tests.length; i++) {
await runTest(i, true);
}
}
function checkResult() {
if (gBrowser.selectedBrowser.currentURI.spec == "about:blank")
return;
gBrowser.removeCurrentTab();
await BrowserTestUtils.openNewForegroundTab(gBrowser);
for (let i = tests.length - 1; i >= 0; i--) {
await runTest(i, false);
}
gBrowser.removeCurrentTab();
});
async function runTest(i, forward) {
let currentTest = tests[i];
let testDesc = "#" + i + " (" + currentTest.name + ")";
if (!forward) {
testDesc += " (second time)";
}
info("Running test " + testDesc);
let popupHidden = null;
if ((forward && i > 0) || (!forward && i < tests.length - 1)) {
popupHidden = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
}
let loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, currentTest.location);
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, currentTest.location);
await loaded;
await popupHidden;
ok(BrowserTestUtils.is_hidden(gIdentityHandler._identityPopup), "Control Center is hidden");
// Sanity check other values, and the value of gIdentityHandler.getEffectiveHost()
is(gIdentityHandler._uri.spec, gCurrentTest.location, "location matches for test " + gTestDesc);
is(gIdentityHandler._uri.spec, currentTest.location, "location matches for test " + testDesc);
// getEffectiveHost can't be called for all modes
if (gCurrentTest.effectiveHost === null) {
if (currentTest.effectiveHost === null) {
let identityBox = document.getElementById("identity-box");
ok(identityBox.className == "unknownIdentity" ||
identityBox.className == "chromeUI", "mode matched");
} else {
is(gIdentityHandler.getEffectiveHost(), gCurrentTest.effectiveHost, "effectiveHost matches for test " + gTestDesc);
is(gIdentityHandler.getEffectiveHost(), currentTest.effectiveHost, "effectiveHost matches for test " + testDesc);
}
if (gPopupHidden) {
info("Waiting for the Control Center to hide");
gPopupHidden.then(() => {
gPopupHidden = null;
ok(BrowserTestUtils.is_hidden(gIdentityHandler._identityPopup), "Control Center is hidden");
executeSoon(nextTest);
});
} else {
executeSoon(nextTest);
}
// Open the Control Center and make sure it closes after nav (Bug 1207542).
let popupShown = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
gIdentityHandler._identityBox.click();
info("Waiting for the Control Center to be shown");
await popupShown;
ok(!BrowserTestUtils.is_hidden(gIdentityHandler._identityPopup), "Control Center is visible");
let displayedHost = currentTest.effectiveHost || currentTest.location;
ok(gIdentityHandler._identityPopupMainViewHeaderLabel.textContent.includes(displayedHost),
"identity UI header shows the host for test " + testDesc);
// Show the subview, which is an easy way in automation to reproduce
// Bug 1207542, where the CC wouldn't close on navigation.
let promiseViewShown = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "ViewShown");
gBrowser.ownerDocument.querySelector("#identity-popup-security-expander").click();
await promiseViewShown;
displayedHost = currentTest.effectiveHost || currentTest.location;
ok(gIdentityHandler._identityPopupContentHost.textContent.includes(displayedHost),
"security subview header shows the host for test " + testDesc);
}

View File

@ -15,12 +15,17 @@
mainViewId="identity-popup-mainView">
<panelview id="identity-popup-mainView"
descriptionheightworkaround="true">
<vbox id="identity-popup-mainView-panel-header">
<label>
<html:span id="identity-popup-mainView-panel-header-span"/>
</label>
</vbox>
<!-- Security Section -->
<hbox id="identity-popup-security" class="identity-popup-section">
<vbox class="identity-popup-security-content" flex="1">
<label class="plain">
<label class="identity-popup-headline identity-popup-host"></label>
<label class="identity-popup-headline identity-popup-hostless" crop="end"/>
<label class="identity-popup-headline">&identity.connection;</label>
</label>
<description class="identity-popup-connection-not-secure"
when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecure;</description>
@ -165,8 +170,7 @@
descriptionheightworkaround="true">
<vbox class="identity-popup-security-content">
<label class="plain">
<label class="identity-popup-headline identity-popup-host"></label>
<label class="identity-popup-headline identity-popup-hostless" crop="end"/>
<label class="identity-popup-headline" id="identity-popup-host"></label>
</label>
<description class="identity-popup-connection-not-secure"
when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecure;</description>

View File

@ -786,6 +786,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
This is the header of the security subview in the Site Identity panel. -->
<!ENTITY identity.securityView.label "Site Security">
<!ENTITY identity.connection "Connection">
<!ENTITY identity.connectionSecure "Secure Connection">
<!ENTITY identity.connectionNotSecure "Connection Is Not Secure">
<!ENTITY identity.connectionFile "This page is stored on your computer.">

View File

@ -490,6 +490,9 @@ webauthn.anonymize=Anonymize anyway
# Spoof Accept-Language prompt
privacy.spoof_english=Changing your language setting to English will make you more difficult to identify and enhance your privacy. Do you want to request English language versions of web pages?
# LOCALIZATION NOTE (identity.headerWithHost):
# %S is the hostname of the site that is being displayed.
identity.headerWithHost=Site Information for %S
identity.identified.verifier=Verified by: %S
identity.identified.verified_by_you=You have added a security exception for this site.
identity.identified.state_and_country=%S, %S

View File

@ -3,8 +3,6 @@
* 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/. */
%endif
%filter substitution
%define identityPopupExpanderWidth 38px
/* Hide all conditional elements by default. */
:-moz-any([when-connection],[when-mixedcontent],[when-ciphers],[when-loginforms]) {
@ -74,7 +72,7 @@
max-width: 33em;
}
.identity-popup-section:not(:first-child) {
.identity-popup-section {
border-top: 1px solid var(--panel-separator-color);
}
@ -105,7 +103,7 @@
margin: 0;
padding: 4px 0;
min-width: auto;
width: @identityPopupExpanderWidth@;
width: 38px;
border-style: none;
-moz-appearance: none;
background: url("chrome://browser/skin/arrow-left.svg") center no-repeat;
@ -147,6 +145,9 @@
/* CONTENT */
#identity-popup-mainView-panel-header > label,
#identity-popup-securityView > .panel-header,
#identity-popup-breakageReportView > .panel-header,
#identity-popup-content-blocking-report-breakage,
#identity-popup-content-blocking-disabled-label,
.identity-popup-content-blocking-category-label,
@ -163,6 +164,23 @@
margin: 0;
}
#identity-popup-mainView-panel-header {
padding: 4px 1em;
min-height: 40px;
-moz-box-pack: center;
-moz-box-align: center;
}
#identity-popup-mainView-panel-header-span {
display: inline-block;
font-weight: 600;
text-align: center;
overflow-wrap: break-word;
/* This is needed for the overflow-wrap to work correctly.
* 33em is the panel width, panel-header has 1em padding on each side. */
max-width: calc(33rem - 2em);
}
#identity-popup-permissions-content > description,
#identity-popup-content-blocking-content > description {
color: var(--panel-disabled-color);
@ -178,11 +196,12 @@
font-size: 150%;
}
.identity-popup-host {
word-wrap: break-word;
/* 1em + 2em + 24px is .identity-popup-security-content padding
* 30em is the panel width */
max-width: calc(30rem - 3rem - 24px - @identityPopupExpanderWidth@);
#identity-popup-host {
overflow-wrap: break-word;
/* This is needed for the overflow-wrap to work correctly.
* 1em + 2em + 24px is .identity-popup-security-content padding
* 33em is the panel width */
max-width: calc(33rem - 3rem - 24px);
}
.identity-popup-warning-gray {

View File

@ -41,7 +41,7 @@ class TestDVCertificate(PuppeteerMixin, MarionetteTestCase):
cert = self.browser.tabbar.selected_tab.certificate
# The shown host equals to the certificate
self.assertRegexpMatches(self.identity_popup.view.main.host.get_property('textContent'),
self.assertRegexpMatches(self.identity_popup.view.main.header.get_property('textContent'),
'.*badssl\.com$')
self.assertRegexpMatches(cert['commonName'], '.*badssl\.com$')

View File

@ -50,8 +50,10 @@ class TestEVCertificate(PuppeteerMixin, MarionetteTestCase):
self.assertEqual(self.identity_popup.element.get_attribute('connection'), 'secure-ev')
# For EV certificates no hostname but the organization name is shown
self.assertEqual(self.identity_popup.view.main.host.get_property('textContent'),
cert['organization'])
l10n_header = self.browser.localize_property('identity.headerWithHost')
l10n_header = l10n_header.replace('%S', cert['organization'])
self.assertEqual(self.identity_popup.view.main.header.get_property('textContent'),
l10n_header)
# Only the secure label is visible in the main view
secure_label = self.identity_popup.view.main.secure_connection_label

View File

@ -524,12 +524,12 @@ class IdentityPopupMainView(IdentityPopupView):
return self.element.find_element(By.CLASS_NAME, 'identity-popup-expander')
@property
def host(self):
"""The DOM element which represents the identity-popup content host.
def header(self):
"""The DOM element which represents the identity-popup header.
:returns: Reference to the identity-popup content host.
:returns: Reference to the identity-popup header.
"""
return self.element.find_element(By.CLASS_NAME, 'identity-popup-host')
return self.element.find_element(By.ID, 'identity-popup-mainView-panel-header-span')
@property
def insecure_connection_label(self):
@ -590,7 +590,7 @@ class IdentityPopupSecurityView(IdentityPopupView):
:returns: Reference to the identity-popup content host.
"""
return self.element.find_element(By.CLASS_NAME, 'identity-popup-host')
return self.element.find_element(By.ID, 'identity-popup-host')
@property
def insecure_connection_label(self):